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

Expo-auth-session在Android独立应用中无法完成Google登录问题

Expo React Native Android独立应用Google登录无响应问题解决

问题现象

基于Expo开发的React Native应用,使用expo-auth-session/providers/google实现Google登录功能,在Expo开发环境中运行正常,但构建为Android独立应用后,点击登录按钮无任何响应。

核心修复方案

1. 修正函数拼写错误

代码中promtAsync为拼写错误,正确应为promptAsync,这是导致点击无响应的直接原因:

// 原错误代码
const [req, res, promtAsync] = Google.useIdTokenAuthRequest(...)
// 修正后
const [req, res, promptAsync] = Google.useIdTokenAuthRequest(...)

// 调用时同步修正
const onLogin = () =>
  promptAsync()
    .then((response) => {
      // 后续逻辑保持不变
    })

2. 完善Android回调配置

在app.json的android字段中添加intentFilters,确保登录回调能正确跳转回应用,scheme需与根字段的scheme保持一致:

"android": {
  "package": "com.xxx.xx",
  "versionCode": 1,
  "adaptiveIcon": {
    "foregroundImage": "./assets/adaptive-icon.png",
    "backgroundColor": "#FFFFFF"
  },
  "intentFilters": [
    {
      "action": "VIEW",
      "data": [
        {
          "scheme": "com.xxx.xx"
        }
      ],
      "category": [
        "BROWSABLE",
        "DEFAULT"
      ]
    }
  ]
}

3. 调整回调处理位置

将WebBrowser.maybeCompleteAuthSession()移至App入口文件(如App.js)顶部,避免页面焦点变化导致回调丢失:

// App.js 顶部
import * as WebBrowser from 'expo-web-browser';
WebBrowser.maybeCompleteAuthSession();

4. 验证Google Cloud配置

  • 确保ANDROID_CLIENT_ID是Google Cloud控制台中为Android应用创建的OAuth 2.0客户端ID,格式为{数字}-{字符串}.apps.googleusercontent.com
  • 客户端ID配置的包名需与app.json中android.package完全一致
  • 已添加独立应用构建使用的Keystore SHA-1指纹到Google Cloud的客户端ID配置中

附:用户提供的原始代码与配置

AuthScreen原始代码

...
import decode from 'jwt-decode';
import { ANDROID_CLIENT_ID, EXPO_CLIENT_ID, IOS_CLIENT_ID } from '../../env';
import * as Google from 'expo-auth-session/providers/google';
import * as WebBrowser from 'expo-web-browser';
...
import { useFocusEffect } from '@react-navigation/native';
...

WebBrowser.maybeCompleteAuthSession();

const AuthScreen = () => {
  const [isLoading, setIsLoading] = useState(false);
  const [isSigningIn, setIsSigningIn] = useState(false);
  // eslint-disable-next-line no-unused-vars
  const [req, res, promtAsync] = Google.useIdTokenAuthRequest({
    expoClientId: EXPO_CLIENT_ID,
    androidClientId: ANDROID_CLIENT_ID,
    iosClientId: IOS_CLIENT_ID,
    scopes: ['profile', 'email'],
  });

  const dispatch = useDispatch();

  useFocusEffect(
    useCallback(() => {
      setIsLoading(true);
      loadFromStorage('user')
        .then(() => {
          setIsLoading(false);
          dispatch(setIsLoggedIn(true));
        })
        .catch(() => setIsLoading(false));
    }, []),
  );

  const onLogin = () =>
    promtAsync()
      .then((response) => {
        console.log({ res, req });
        if (response?.type === 'success') {
          const userInfo = decode(response?.params?.id_token);
          if (response?.params?.id_token) {
            setIsSigningIn(true);
            setIsLoading(true);
            login({
              google_id_token: response?.params?.id_token,
              name: userInfo?.name,
              profile_image: userInfo?.picture,
              agent: Platform.OS,
            })
              .then((res) => {
                const jwtToken = res?.headers?.['jwt-token'];
                saveToStorage({
                  key: 'jwtToken',
                  value: jwtToken,
                });
                saveToStorage({ key: 'user', value: userInfo });
                setIsSigningIn(false);
                setIsLoading(false);
                dispatch(setIsLoggedIn(true));
              })
              .catch(() => {
                console.log('Unable to sign-in.');
                setIsSigningIn(false);
                setIsLoading(false);
              });
          }
        }
      })
      .catch(() => {
        console.log('Unable to sign-in.');
        setIsSigningIn(false);

        setIsLoading(false);
      });

  return (
    <View style={styles.container}>
      {isLoading ? (
        <Loader />
      ) : (
        <>
          <ErpLogo />
          <TouchableNativeFeedback onPress={onLogin}>
            <GoogleSignInButton style={styles.googleButton} />
          </TouchableNativeFeedback>
        </>
      )}
      {isSigningIn && (
        <Text
          style={{
            position: 'absolute',
            bottom: Dimensions.get('screen').height / 30,
            fontFamily: fonts.firaSans400,
            color: colors.textColor,
          }}
        >
          Signing in...
        </Text>
      )}
    </View>
  );
};

export default AuthScreen;

app.json原始配置

{
  "expo": {
    "name": "X",
    "slug": "x",
    "version": "1.0.0",
    "owner": "xyz",
    "orientation": "portrait",
    "icon": "./assets/img/erp.png",
    "userInterfaceStyle": "light",
    "scheme": "com.xxx.xx",
    "splash": {
      "image": "./assets/splash.png",
      "resizeMode": "contain",
      "backgroundColor": "#ffffff"
    },
    "updates": {
      "fallbackToCacheTimeout": 0
    },
    "assetBundlePatterns": ["**/*"],
    "ios": {
      "supportsTablet": true,
      "bundleIdentifier": "com.xxx.xx",
      "buildNumber": "1.0.0"
    },
    "android": {
      "package": "com.xxx.xx",
      "versionCode": 1,
      "adaptiveIcon": {
        "foregroundImage": "./assets/adaptive-icon.png",
        "backgroundColor": "#FFFFFF"
      },
    },
    "web": {
      "favicon": "./assets/favicon.png"
    }
  }
}

内容的提问来源于stack exchange,提问作者Hafiz Muhammad Bilal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 05:06:36