2016-04-06 6 views
2

Ich habe eine Methode namens calcDays(), die eine Datenbank immer wieder durchläuft, bis eine bestimmte Bedingung erfüllt ist. Das Problem ist, dass Android Studio mir sagt, dass ich keine Dateien mehr habe. Ich merke, dass ich Datenbanken öffne und sie nicht schließe, weshalb ich den Fehler habe. Allerdings kann ich diesen Fehler nicht beheben.Anwendung hat zu viele Dateien Öffnen - Android

Klasse mit calcDays() -Methode

package com.example.brandon.netflixcalculator; 

import android.app.Activity; 
import android.app.AlertDialog; 
import android.content.Intent; 
import android.database.Cursor; 
import android.database.sqlite.SQLiteDatabase; 
import android.support.v7.app.AppCompatActivity; 
import android.os.Bundle; 
import android.view.View; 
import android.widget.Button; 
import android.widget.EditText; 
import android.widget.TextView; 
import android.widget.Toast; 

import java.io.BufferedReader; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.sql.SQLException; 
import java.util.Calendar; 

public class MainActivity extends Activity { 

    private Button b1; 
    private Button b2; 
    private Button b3; 
    private Button b4; 
    private TextView daysRemaining, showName;; 
    private int x; 
    private int[] dailyMin = new int[7]; 
    private String[] dailyPercent = {"100%", "75%", "50%", "25%", "0%"}; 
    private double[] percent = {1, .75, .5, .25, 0}; 
    private DatabaseHelper db; 
    String[] stringDays = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"}; 
    private File viewingInfo; 


    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     setOnButton1ClickListener(); 
     setOnButton2ClickListener(); 
     setOnButton3ClickListener(); 
     setOnButton4ClickListener(); 
     daysRemaining = (TextView)findViewById(R.id.textViewRemainingDays); 
     showName = (TextView)findViewById(R.id.textViewCurrentShow); 
     if(!ifFileExists()){ 
      createDBFirstTime(); 
     } 
     else{ 
      db = new DatabaseHelper(getApplicationContext()); 
      daysRemaining.setText(String.valueOf(calcDays())); 
      showName.setText(db.getShowName()); 
     } 
    } 

    public void createDBFirstTime(){ 
     System.out.println("Database deleted? " + this.deleteDatabase("viewing_database")); 
     db = new DatabaseHelper(this.getApplicationContext()); 
     for(int i = 0; i < stringDays.length; i++){ 
      db.insertDataViewing(stringDays[i], 0, "100%"); 
     } 
     db.insertDataShow("N/A", 0, 0, 0); 
     try { 
      FileOutputStream fos = openFileOutput("madeDB", MODE_PRIVATE); 
      try { 
       fos.write("true".getBytes()); 
       fos.close(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } catch (FileNotFoundException e) { 
      e.printStackTrace(); 
     } 
    } 


    public boolean ifFileExists(){ 
     File file = getApplicationContext().getFileStreamPath("madeDB"); 
     if(file.exists()) 
      return true; 
     else return false; 
    } 


    public int calcDays() { 
     int seasons, episodes, epiLength; 
     int[] info = new int[3]; 
     for(int i = 0; i < info.length; i++){ 
      info[i] = db.extractShowInfo()[i]; 
     } 
     seasons = info[0]; 
     episodes = info[1]; 
     epiLength = info[2]; 
     int totalTime = (seasons * episodes * epiLength); 
     System.out.println(seasons); 
     int dayOfWeek = getDay(); 
     int days = 0; 
     int y; 
     double z; 
     while (totalTime > 0) { 
      y = db.getMin(dayOfWeek); 
      z = db.getPercentage(dayOfWeek); 
      totalTime -= y*z; 
      dayOfWeek++; 
      if (dayOfWeek == 7) { 
       dayOfWeek = 0; 
      } 
      days++; 
     } 

     return days; 
    } 

    public int getDay() { 
     Calendar calendar = Calendar.getInstance(); 
     int day = calendar.get(Calendar.DAY_OF_WEEK); 
     return day; 
    } 


    public void setOnButton1ClickListener() { 
     b1 = (Button) findViewById(R.id.button); 
     b1.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       Intent i = new Intent("com.example.brandon.netflixcalculator.RoughGuessActivity"); 
       startActivity(i); 
      } 
     }); 
    } 

    public void setOnButton2ClickListener() { 
     b2 = (Button) findViewById(R.id.button2); 
     b2.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       Intent i = new Intent("com.example.brandon.netflixcalculator.Exact_Activity"); 
       startActivity(i); 
      } 
     }); 
    } 

    public void setOnButton3ClickListener() { 
     b3 = (Button) findViewById(R.id.button3); 
     b3.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       Intent i = new Intent("com.example.brandon.netflixcalculator.ShowInfoActivity"); 
       startActivity(i); 
      } 
     }); 
    } 

    public void setOnButton4ClickListener() { 
     b4 = (Button) findViewById(R.id.btnUpdate); 
     b4.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       System.out.println("-----------------------------------------------------"); 
       System.out.println(calcDays()); 
       showMessage("Days remaining", String.valueOf(calcDays())); 
       daysRemaining.setText(String.valueOf(calcDays())); 
      } 

     }); 

    } 

    public int getTotalMin(){ 
     int x = 0; 
     Cursor res = db.getWritableDatabase().rawQuery("select MINUTES from VIEWING", null); 
     StringBuffer sb = new StringBuffer(); 
     while(res.moveToNext()){ 
      x += Integer.parseInt(res.getString(0)); 
     } 
     return x; 
    } 


    public void readDB(){ 
     Cursor res = db.getAllData("SHOW_INFO"); 
     if (res.getCount() == 0) { 
      showMessage("Error", "No data found"); 
      return; 
     } 
     StringBuffer sb = new StringBuffer(); 
     while (res.moveToNext()) { 
      sb.append("\nName: " + res.getString(1) + "\nSeasons: " 
        + res.getString(2) + "\nEpisodes: " + res.getString(3) + "\nEpisode Length: " + 
        res.getString(4)); 
     } 
     showMessage("Test", sb.toString()); 
     db.close(); 

    } 

    public void showMessage(String title, String msg){ 
     AlertDialog.Builder builder = new AlertDialog.Builder(this); 
     builder.setCancelable(true); 
     builder.setTitle(title); 
     builder.setMessage(msg); 
     builder.show(); 
    } 
} 

DatabaseHelper Klasse

public class DatabaseHelper extends SQLiteOpenHelper{ 

    private static final String dbName = "viewing_database"; 
    private static final String tableViewing = "VIEWING"; 
    private static final String tableShowInfo = "SHOW_INFO"; 
    private static final String COL_1 = "ID"; 
    private static final String COL_2 = "WEEKDAY"; 
    private static final String COL_3 = "MINUTES"; 
    private static final String COL_4 = "PERCENTAGE"; 
    private static DatabaseHelper sInstance; 


    public DatabaseHelper(Context context) { 
     super(context, dbName, null, 1); 
    } 

    @Override 
    public void onCreate(SQLiteDatabase db) { 
     db.execSQL("create table " + tableViewing + " (ID INTEGER PRIMARY KEY AUTOINCREMENT, WEEKDAY TEXT, MINUTES INTEGER, PERCENTAGE TEXT)"); 
     db.execSQL("create table " + tableShowInfo + " (ID INTEGER PRIMARY KEY AUTOINCREMENT, NAME TEXT, SEASONS INTEGER, EPISODES INTEGER," + 
       " EPISODE_LENGTH INTEGER)"); 
    } 

    public static synchronized DatabaseHelper getInstance(Context context) { 
     // Use the application context, which will ensure that you 
     // don't accidentally leak an Activity's context. 
     if (sInstance == null) { 
      sInstance = new DatabaseHelper(context.getApplicationContext()); 
     } 
     return sInstance; 
    } 

