2017-03-06 1 views
0

Wenn ich eine App über Android Studio neu starte, wird gelegentlich diese Ausnahme auftreten und die einzige Möglichkeit, die ich gefunden habe, ist es, die in der App gespeicherten Daten zu löschen.Neustart von Android App gelegentlich wirft java.lang.IllegalStateException

Ich nehme an, dies geschieht, weil die App in der Mitte einer Transaktion zu meiner SQLite-Datenbank getötet wird.

  1. Ist meine Annahme richtig?
  2. Gibt es eine Möglichkeit, dies zu verhindern?
  3. Wenn meine App einen Dienst im Vordergrund ausführt und es getötet wird, um die App selbst zu aktualisieren, könnte dies passieren?

Edit:

STACK_TRACE=java.lang.RuntimeException: Unable to start activity ComponentInfo{com.camhart.netcountable/com.camhart.netcountable.activities.setup.DeviceTypeActivity}: java.lang.IllegalStateException: Couldn't read row 0, col 0 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it. 
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3254) 
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3350) 
at android.app.ActivityThread.access$1100(ActivityThread.java:222) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1795) 
at android.os.Handler.dispatchMessage(Handler.java:102) 
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) 
Caused by: java.lang.IllegalStateException: Couldn't read row 0, col 0 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it. 
at android.database.CursorWindow.nativeGetLong(Native Method) 
at android.database.CursorWindow.getLong(CursorWindow.java:524) 
at android.database.AbstractWindowedCursor.getLong(AbstractWindowedCursor.java:75) 
at com.camhart.netcountable.sqlite.dataaccess.SettingDataAccess.getSettings(SettingDataAccess.java:91) 
at com.camhart.netcountable.sqlite.businesslogic.SettingBusinessLogic.getSettingsFromDatabase(SettingBusinessLogic.java:61) 
at com.camhart.netcountable.sqlite.businesslogic.SettingBusinessLogic.getSetting(SettingBusinessLogic.java:54) 
at com.camhart.netcountable.activities.setup.DeviceTypeActivity.onCreate(DeviceTypeActivity.java:43) 
at android.app.Activity.performCreate(Activity.java:6876) 
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1135) 
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3207) 
... 9 more 
java.lang.IllegalStateException: Couldn't read row 0, col 0 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it. 
at android.database.CursorWindow.nativeGetLong(Native Method) 
at android.database.CursorWindow.getLong(CursorWindow.java:524) 
at android.database.AbstractWindowedCursor.getLong(AbstractWindowedCursor.java:75) 
at com.camhart.netcountable.sqlite.dataaccess.SettingDataAccess.getSettings(SettingDataAccess.java:91) 
at com.camhart.netcountable.sqlite.businesslogic.SettingBusinessLogic.getSettingsFromDatabase(SettingBusinessLogic.java:61) 
at com.camhart.netcountable.sqlite.businesslogic.SettingBusinessLogic.getSetting(SettingBusinessLogic.java:54) 
at com.camhart.netcountable.activities.setup.DeviceTypeActivity.onCreate(DeviceTypeActivity.java:43) 
at android.app.Activity.performCreate(Activity.java:6876) 
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1135) 
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3207) 
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3350) 
at android.app.ActivityThread.access$1100(ActivityThread.java:222) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1795) 
at android.os.Handler.dispatchMessage(Handler.java:102) 
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) 

SettingDataAccess.java

package com.camhart.netcountable.sqlite.dataaccess; 

import android.content.ContentValues; 
import android.content.Context; 
import android.database.Cursor; 

import com.camhart.netcountable.sqlite.models.Setting; 
import com.camhart.netcountable.sqlite.tabledata.SettingTableData; 

import net.openid.appauth.AuthState; 

import org.json.JSONException; 

public class SettingDataAccess extends DataAccess { 

    \\... 

