【问题标题】:Android startActivityForResult called twiceAndroid startActivityForResult 调用了两次
【发布时间】:2015-02-18 01:47:41
【问题描述】:

所以我的应用程序,因为它必须访问用户驱动器信息,首先提示用户选择一个帐户startActivityForResult(mGoogleAccountCredential.newChooseAccountIntent(), CHOOSE_ACCOUNT_REQUEST_CODE); 从我的应用程序调用的活动中获取结果(帐户名)在单独的线程代码中进行检查如果用户已授予应用访问其信息的权限。正是在这一点上,如果用户没有授予权限,他们将被提示一个对话框,要求用户同意。
在我的手机上,这非常有效,弹出一个选择帐户的对话框,然后很快另一个对话框询问同意打开,我接受,我回到我的应用程序主屏幕。不过,在我的平板电脑上,一旦我同意,要求我选择一个帐户的对话框就会再次弹出。在修补之后,我发现startActivityForResult 行运行了两次(这不是系统提示的事情),第二次在我同意后。
经过一番研究后,我发现这可能与对我的活动生命周期处理不当有关,我注意到在我的手机上,当同意屏幕弹出时,它完全覆盖了它背后的活动,而在我的平板电脑上,它只覆盖了屏幕的一部分。我知道当一个活动被另一个视图部分覆盖时,它的onPause() 方法被调用,但我仍然不明白为什么我的startActivityForResult 被调用了两次。最后一件事,在我意识到在我的平板电脑上第二次运行onCreate() 之后(在接受同意对话框之后),我在一个 if 语句中包围了我对startActivityForResult 的调用,你可以在我的代码中看到,但这没有用并且我的问题是为什么?那段代码不应该只运行一次吗?
总结一下,为什么帐户选择器对话框会弹出两次(onCreate 中的所有代码都运行两次),为什么我的 if 语句不起作用?我错过了什么? 谢谢。

 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;
        }

    }}

【问题讨论】:

    标签: java android google-drive-api google-sheets android-lifecycle


    【解决方案1】:

    所以看起来我在我的开发人员选项中选择了“不保留活动”选项。因此,当对话框遮挡了我的活动视图时,它将被销毁,因此一旦同意提示被消耗,它的onCreate 将被调用,这导致我的整个onCreate 方法被调用,从而导致对话框弹出涨了两次。关于为什么我的 if 语句不起作用的问题,因为当活动被破坏时,我的布尔值中的信息显然如此。为了显示这一点,首先运行下面的代码,不要使用“不保留活动”。启动应用程序,按主页,然后再次打开应用程序。日志将显示结果。

    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");
    }
    

    }

    【讨论】:

      【解决方案2】:

      改变

          boolean b;
      

          volatile boolean b;
      

      【讨论】:

      • 请不要只写代码,解释一下为什么您认为更改可以解决我的问题,而这并不能回答我的全部问题。
      猜你喜欢
      • 1970-01-01
      • 2018-04-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-07
      • 1970-01-01
      • 2019-09-19
      • 1970-01-01
      相关资源
      最近更新 更多