    @Override 
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
     db.execSQL("DROP TABLE IF EXISTS " + tableViewing); 
     db.execSQL("DROP TABLE IF EXISTS " + tableShowInfo); 
     onCreate(db); 
    } 


    public boolean updateDataViewing(String id, String weekday, int minutes, String percentage){ 
     SQLiteDatabase myDataBase = this.getWritableDatabase(); 
     ContentValues cv = new ContentValues(); 
     cv.put(COL_1, id); 
     cv.put(COL_2, weekday); 
     cv.put(COL_3, minutes); 
     cv.put(COL_4, percentage); 
     myDataBase.update(tableViewing, cv, "ID = ?", new String[]{id}); 
     myDataBase.close(); 
     return true; 
    } 

    public boolean updateDataShow(String id, String name, int seasons, int episodes, int episodeLength){ 
     SQLiteDatabase myDataBase = this.getWritableDatabase(); 
     ContentValues cv = new ContentValues(); 
     cv.put(COL_1, id); 
     cv.put("NAME", name); 
     cv.put("SEASONS", seasons); 
     cv.put("EPISODES", episodes); 
     cv.put("EPISODE_LENGTH", episodeLength); 
     myDataBase.update(tableShowInfo, cv, "ID = ?", new String[]{id}); 
     return true; 
    } 

    public double getPercentage(int id){ 
     SQLiteDatabase myDataBase = this.getWritableDatabase(); 
     Cursor res = myDataBase.rawQuery("select PERCENTAGE from " + tableViewing + " where ID =" + id, null); 
     if (res.getCount() == 0) { 
      return 0; 
     } 
     StringBuffer sb = new StringBuffer(); 
     while (res.moveToNext()) { 
      sb.append(res.getString(0)); 
     } 

     String msg = sb.toString(); 
     myDataBase.close(); 
     return Integer.parseInt(msg.substring(0, msg.length()-1))/100.0; 
    } 


    public int getMin(int id){ 
     SQLiteDatabase myDataBase = this.getWritableDatabase(); 
     Cursor res = myDataBase.rawQuery("select MINUTES from " + tableViewing + " where ID =" + id, null); 
     if (res.getCount() == 0) { 
      return 0; 
     } 
     StringBuffer sb = new StringBuffer(); 
     while (res.moveToNext()) { 
      sb.append(res.getString(0)); 
     } 
     myDataBase.close(); 
     return Integer.parseInt(sb.toString()); 
    } 

    public Cursor getAllData(String tableName){ 
     SQLiteDatabase myDataBase = this.getWritableDatabase(); 
     Cursor res = myDataBase.rawQuery("select * from " + tableName, null); 
     return res; 
    } 

    public boolean insertDataViewing(String dayOfWeek, int minutes, String percentage){ 
     SQLiteDatabase myDataBase = getWritableDatabase(); 
     ContentValues cv = new ContentValues(); 
     cv.put(COL_2, dayOfWeek); 
     cv.put(COL_3, minutes); 
     cv.put(COL_4, percentage); 
     double result = myDataBase.insert(tableViewing, null, cv); 
     myDataBase.close(); 
     return(result != -1); 
    } 

    public boolean insertDataShow(String name, int seasons, int episodes, int episodeLength){ 
     SQLiteDatabase myDataBase = getWritableDatabase(); 
     ContentValues cv = new ContentValues(); 
     cv.put("NAME", name); 
     cv.put("SEASONS", seasons); 
     cv.put("EPISODES", episodes); 
     cv.put("EPISODE_LENGTH", episodeLength); 
     double result = myDataBase.insert(tableShowInfo, null, cv); 
     myDataBase.close(); 
     return(result != -1); 
    } 

    public String getShowName(){ 
     Cursor res = getAllData("SHOW_INFO"); 
     if (res.getCount() == 0) { 
      System.out.println("No data found"); 
      return "N/A"; 
     } 
     StringBuffer sb = new StringBuffer(); 
     while (res.moveToNext()) { 
      sb.append(res.getString(1)); 
     } 
     return sb.toString(); 
    } 

    public int[] extractShowInfo() { 
     int[] info = new int[3]; 
     Cursor res = getAllData("SHOW_INFO"); 
     if (res.getCount() == 0) { 
      System.out.println("No data found"); 
      return new int[] {0, 0, 0}; 
     } 
     while(res.moveToNext()){ 
      info[0] = Integer.parseInt(res.getString(2)); //seasons 
      info[1] = Integer.parseInt(res.getString(3)); //episodes 
      info[2] = Integer.parseInt(res.getString(4)); //episode length 
     } 

     for(int x:info){ 
      System.out.println(x); 
     } 

     return info; 

    } 

} 

Und schließlich der Fehler

04-06 13:59:22.081 1327-1327/com.example.brandon.netflixcalculator W/SQLiteLog: (28) failed to open "/data/user/0/com.example.brandon.netflixcalculator/databases/viewing_database-journal" with flag (131072) and mode_t (1b0) due to error (24) 
04-06 13:59:22.081 1327-1327/com.example.brandon.netflixcalculator E/SQLiteLog: (14) cannot open file at line 31517 of [2ef4f3a5b1] 
04-06 13:59:22.081 1327-1327/com.example.brandon.netflixcalculator E/SQLiteLog: (14) os_unix.c:31517: (24) open(/data/user/0/com.example.brandon.netflixcalculator/databases/viewing_database-journal) - 
04-06 13:59:22.081 1327-1327/com.example.brandon.netflixcalculator W/SQLiteLog: (28) failed to open "/data/user/0/com.example.brandon.netflixcalculator/databases/viewing_database-journal" with flag (131074) and mode_t (1b0) due to error (24) 
04-06 13:59:22.081 1327-1327/com.example.brandon.netflixcalculator W/SQLiteLog: (28) failed to open "/data/user/0/com.example.brandon.netflixcalculator/databases/viewing_database-journal" with flag (131072) and mode_t (1b0) due to error (24) 
04-06 13:59:22.081 1327-1327/com.example.brandon.netflixcalculator E/SQLiteLog: (14) cannot open file at line 31517 of [2ef4f3a5b1] 
04-06 13:59:22.081 1327-1327/com.example.brandon.netflixcalculator E/SQLiteLog: (14) os_unix.c:31517: (24) open(/data/user/0/com.example.brandon.netflixcalculator/databases/viewing_database-journal) - 
04-06 13:59:22.081 1327-1327/com.example.brandon.netflixcalculator E/SQLiteLog: (2062) statement aborts at 9: [select PERCENTAGE from VIEWING where ID =4] unable to open database file 
04-06 13:59:22.091 1327-1327/com.example.brandon.netflixcalculator E/SQLiteQuery: exception: unable to open database file (code 2062) 
                        ################################################################# 
                        Error Code : 2062 (SQLITE_CANTOPEN_EMFILE) 
                        Caused By : Application has opened two many files. Maximum of available file descriptors in one process is 1024 in default. 
                        (unable to open database file (code 2062)) 
                        #################################################################; query: select PERCENTAGE from VIEWING where ID =4 
