浏览器意图并返回到正确的活动(closures打开的选项卡)

在Android中的AccountManager中实现自定义帐户types时,我有以下问题的loginstream程:

login应通过OAuth提供商进行。 因此,我创build了一个启动WebView并启动OAuthstream程的SignInActivity 。 这工作得很好,当callback接收到my-custom-scheme://callback WebView检测到它,接收code查询string参数,并完成stream程。 使用WebView的缺点是,即使用户在浏览器中可能已经有一个活动的会话,该会话也不会在WebView使用,因此用户将不得不在WebView再次login。

为了解决这个问题,我尝试在AndroidManifest.xml使用intent-filter ,像这样:

 <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="my-custom-scheme" android:path="callback"/> </intent-filter> 

而不是在SignInActivity中打开一个WebView ,然后启动一个浏览器的意图,并等待浏览器打my-custom-scheme://callback

 Intent browserIntent = new Intent(Intent.ACTION_VIEW, "http://oauth2provider/authorize"); startActivity(browserIntent); finish(); 

在我的SignInActivity我有以下代码来处理callback:

 if (intent != null && intent.getData() != null && getString("my-custom-scheme").equals(intent.getData().getScheme())) { String code = getIntent().getData().getQueryParameter("code"); // complete oauth flow } 

这工作。 但是, 对于这个问题 (最后!):

  1. 如果用户未login,则浏览器意图将显示oauth提供程序的login页面。 用户login后,Chrome将redirect到my-custom-scheme://callback, SignInActivity将启动以处理该意图。 由于这个活动是不可见的,所以浏览器将在login页面上保持打开状态,对用户来说看起来没有任何事情发生。 浏览器从不closures。
  2. 如果用户已经login,oauth提供者将直接redirect到my-custom-scheme://callback。 在这种情况下,浏览器选项卡会自动closures,但浏览器本身保持打开状态(没有可用的选项卡)。

所以我的问题是:无论如何,使浏览器行为有所不同之后redirect到我的自定义scheme:/ /callback? 理想情况下,我希望它在redirect到callback后closures,并返回到活动堆栈中的前一个活动(即从开始启动SignInActivity的活动)。

Solutions Collecting From Web of "浏览器意图并返回到正确的活动(closures打开的选项卡)"

我用下一个方法来解决同样的问题。

假设我们有Sign Inbutton的MainActivity而不是直接点击该button启动浏览器,我使用startActivityForResult方法启动SignInActivity 。 它正在使用,然后我可以处理loginstream的结果。

startActivityForResult(new Intent(this, SignInActivity.class), requestCode);

SignInActivity负责:

  • 用login页面打开浏览器
  • 捕获redirect到custom-scheme://callback
  • 使用从redirect的URL接收到的令牌完成loginstream程
  • 将结果返回到MainActivity

所以,它的onCreate方法如下所示:

 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.login); if (intent != null && intent.getData() != null && "custom-scheme".equals(intent.getData().getScheme())) { String code = getIntent().getData().getQueryParameter("code"); // complete oauth flow } else { Intent browserIntent = new Intent(Intent.ACTION_VIEW, "http://oauth2provider/authorize") .setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_FROM_BACKGROUND); startActivity(browserIntent); finish(); } } 

承认标志设置到浏览器意图。

这样,如果从MainActivity打开SignInActivity ,它只是在浏览器中打开login页面,如果打开捕获redirecturl,则完成loginstream发送适当的请求。

在完成loginstream程后,将代码发送到callback方法中的某个端点后,您应该执行以下操作:

 setResult(Activity.RESULT_OK); this.finish(); 

当然,您会从该端点收到access_token。 你可以把它存储在这里的任何地方,在成功callback或返回到MainActivity来处理它。

作为SignInActivity布局,您可以在页面的中心使用ProgressBar 。 在SignInActivity打开后loginstream程完成时会出现捕获redirecturl( custom-scheme://callback )。

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <ProgressBar android:layout_width="48dp" android:layout_height="48dp" android:layout_centerVertical="true" android:layout_centerHorizontal="true" /> </RelativeLayout> 

这是AndroidManifest.xmlSignInActivity声明

 <activity android:name=".SignInActivity" android:launchMode="singleTask" android:noHistory="true" > <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT"/> <category android:name="android.intent.category.BROWSABLE"/> <data android:scheme="custom-scheme" android:host="callback"/> </intent-filter> </activity>