    private static String[] columnsToGrab = new String[]{ 
      SettingTableData._ID, 
      SettingTableData.COLUMN_NAME_USERNAME, 
      SettingTableData.COLUMN_NAME_ACCOUNTID, 
      SettingTableData.COLUMN_NAME_IDENTITYID, 
      SettingTableData.COLUMN_NAME_WIFIONLY, 
      SettingTableData.COLUMN_NAME_EMAIL, 
      SettingTableData.COLUMN_NAME_ADMINDEVICE, 
      SettingTableData.COLUMN_NAME_PREMIUM, 
      SettingTableData.COLUMN_NAME_PUBLICKEY, 
      SettingTableData.COLUMN_NAME_TAKENAPSHOTS, 
      SettingTableData.COLUMN_NAME_AUTHSTATEJSON 
    }; 

    public Setting getSettings() { 
     Setting setting = new Setting(); 

     Cursor c = db.query(SettingTableData.TABLE_NAME, 
       columnsToGrab, 
       null, 
       new String[]{}, 
       null, 
       null, 
       null, 
       null); 

     if(c.moveToFirst()) { 
      setting.setId(c.getLong(c.getColumnIndex(SettingTableData._ID))); //#line 91 
      setting.setAccountId(c.getString(c.getColumnIndex(SettingTableData.COLUMN_NAME_ACCOUNTID))); 
      setting.setIdentityId(c.getString(c.getColumnIndex(SettingTableData.COLUMN_NAME_IDENTITYID))); 
      setting.setDisplayName(c.getString(c.getColumnIndex(SettingTableData.COLUMN_NAME_USERNAME))); 
      setting.setWifiOnlyUpload(c.getInt(c.getColumnIndex(SettingTableData.COLUMN_NAME_WIFIONLY)) == 1); 
      setting.setEmail(c.getString(c.getColumnIndex(SettingTableData.COLUMN_NAME_EMAIL))); 

      setting.setAdminDevice(c.getInt(c.getColumnIndex(SettingTableData.COLUMN_NAME_ADMINDEVICE)) == 1); 
      setting.setPremium(c.getInt(c.getColumnIndex(SettingTableData.COLUMN_NAME_PREMIUM)) == 1); 
      setting.setPublicKey(c.getString(c.getColumnIndex(SettingTableData.COLUMN_NAME_PUBLICKEY))); 
      setting.setTakeSnapshots(c.getInt(c.getColumnIndex(SettingTableData.COLUMN_NAME_TAKENAPSHOTS)) == 1); 
      String jsonAuthState = c.getString(c.getColumnIndex(SettingTableData.COLUMN_NAME_AUTHSTATEJSON)); 

      if(jsonAuthState != null) { 
       try { 
        setting.setAuthState(AuthState.jsonDeserialize(jsonAuthState)); 
       } catch (JSONException e) { 
        e.printStackTrace(); 
       } 
      } 
      c.close(); 

      return setting; 
     } 
     c.close(); 

     return null; 
    } 
} 

SettingTableData.java

public class SettingTableData implements BaseColumns { 
    public static final String TABLE_NAME = "settings"; 
    public static final String COLUMN_NAME_WIFIONLY = "wifiOnlyUpload"; 
    public static final String COLUMN_NAME_USERNAME = "username"; 
    public static final String COLUMN_NAME_ACCOUNTID = "accountId"; 
    public static final String COLUMN_NAME_IDENTITYID = "identityId"; 
    public static final String COLUMN_NAME_EMAIL = "email"; 
    public static final String COLUMN_NAME_PREMIUM = "premium"; 
    public static final String COLUMN_NAME_LASTREFRESH = "lastRefresh"; 
// public static final String COLUMN_NAME_PRIVATEKEY = "privateKey"; 
    public static final String COLUMN_NAME_ADMINDEVICE = "admin"; 
    public static final String COLUMN_NAME_PUBLICKEY = "publicKey"; 
    public static final String COLUMN_NAME_TAKENAPSHOTS = "takeSnapshots"; 
    public static final String COLUMN_NAME_AUTHSTATEJSON = "jsonAuthState"; 
} 

Setting.java

public class Setting { 

