Android startActivityForResult 调用了两次
Android startActivityForResult called twice
所以我的应用程序,因为它必须访问用户的驱动器信息,首先提示用户选择一个帐户 startActivityForResult(mGoogleAccountCredential.newChooseAccountIntent(), CHOOSE_ACCOUNT_REQUEST_CODE);
从 activity 我的应用程序获取结果(帐户名)调用单独的线程代码来检查用户是否已授予应用程序访问其信息的权限。正是在这一点上,如果用户没有授予权限,他们将收到一个对话框,要求用户同意。
在我的 phone 上,这非常有效,弹出选择帐户的对话框在另一个请求同意的对话框打开后不久,我接受并回到我的应用程序主屏幕。但是在我的平板电脑上,一旦我同意,要求我选择一个帐户的对话框就会再次弹出。在修补之后,我发现 startActivityForResult
行得到了 运行 两次(这不是系统提示的事情),第二次是在我同意之后。
对此进行了一些研究后,我发现这可能与我 activity 的生命周期处理不当有关,我注意到在我的 phone 上弹出同意屏幕时向上它完全覆盖了它后面的 activity,而在我的平板电脑上它只覆盖了屏幕的一部分。我知道当 activity 被另一个视图部分覆盖时,它的 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;
}
}}
改变
boolean b;
到
volatile boolean b;
所以看起来我在我的开发者选项中选择了“不保留活动”选项。因此,当对话框遮挡了我的 activity 视图时,它会被销毁,因此一旦同意提示被使用,它的 onCreate
就会被调用,这导致了我的整个 onCreate
方法被调用从而导致对话框弹出两次。关于为什么我的 if 语句不起作用的问题,因为当 activity 被销毁时,我的布尔值中的信息显然是这样。要显示此 运行 下面的代码首先没有“不保留活动”。启动应用程序,按主页,然后再次打开应用程序。日志将显示结果。
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");
}
}
所以我的应用程序,因为它必须访问用户的驱动器信息,首先提示用户选择一个帐户 startActivityForResult(mGoogleAccountCredential.newChooseAccountIntent(), CHOOSE_ACCOUNT_REQUEST_CODE);
从 activity 我的应用程序获取结果(帐户名)调用单独的线程代码来检查用户是否已授予应用程序访问其信息的权限。正是在这一点上,如果用户没有授予权限,他们将收到一个对话框,要求用户同意。
在我的 phone 上,这非常有效,弹出选择帐户的对话框在另一个请求同意的对话框打开后不久,我接受并回到我的应用程序主屏幕。但是在我的平板电脑上,一旦我同意,要求我选择一个帐户的对话框就会再次弹出。在修补之后,我发现 startActivityForResult
行得到了 运行 两次(这不是系统提示的事情),第二次是在我同意之后。
对此进行了一些研究后,我发现这可能与我 activity 的生命周期处理不当有关,我注意到在我的 phone 上弹出同意屏幕时向上它完全覆盖了它后面的 activity,而在我的平板电脑上它只覆盖了屏幕的一部分。我知道当 activity 被另一个视图部分覆盖时,它的 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;
}
}}
改变
boolean b;
到
volatile boolean b;
所以看起来我在我的开发者选项中选择了“不保留活动”选项。因此,当对话框遮挡了我的 activity 视图时,它会被销毁,因此一旦同意提示被使用,它的 onCreate
就会被调用,这导致了我的整个 onCreate
方法被调用从而导致对话框弹出两次。关于为什么我的 if 语句不起作用的问题,因为当 activity 被销毁时,我的布尔值中的信息显然是这样。要显示此 运行 下面的代码首先没有“不保留活动”。启动应用程序,按主页,然后再次打开应用程序。日志将显示结果。
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");
}
}