【问题标题】:onNewIntent is never gets called - AndroidonNewIntent 永远不会被调用 - Android
【发布时间】:2020-10-21 12:16:00
【问题描述】:

我正在尝试使用 AppAuth 创建一个简单的 oauth2 流。我正在关注 AppAuth 的this tutorial。它可以很好地提出 oauth 请求,但是在对主要活动进行授权之后,它就永远不会调用 onNewIntent,我还检查了讨论的问题 here

编辑:当我使用 onResume 方法时,授权后使用 onResume 方法,但使用"android.intent.action.MAIN" 操作。在 onResume 上应该有 "com.google.codelabs.appauth.HANDLE_AUTHORIZATION_RESPONSE" 操作。

有什么建议为什么会发生?

下面是 MainActivity 类

public class MainActivity extends AppCompatActivity {
    private static final String USED_INTENT = "USED_INTENT";
    public static final String LOG_TAG = "AppAuthSample";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void setupAuthorization(View view) {
        AuthorizationServiceConfiguration serviceConfiguration = new AuthorizationServiceConfiguration(
                Uri.parse("https://accounts.google.com/o/oauth2/v2/auth"), //* auth endpoint *//*,
                Uri.parse("https://oauth2.googleapis.com/token") //* token endpoint *//*
        );

        String clientId = "MY_ID.apps.googleusercontent.com";
        Uri redirectUri = Uri.parse("com.demo.testdriveapi:/oauth2callback");
        AuthorizationRequest.Builder builder = new AuthorizationRequest.Builder(
                serviceConfiguration,
                clientId,
                "code",
                redirectUri
        );
        builder.setScopes("https://www.googleapis.com/auth/drive.appdata");
        AuthorizationRequest request = builder.build();
        AuthorizationService authorizationService = new AuthorizationService(this);

        String action = "com.google.codelabs.appauth.HANDLE_AUTHORIZATION_RESPONSE";
        Intent postAuthorizationIntent = new Intent(action);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, request.hashCode(), postAuthorizationIntent, 0);
        authorizationService.performAuthorizationRequest(request, pendingIntent);
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        checkIntent(intent);
    }    
 
    private void checkIntent(@Nullable Intent intent) {
        if (intent != null) {
            String action = intent.getAction();
            switch (action) {
                case "com.google.codelabs.appauth.HANDLE_AUTHORIZATION_RESPONSE":
                    if (!intent.hasExtra(USED_INTENT)) {
                        handleAuthorizationResponse(intent);
                        intent.putExtra(USED_INTENT, true);
                    }
                    break;
                default:
                    // do nothing
            }
        }
    }

    @Override
    protected void onStart() {
        super.onStart();
        checkIntent(getIntent());
    }

    private void handleAuthorizationResponse(@NonNull Intent intent) {
        AuthorizationResponse response = AuthorizationResponse.fromIntent(intent);
        AuthorizationException error = AuthorizationException.fromIntent(intent);
        final AuthState authState = new AuthState(response, error);

        if (response != null) {
            Log.i(LOG_TAG, String.format("Handled Authorization Response %s ", authState.jsonSerializeString()));
            AuthorizationService service = new AuthorizationService(this);
            service.performTokenRequest(response.createTokenExchangeRequest(), new AuthorizationService.TokenResponseCallback() {
                @Override
                public void onTokenRequestCompleted(@Nullable TokenResponse tokenResponse, @Nullable AuthorizationException exception) {
                    if (exception != null) {
                        Log.w(LOG_TAG, "Token Exchange failed", exception);
                    } else {
                        if (tokenResponse != null) {
                            authState.update(tokenResponse, exception);
                            Log.i(LOG_TAG, String.format("Token Response [ Access Token: %s, ID Token: %s ]", tokenResponse.accessToken, tokenResponse.idToken));
                        }
                    }
                }
            });
        }
    }
}

这是来自 AndroidMenifest.xml 的 sn-p

<application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <intent-filter>
                <action android:name="com.google.codelabs.appauth.HANDLE_AUTHORIZATION_RESPONSE"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </activity>

        <activity android:name="net.openid.appauth.RedirectUriReceiverActivity">
            <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="com.demo.testdriveapi"/>
            </intent-filter>
        </activity>
    </application>

这里是activity_main.xml的sn-p,我只有一个按钮

<Button
        android:id="@+id/buttonAuthorize"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="153dp"
        android:layout_marginTop="288dp"
        android:layout_marginEnd="170dp"
        android:onClick="setupAuthorization"
        android:text="Authorize"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

编辑:也尝试使用"android:launchMode="singleTop",但它也不起作用。

Edit2:添加谷歌开发者控制台截图

【问题讨论】:

    标签: android oauth-2.0 google-drive-api appauth


    【解决方案1】:

    检查 google drive API Dashboard 以进行 oAuth 身份验证,您的回调名称应匹配,并且也应在此处注册。正是通过此回调将授权响应发送回您的活动。

    【讨论】:

    • 在我的 google api 控制台上,它不会要求我提供回调 URL。在 Credential 部分中只询问 Name、Package Name 和 SHA1。我在哪里放置回调 URL?
    • 当您在 API 控制台中创建 OAuth 部分时。对于 OAuth 是要求回调。当您的客户端密钥可能已生成时,请查看该页面。我相信会有一些回调可能已经被填写。
    • 看看这个并环顾四周,您将获得设置回调所需的解决方案。希望这有助于developers.google.com/tasks/…
    • 你好再次感谢,但我认为谷歌已经改变了这一点。您最近是否尝试过创建 OAuth2 凭据?因为,当您在控制台上选择 Web 应用程序时,它会为您提供 RedirectUri 选项,而不是在您使用 Android 选项时。但是,当我为我为 Android 创建的凭证下载 JSON 时,它会在该文件中显示重定向 Uris。我尝试了两个都没有成功,即 "redirect_uris":[ "urn:ietf:wg:oauth:2.0:oob", "localhost" ]
    • 我添加了一张我在 Google Developer Console 上看到的图片供您参考。请看一看。提前致谢。
    【解决方案2】:

    net.openid:appauth:0.7.1 似乎有问题。我偶然发现了this question,然后我将我的版本更改为 0.2.0 并且它工作正常。

    【讨论】:

    • 整个库被证明是一场噩梦,文档有点难以理解并且缺乏示例。我不得不解决一些问题
    • 您好@Chief,如果您在网络上的某个地方有您的工作,请分享。
    【解决方案3】:

    如果我理解正确,您已经成功配置了 AppAuth,并且在启动身份验证机制时,用户可以输入他们的用户名和密码来登录 openId 或其他任何内容。但这样做时,您无法拦截该意图的结果(chrome 自定义选项卡)。

    如果是这样,试试这个覆盖方法

    onActivityResult(requestCode: Int, resultCode: Int, data: Intent?)
    

    您还需要startActivityForResult(authIntent, REQUEST_CODE)

    【讨论】:

    • 是的,但我想让它明确的意图而不是隐含的。获取验证码后代码接收token仍有问题
    猜你喜欢
    • 2014-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-04
    • 2017-01-20
    • 2023-03-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多