所以我的应用程序,因为它必须访问用户驱动器信息,首先提示用户从我的应用程序调用的活动中获取结果(帐户名称)时在单独的线程代码中选择帐户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;
}
}}
答案 0 :(得分:0)
所以看来我在我的开发者选项中没有保留活动'选择的选项。因此,当对话框模糊了我的活动视图时,它将被销毁,因此一旦使用了同意提示,就会调用它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");
}
}
答案 1 :(得分:-3)
更改
boolean b;
到
volatile boolean b;