04-06 13:59:22.091 1327-1327/com.example.brandon.netflixcalculator D/AndroidRuntime: Shutting down VM 
04-06 13:59:22.091 1327-1327/com.example.brandon.netflixcalculator E/AndroidRuntime: FATAL EXCEPTION: main 
                        Process: com.example.brandon.netflixcalculator, PID: 1327 
                        android.database.sqlite.SQLiteCantOpenDatabaseException: unable to open database file (code 2062) 
                        ################################################################# 
                        Error Code : 2062 (SQLITE_CANTOPEN_EMFILE) 
                        Caused By : Application has opened two many files. Maximum of available file descriptors in one process is 1024 in default. 
                         (unable to open database file (code 2062)) 
                        ################################################################# 
                         at android.database.sqlite.SQLiteConnection.nativeExecuteForCursorWindow(Native Method) 
                         at android.database.sqlite.SQLiteConnection.executeForCursorWindow(SQLiteConnection.java:980) 
                         at android.database.sqlite.SQLiteSession.executeForCursorWindow(SQLiteSession.java:836) 
                         at android.database.sqlite.SQLiteQuery.fillWindow(SQLiteQuery.java:62) 
                         at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:143) 
                         at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:132) 
                         at com.example.brandon.netflixcalculator.DatabaseHelper.getPercentage(DatabaseHelper.java:83) 
                         at com.example.brandon.netflixcalculator.MainActivity.calcDays(MainActivity.java:108) 
                         at com.example.brandon.netflixcalculator.MainActivity$4.onClick(MainActivity.java:166) 
                         at android.view.View.performClick(View.java:5697) 
                         at android.widget.TextView.performClick(TextView.java:10815) 
                         at android.view.View$PerformClick.run(View.java:22526) 
                         at android.os.Handler.handleCallback(Handler.java:739) 
                         at android.os.Handler.dispatchMessage(Handler.java:95) 
                         at android.os.Looper.loop(Looper.java:158) 
                         at android.app.ActivityThread.main(ActivityThread.java:7229) 
                         at java.lang.reflect.Method.invoke(Native Method) 
                         at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230) 
                         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120) 
04-06 13:59:28.401 1327-1338/com.example.brandon.netflixcalculator W/SQLiteConnectionPool: A SQLiteConnection object for database '+data+user+0+com_example_brandon_netflixcalculator+databases+viewing_database' was leaked! Please fix your application to end transactions in progress properly and to close the database when it is no longer needed. 
04-06 14:04:22.231 1327-1327/com.example.brandon.netflixcalculator I/Process: Sending signal. PID: 1327 SIG: 9 
+0

'Ich weiß, dass ich Datenbanken öffne und nicht schließe, weshalb ich den Fehler habe. Wie auch immer, ich kann diesen Fehler anscheinend nicht beheben. Was ist mit dem ** Schließen ** der Datenbank **, sobald Sie es benutzt haben? Sie können es dann erneut öffnen und erneut verwenden (und erneut schließen). Es ist gesunder Menschenverstand. –

+0

Mache ich das nicht schon mit myDatabase.close()? –

+0

Nein, das macht man nicht immer. –

Antwort

7

Sie Erstellen nur a single SqliteOpenHelper object für Ihre gesamte App werden sollte, und Verwendung das überall dort, wo ein Datenbankzugriff erforderlich ist. Dies wird viele Probleme mit gleichzeitigem Zugriff auf die Datenbank verhindern.

4

Ich war vor dem gleichen Problem, und ich schaffte es zu lösen, indem Sie den Cursor zu schließen, indem Sie den folgenden Aufruf, wo ich es offen gelassen:

cursor.close();

Ich erstellte ein neues Objekt der Cursor-Klasse innerhalb einer Schleife, ohne es zu schließen. Während kleine Schleifen-Iterationen gut funktionierten, nachdem die Daten größer wurden und die Schleifen-Iterationen auch, dann begann ich, dieses Problem zu sehen.

Verwandte Themen