    private boolean wifiOnlyUpload; 
    private String displayName; 
    private String accountId; 
    private String identityId; 
    private long id; 
    private String email; 
    private boolean premium; 
    private boolean adminDevice; 
    private String publicKey; 
    private boolean takeSnapshots; 
    private AuthState authState; 

    public String getIdentityId() { 
     return identityId; 
    } 

    public void setIdentityId(String identityId) { 
     this.identityId = identityId; 
    } 

    public String getAccountId() { 
     return accountId; 
    } 

    public void setAccountId(String accountId) { 
     this.accountId = accountId; 
    } 

    public boolean isWifiOnlyUpload() { 
     return wifiOnlyUpload; 
    } 

    public void setWifiOnlyUpload(boolean wifiOnlyUpload) { 
     this.wifiOnlyUpload = wifiOnlyUpload; 
    } 

    public String getDisplayName() { 
     return displayName; 
    } 

    public void setDisplayName(String username) { 
     this.displayName = username; 
    } 

    public long getId() { 
     return id; 
    } 

    public void setId(long id) { 
     this.id = id; 
    } 

    public void setEmail(String email) { 
     this.email = email; 
    } 

    public String getEmail() { 
     return email; 
    } 

    public boolean isPremium() { 
     return premium; 
    } 

    public void setPremium(boolean premium) { 
     this.premium = premium; 
    } 

    public boolean isAdminDevice() { 
     return adminDevice; 
    } 

    public void setAdminDevice(boolean adminDevice) { 
     this.adminDevice = adminDevice; 
    } 

    public void setPublicKey(String publicToken) { 
     this.publicKey = publicToken; 
    } 

    public String getPublicKey() { 
     return this.publicKey; 
    } 

    public boolean takesSnapshots() { 
     //TODO: Make it so admins can take screenies too (for couples) 
     return isTakeSnapshots() && isPremium(); 
    } 

    public void setTakeSnapshots(boolean takeSnapshots) { 
     this.takeSnapshots = takeSnapshots; 
    } 

    public boolean isTakeSnapshots() { 
     return takeSnapshots; 
    } 

    public AuthState getAuthState() { 
     return authState; 
    } 

    public void setAuthState(AuthState jsonAuthState) { 
     this.authState = jsonAuthState; 
    } 

    //TODO: update this to save the device type, then just have this check for isOwnerDevice instead of 
    // having to check the auth state too. 
    public boolean isOwner() { 
     return getAuthState() != null && isAdminDevice(); 
    } 

    public String getReversedIdentityId() { 
     return new StringBuilder(getIdentityId()).reverse().toString(); 
    } 
} 

DataAccess.java

public class DataAccess { 
    protected SQLiteDatabase db; 
    private static DbHelper dbHandler; 

    protected static synchronized DbHelper getDbHelper(Context context) { 
     if(dbHandler == null) { 
      dbHandler = new DbHelper(context); 
     } 
     return dbHandler; 
    } 

    public DataAccess(Context context) { 
     if(dbHandler == null) { 
      dbHandler = getDbHelper(context); 
     } 
    } 

    public void open() throws SQLException { 
     db = dbHandler.getWritableDatabase(); 
    } 

    public void close() { 
     db.close(); 
     db = null; 
    } 
} 
+0

Wir brauchen mehr Informationen, um Ihnen zu helfen. Bitte posten Sie den gesamten Stack und den entsprechenden Code. –

+0

Das hat nichts mit Transaktionen zu tun. –

+0

Ich warte auf den Fehler erneut auftreten und dann werde ich mit Code und einem vollständigen Stack-Trace aktualisieren. – CamHart

Antwort

0

Es scheint, was mein Auth Zustand JSON-String geschieht, ist viel viel länger als ich erwartet hatte, es wäre. Ich habe es an einen SharedPreference-Speicherort verschoben und nach einiger Zeit habe ich begonnen, OOM immer zu laden, wenn ich es laden wollte. Ich denke, das könnte in Sqlite so sein.

Verwandte Themen