7

My Android app need the user to create an account to be able to use the app. The account info is stored in SQLite database. When the application starts I check if the user has an account, if not I show a sign up activity for the user.

Now I get reports from users that they sometimes comes to the sign up activity even if they've already created an account. This happens when they've closed the application and reopen it again.

This is the code I'm using and I need to figure out what the problem might be:

//MyApplication.java
public class MyApplication extends Application {
    private DataBaseUtility dbu;
    public boolean hasAccount;  

    @Override
    public void onCreate() {
        super.onCreate();

        //Init sqlite database
        this.dbu = new DataBaseUtility(this);

        //This loads the account data from the database and returns true if the user has already created an account
        this.hasAccount = loadAccount();
    }

    public boolean loadAccount() {
        boolean loadedData = false;

        String query = "SELECT data FROM tblaccount WHERE tblaccount.deleted=0";
        Cursor cursor = this.dbu.getCursor(query);
        if (cursor != null) {
            while (cursor.moveToNext()) {
                loadedData = true;
            }
            cursor.close();
        }

        return loadedData;
    }
}

//MainActivity.java
public class MainActivity extends TabActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        MyApplication application = (MyApplication)getApplication();
        if (!application.hasAccount) {
            //Take the user to the sign up activity
        }
}

My idea is that maybe sometimes MainActivity.onCreate() runs before MyApplication.onCreate(). Can that be the case?

Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
Martin
  • 7,190
  • 9
  • 40
  • 48
  • Are you sure your loadAccount() method always works properly? Can you post it's code? – Vladimir Ivanov Aug 03 '11 at 08:02
  • You can try printing something in Logcat to see what method is called first. –  Aug 03 '11 at 08:05
  • Yeah, I'm quite sure, it only uses the DataBaseUtility to load the data from the sqlite database. So as far as the sqlite database is initialized it should work. – Martin Aug 03 '11 at 08:06
  • Alex I haven't ever had this problem myself, have tried to open and close the app many many times and it always work like it should, so it is hard to reproduce. – Martin Aug 03 '11 at 08:07
  • So only some users experience it, the question is, on what phones? Maybe the connection to database is working slow, and takes some time to load. –  Aug 03 '11 at 08:09
  • Yes, it seems that it is not happening for everybody. I know one running samsung galaxy GT-I9000. Can't I always be sure that MyApplication.onCreate() runs before MainActivity.onCreate()? – Martin Aug 03 '11 at 08:17
  • `MyApplication.onCreate()` runs first but `this.hasAccount = loadAccount();` may not have any effect. Is there a thread in there? Can we see the code for `loadAccount()` ? –  Aug 03 '11 at 08:28
  • Maybe it is only code excerpt but maybe move hasAccount to MainActivity if it is the one that suppose to us it. – gregory561 Aug 03 '11 at 08:35
  • I added the code of the loadAccount() to the question. There is no threads or something like that. – Martin Aug 03 '11 at 08:45
  • Greg I need to have hasAccount in MyApplication as I need to use it all around the app. But maybe I should move the check to MainActivity. – Martin Aug 03 '11 at 08:57

1 Answers1

4

In application's onCreate, you are checking if the user has an account and setting a boolean.

You are checking in the MainActivity's onCreate if the user has an account through the application's boolean.

application's onCreate() executing before MainActivity's onCreate() is always the case! It is impossible for a different execution path to occur and since application's onCreate() does not have a Runnable it is a 100% garantuee.

Please make sure you're DataBaseUtility does not have any Runnables.

Anyway STILL there are several ways to reproduce the error! I will not state these now but you can know them when you see:

SOLUTION

MainActivity You have forgotten to update application.hasAccount upon successfull sign up~

public class MainActivity extends TabActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        MyApplication application = (MyApplication)getApplication();
        if (!application.hasAccount) {
            //Take the user to the sign up activity
            //if(successful) application.hasAccount = true
        }
}

To avoid database exceptions

I use this:

REMARK It would be much better to use more strong persistent status saving for the database -i.e. SharedPreferences

boolean isOpened = false;
//When I need to open
if(!isOpened){
    //open
    isOpened = true;
}
//When I need to close
if(isOpened){
    //close
    isOpened = false;
}

onDestroy() {  //every onDestroy
    if(isOpened){
        //close
    }
}
Sherif elKhatib
  • 45,786
  • 16
  • 89
  • 106
  • Thanks! So I can always be sure that application's onCreate() runs first, thats good. I save the user info in the sqlite database on successful signup. Then I set hasAccount = True, so that is not the case. There are thousands of users running the application and this errors seems to happen only for a few users. As I relay on the sqlite database stored on the device, maybe the problem is that it has been removed or is corrupt? – Martin Aug 03 '11 at 09:07
  • it can not go corrupt? Are you sure you are closing database? sometime if you do not close database (even if the app was closed using force close) next time you try to open, exception occurs! Did you try `SharedPreferences`? – Sherif elKhatib Aug 03 '11 at 09:10
  • Hmm, I'm not closing the database. I only have one open connection in DataBaseUtility that I use through the whole app. So when should I close it, when the app closes? – Martin Aug 03 '11 at 09:15
  • Thanks! As I only open the database once in application's onCreate and keep it open do I put this code in the DataBaseUtility or in MyApplication? – Martin Aug 03 '11 at 09:29
  • No put it in *MyApplication*. Try to reproduce the error and see if the user will get sign-up screen – Sherif elKhatib Aug 03 '11 at 09:30
  • But Application doesn't seem to have an onDestroy method? http://developer.android.com/reference/android/app/Application.html – Martin Aug 03 '11 at 09:37
  • Ah yeah application doesnt have onDestroy()... In each block of code, when you are done, close the database – Sherif elKhatib Aug 03 '11 at 09:38
  • So I need to open and close the database every time I use it in an activity? I thought I could keep the connection open through the application with DataBaseUtility. Now I need to rewrite my whole app. Maybe I can just close the database on MainActivity.onDestroy() as this activity is always in the background of my app? – Martin Aug 03 '11 at 10:01
  • Yes close it.. Anyway try to simulate if database is not closed ! and force close app then open .. there must be an exception – Sherif elKhatib Aug 03 '11 at 10:12
  • Yeah, I've tried like thousands time to reproduce this problem that some users have but I never have this problem when I test. – Martin Aug 03 '11 at 10:25