0

We updated our Android app to Api level 33 ie targetSdk33 on June 1st 2023. Immediately after it went public and was installed we started getting lots of Crashlytics involving this "java.lang.NullPointerException: Attempt to invoke virtual method 'java.io.File android.content.Context.getDatabasePath(java.lang.String)' on a null object reference" on Android 10 upwards. Android 9 and below do not have this issue.

Previous versions below Api 33 do not have this error at all and we have been scratching our heads on what to do. going back to api 29 is not really an option given that come Aug 31st , to publish we'll have to update to 33 anyway.

My question is this. is anyone else on Api 33, getting random Null pointers when your app is attempting to do an Sqlite operation ie getWriteableDatabase(),especially in the background ? (we are getting a few foreground never seen before errors as well)

What we have done so far, We moved our Sqlite initialization code into the main app singleton

public class myApp extends MultiDexApplication implements Application.ActivityLifecycleCallbacks {
    // Singleton application mInstance
    private volatile static myApp mInstance;
    private static Context context;
    public static DatabaseRoutines db;

   
    public static Context getAppContext() {
        return context;
    }

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        MultiDex.install(this);
    }

    @Override
    public void onCreate() {
        super.onCreate();
        mInstance = this;
        context = mInstance.getApplicationContext();
           
        try {

            db = new DatabaseRoutines(mInstance);

        } catch (Exception e) {
            e.printStackTrace();
        }
    //other init stuff
     
    public static myApp getInstance() {
        if (null == mInstance) {
            synchronized (myApp.class) {
                if (null == mInstance) {
                    mInstance = new myApp();

                }
            }
        }
        return mInstance;
    }
//rest of my code
    }
    public static synchronized DatabaseRoutines getDatabase() {
        return db;
    }


}

we now get a single instance of the sqlite db using SqliteDatabase db= MyApp.getDatabase(); Also we changed the actual initialization of the sqlite database to the following. before this We were getting the app context from the Sqlite database itself and passing in the MyAPP context to it if it was not already started.

public class DatabaseRoutines extends SQLiteOpenHelper {

    public static final String MY_APP_DB = "MyAppDBNameExact.db";
       
    private static DatabaseRoutines mInstance;
    
    public DatabaseRoutines(Context context) {
        super(context, MY_APP_DB, null, 1);
    }

    public static synchronized DatabaseRoutines getInstance() {

        if (mInstance == null) {
            mInstance = new DatabaseRoutines(myApp.getAppContext());
        }
        return mInstance;
}

Previously we were just calling SqliteDatabase db= DatabaseRoutines.getInstance(); we stopped doing this.

The Sqlite Context errors have gone down dramatically but once in a while we still get a context issue usually with the main app itself, weirdly when the app is in foreground!

Again has anyone come across this issue and if you have resolved it , please share.

KuriaNdungu
  • 623
  • 8
  • 20

0 Answers0