【问题标题】:Browser intent and return to correct activity (close opened tab)浏览器意图并返回正确的活动(关闭打开的选项卡)
【发布时间】:2014-11-08 00:45:11
【问题描述】:

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

应通过 OAuth 提供程序进行登录。因此,我创建了一个 SignInActivity,它启动了一个 WebView 并启动了一个 OAuth 流程。这工作正常,当接收到my-custom-scheme://callback 的回调时,WebView 检测到它,接收code 查询字符串参数并完成流程。使用WebView 的缺点是,即使用户在浏览器中可能已经有一个活动会话,但该会话并没有在WebView 中使用,因此用户必须在WebView 中再次登录。

为了解决这个问题,我尝试在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 中,我有以下代码来处理回调:

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

这行得通。但是,解决问题(终于!):

  1. 如果用户未登录,浏览器意图将显示 oauth 提供程序的登录页面。用户登录后,Chrome 将重定向到 my-custom-scheme://callback,SignInActivity 将启动以处理该意图。由于此活动是不可见的,因此浏览器将在登录页面上保持打开状态,并且对用户而言,它看起来就像什么都没发生。浏览器永远不会关闭。
  2. 如果用户已经登录,oauth 提供程序将直接重定向到 my-custom-scheme://callback。在这种情况下,浏览器 标签 会自动关闭,但浏览器本身仍保持打开状态(没有可见的标签)。

所以我的问题是:在重定向到 my-custom-scheme://callback 后,无论如何让浏览器表现不同吗?理想情况下,我希望它在重定向到回调后简单地关闭,并返回到活动堆栈中的上一个活动(即从一开始就启动 SignInActivity 的活动)。

【问题讨论】:

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


    【解决方案1】:

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

    假设我们有MainActivitySign In 按钮。 而不是直接单击该按钮启动浏览器,我使用startActivityForResult 方法启动SignInActivity。它用于然后我可以处理登录流程的结果。

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

    SignInActivity 负责:

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

    允许在浏览器意图中设置标志。

    这样,如果 SignInActivityMainActivity 打开它只会在浏览器中打开登录页面,如果它打开捕获重定向 url 它会完成登录流程发送适当的请求。

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

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

    当然,您会从该端点收到 access_token。您可以将其存储在此处的某个位置、成功回调中,也可以将其返回到MainActivity 以在那里进行处理。

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

    这是SignInActivityAndroidManifest.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>
    

    【讨论】:

    • 这对我没有帮助
    猜你喜欢
    • 2013-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-10
    • 2020-06-04
    • 2021-03-31
    相关资源
    最近更新 更多