简体   繁体   中英

Android startActivityForResult called twice

So my app, since it has to access a users drive information, starts by prompting the user to choose an account startActivityForResult(mGoogleAccountCredential.newChooseAccountIntent(), CHOOSE_ACCOUNT_REQUEST_CODE); upon getting the result(account name) from the activity my app calls in a separate thread code to check if the user has granted the app permission to access their information. It is at this point that if the user hasn't granted permission they will be prompted with a dialog asking for user consent.
On my phone this works perfectly, the dialog to choose an account pops up and soon after another dialog asking for consent opens up, i accept and I'm back at my app home screen. On my tablet though, once i give consent the dialog asking for me to choose an account pops up again. After tinkering about i found that the startActivityForResult line gets run twice(it isn't a system prompted thing), second time after i give consent.
After researching this for a bit i found that this might have to do with mis-handling the life-cycle of my activity, i noticed that on my phone when the consent screen pops up it completely covers the activity behind it, while on my tablet it only covers up a part of the screen. I know that when a activity is partially covered by another view its onPause() method is called but i still dont understand why my startActivityForResult is being called twice. Last thing, after realizing that on my tablet the onCreate() is run a second time(after accepting consent dialog) i surrounded my call to startActivityForResult in a if statement, which you can see in my code, but this didnt work and my question is why? Shouldnt that block of code only run once?
So in recap, why is the account chooser dialog popping up twice(all the code in onCreate is run twice) and why doesnt my if statement work? What am i missing? Thankyou.

 public class PlannerActivity extends ActionBarActivity{

        //YIG
        ListPlannerFragment mListFragment;
        DetailPlannerFragment mDetailFragment;
        YIGDataController mController;

        //Google
        private Drive mDrive;
        private SpreadsheetService mSpreadsheetService;
        private GoogleAccountCredential mGoogleAccountCredential;
boolean b;


        //Scope
        private static final String DRIVE_SCOPE = "https://www.googleapis.com/auth/drive";
        private static final String SHEETS_SCOPE = "https://spreadsheets.google.com/feeds https://docs.google.com/feeds";
        private static final String MY_APP_SCOPE = DRIVE_SCOPE + " " + SHEETS_SCOPE;
        //Request Codes
        protected static final int CHOOSE_ACCOUNT_REQUEST_CODE = 1;
        protected static final int AUTHORIZE_APP_ACCESS_REQUEST_CODE = 2;

        public static final String TAG = "PlannerActivity";



        //Life Cycle
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            //Google
        if(!b){//This still gets run second time when user consent dialog is accepted, is the value of b being reset??
           b = true;
           verifyGoogleAPIUse();
         }


            setContentView(R.layout.activity_planner);
        }

        @Override
        protected void onPause() {
            super.onPause();
        }

        @Override
        protected void onResume() {
            super.onResume();
        }

        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            switch(requestCode) {
                case CHOOSE_ACCOUNT_REQUEST_CODE:

                    if(resultCode == Activity.RESULT_OK) {
                        Log.d(TAG, "CHOOSE_ACCOUNT successful");

                        String accountName = data.getExtras().getString(AccountManager.KEY_ACCOUNT_NAME);
                        mGoogleAccountCredential.setSelectedAccountName(accountName);
                        mDrive = new Drive.Builder(AndroidHttp.newCompatibleTransport(),new GsonFactory(), mGoogleAccountCredential).setApplicationName("YIG Manager").build();
                        mSpreadsheetService = new SpreadsheetService("YIG Manager");
                        AuthorizeAPIUse authroizeAPIUse = new AuthorizeAPIUse(this,mGoogleAccountCredential.getScope(),mGoogleAccountCredential.getSelectedAccountName(),mSpreadsheetService,mGoogleAccountCredential,mDrive);
                        authroizeAPIUse.execute();
                    } else {
                        Log.d(TAG, "CHOOSE_ACCOUNT failure");
                        finish();
                    }

                    break;
                case AUTHORIZE_APP_ACCESS_REQUEST_CODE:

                    if(resultCode == Activity.RESULT_OK){
                        Log.d(TAG, "AUTHORIZE_APP_ACCESS success");
                        AuthorizeAPIUse authroizeAPIUsex = new AuthorizeAPIUse(this,mGoogleAccountCredential.getScope(),mGoogleAccountCredential.getSelectedAccountName(),mSpreadsheetService,mGoogleAccountCredential,mDrive);
                        authroizeAPIUsex.execute();
                    }
                    else{
                        Log.d(TAG, "AUTHORIZE_APP_ACCESS failed");
                        finish();
                    }

                    break;
            }
        }


        //Util
        private void verifyGoogleAPIUse(){
            mController.mGoogleAccountCredential = GoogleAccountCredential.usingOAuth2(this, Collections.singleton(MY_APP_SCOPE));
            mGoogleAccountCredential = mController.mGoogleAccountCredential;
            startActivityForResult(mGoogleAccountCredential.newChooseAccountIntent(), CHOOSE_ACCOUNT_REQUEST_CODE);
        }

        public void handleAuthException(UserRecoverableAuthException e) {
            startActivityForResult(e.getIntent(), AUTHORIZE_APP_ACCESS_REQUEST_CODE);//This gets run second time after user consent dialog is accepeted
        }



    private class AuthorizeAPIUse extends AsyncTask {

        @Override
        protected Object doInBackground(Object[] params) {
            try {
                String token = fetchToken();
                if(token != null){
                    Log.d(PlannerActivity.TAG, "Scope authorized");
                    mSpreadsheetService.setAuthSubToken(token);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }

        protected String fetchToken() throws IOException {
            try {
                return GoogleAuthUtil.getToken(mActivity, mEmail, mScope);
            } catch (UserRecoverableAuthException e) {
                mActivity.handleAuthException(e);//This is what starts the dialog that prompts for user consent
            } catch (GoogleAuthException e) {
                e.printStackTrace();
            }
            return null;
        }

    }}

So it would appear that i had in my developer options the 'don't keep activities' option selected. Because of this when the dialog obscured the view of my activity it would be destroyed and so its onCreate would be called once the consent prompt was consumed, this was resulting in my entire onCreate method being called thus resulting in the dialog popping up twice. On my question of why my if statement was not working its because when the activity was destroyed so apparently was the information in my boolean. To show this run the code below first without 'don't keep activities'. start the app, press home and then open the app again. The logs will show the results.

public class LifeCycleActivity extends ActionBarActivity {

private static final String TAG = "lifecycle";
boolean b;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    Log.d(TAG,"onCreate");
}

@Override
protected void onStart() {
    super.onStart();
    b = !b;
    Log.d(TAG,"onStart: b = " + b);
}

@Override
protected void onResume() {
    super.onResume();
    Log.d(TAG,"onResume: b = " + b);
}

@Override
protected void onPause() {
    super.onPause();
    Log.d(TAG,"onPause: b = " + b);
}

@Override
protected void onStop() {
    super.onStop();
    Log.d(TAG,"onStop");
}

@Override
protected void onRestart() {
    super.onRestart();
    Log.d(TAG,"onRestart");
}

@Override
protected void onDestroy() {
    super.onDestroy();
    Log.d(TAG,"onDestroy");
}

}

Change

    boolean b;

to

    volatile boolean b;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM