You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android GitHub OAuth登录异常:onResume提前执行致uri为空,onActivityResult未触发

解决GitHub OAuth登录时的回调异常问题

嘿,我帮你分析下你遇到的这个问题——其实这是Android系统处理外部Intent回调的机制导致的,咱们一步步来解决:

问题根源拆解

你现在的流程是:LoginActivity → BrowserActivity → 外部浏览器,当GitHub通过自定义Scheme回调时,会出现两个核心问题:

  1. onResume提前执行且uri为空:BrowserActivity启动外部浏览器后,系统会立刻触发它的onResume,但这时候还没到回调环节,getIntent().getData()自然是启动时的旧数据,也就是null。
  2. onCreate被调用而非onActivityResult:当回调触发时,系统会新建一个BrowserActivity实例(而不是回到之前启动的那个),所以旧实例的onActivityResult根本不会被触发,反而新实例的onCreate会执行。这是因为默认的Activity启动模式下,系统会为新的Intent创建新实例。

解决方案:两种修复路径

路径一:简化流程,去掉中间的BrowserActivity(推荐)

其实没必要用BrowserActivity做中转,直接让LoginActivity处理整个流程更简单:

  1. 修改AndroidManifest.xml:把原来BrowserActivity的intent-filter移到LoginActivity上:
<activity android:name=".ui.activities.LoginActivity" 
    android:label="@string/app_name" 
    android:theme="@style/AppTheme.NoActionBar"> 
    <intent-filter> 
        <action android:name="android.intent.action.MAIN" /> 
        <category android:name="android.intent.category.LAUNCHER" /> 
    </intent-filter>
    <!-- 新增OAuth回调的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:host="callback" android:scheme="app" /> 
    </intent-filter> 
</activity>
<!-- 可以删除BrowserActivity的配置了 -->
  1. 修改LoginActivity代码:直接启动外部浏览器,并在onNewIntent中处理回调:
public class LoginActivity extends AppCompatActivity { 
    Button loginButton; 
    private static final String OAUTH_URL = "你的OAuth授权地址";

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.activity_login); 
        loginButton = findViewById(R.id.button); 
        Log.d("called","oncreate"); 

        // 处理启动时的回调Intent(比如刚安装后直接从回调打开的情况)
        handleCallbackIntent(getIntent());

        loginButton.setOnClickListener(v -> {
            Log.d("called","onclick"); 
            attemptLogin(); 
        }); 
    } 

    private void attemptLogin(){ 
        Log.d("called","onattempt"); 
        // 直接启动外部浏览器
        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(OAUTH_URL)); 
        startActivity(intent); 
    } 

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        // 处理回调的Intent
        handleCallbackIntent(intent);
    }

    private void handleCallbackIntent(Intent intent) {
        Uri uri = intent.getData(); 
        if(uri != null && uri.toString().startsWith("app://callback")) { 
            String code = uri.getQueryParameter("code"); 
            Log.d("called", "拿到的code:" + code);
            // 这里继续处理code,比如请求token
        }
    }
}

路径二:保留BrowserActivity,修复回调逻辑

如果你一定要保留BrowserActivity,需要调整它的启动模式和回调处理逻辑:

  1. 修改AndroidManifest.xml:给BrowserActivity设置launchMode="singleTask",确保回调时复用已有实例:
<activity android:name=".ui.activities.BrowserActivity" 
    android:label="@string/app_name" 
    android:theme="@style/AppTheme.NoActionBar"
    android:launchMode="singleTask"> <!-- 新增启动模式 -->
    <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:host="callback" android:scheme="app" /> 
    </intent-filter> 
</activity>
  1. 修改BrowserActivity代码:用onNewIntent接收回调的Intent,而不是在onResume里拿旧Intent:
public class BrowserActivity extends AppCompatActivity { 
    public static String CALLBACK_URL = "app://callback"; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.activity_browser); 
        Intent intent = getIntent(); 
        if(intent != null && !intent.getDataString().startsWith(CALLBACK_URL)){ 
            // 只有当不是回调Intent时,才启动外部浏览器
            String url = intent.getStringExtra("URL"); 
            Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); 
            startActivity(i); 
        }
    } 

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        // 接收回调的新Intent
        Uri uri = intent.getData(); 
        if(uri != null && uri.toString().startsWith(CALLBACK_URL)) { 
            String code = uri.getQueryParameter("code"); 
            Intent resultIntent = new Intent(); 
            resultIntent.putExtra("code",code); 
            setResult(RESULT_OK, resultIntent); 
            finish(); 
        }
    }

    // 移除原来的onResume逻辑,因为它拿的是旧Intent
}

这样调整后,当回调触发时,系统会回到原来的BrowserActivity实例,调用onNewIntent处理回调,然后通过setResult把code返回给LoginActivity的onActivityResult。

另外提一句:startActivityForResult在Android 11及以上已经被弃用了,推荐使用ActivityResultContracts.StartActivityForResult,不过上面的代码先解决你当前的核心问题~

内容的提问来源于stack exchange,提问作者Brijesh Shah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:14:43