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

时间:2014-09-14 09:40:35

标签: android google-chrome android-intent oauth-2.0

在Android中的AccountManager中实施自定义帐户类型时,我对登录流程存在以下问题:

登录应通过OAuth提供商进行。因此,我创建了一个SignInActivity来启动WebView并启动OAuth流程。这工作正常,当收到my-custom-scheme://callback WebView的回调时,code检测到它,接收WebView querystring参数并完成流程。使用WebView的缺点是,即使用户可能已在浏览器中拥有活动会话,WebView中也不会使用此会话,因此用户必须再次登录intent-filter 1}}。

要解决此问题,我尝试使用AndroidManifest.xml中的<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> 切换,如下所示:

WebView

我没有在SignInActivity中打开my-custom-scheme://callback,而是启动浏览器意图并等待浏览器点击Intent browserIntent = new Intent(Intent.ACTION_VIEW, "http://oauth2provider/authorize"); startActivity(browserIntent); finish();

SignInActivity

在我的if (intent != null && intent.getData() != null && getString("my-custom-scheme").equals(intent.getData().getScheme())) { String code = getIntent().getData().getQueryParameter("code"); // complete oauth flow } 中,我有以下代码来处理回调:

SignInActivity

这很有效。但是,解决问题(最后!):

  1. 如果用户未登录,则浏览器意图将显示oauth提供程序的登录页面。用户登录后,Chrome会重定向到my-custom-scheme://回调,SignInActivity将启动以处理意图。由于此活动不可见,浏览器将在登录页面上保持打开状态,对于用户来说,它看起来似乎什么也没发生。浏览器永远不会关闭。
  2. 如果用户已登录,则oauth提供程序将直接重定向到my-custom-scheme://回调。在这种情况下,浏览器标签会自动关闭,但浏览器本身仍处于打开状态(没有标签可见)。
  3. 所以我的问题是:无论如何,在重定向到my-custom-scheme://回调后,浏览器的行为是否有所不同?理想情况下,我希望它在重定向到回调之后简单地关闭,并返回到活动堆栈中的上一个活动(即从开头开始{{1}}的活动)。

1 个答案:

答案 0 :(得分:4)

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

假设我们MainActivity带有Sign In按钮。 相反启动浏览器直接点击该按钮我使用SignInActivity方法启动startActivityForResult。它用于那时我可以处理登录流程的结果。

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

SignInActivity负责:

  • 使用登录页面打开浏览器
  • 抓住重定向到custom-scheme://callback
  • 使用从重定向网址
  • 收到的令牌完成登录流程
  • 将结果返回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();
    }
}

允许将标记设置到浏览器意图中。

这样,如果从SignInActivity打开MainActivity,它只会在浏览器中打开登录页面,如果它已打开捕获重定向网址,则会完成登录流程,发送相应的请求。

完成登录流程后,将代码发送到回调方法中的某个端点,您应该执行以下操作:

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

当然,您从该端点接收access_token。您可以将它存储在此处,成功回调中,或者将其返回到MainActivity以在那里处理它。

作为SignInActivity的布局,您只能在页面中心使用ProgressBar。在SignInActivity打开后,在登录流程完成时,它会显示为捕获重定向网址(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>

以下是SignInActivity

AndroidManifest.xml的声明
<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>