首页 > 解决方案 > GoogleSignInClient.signInIntent 崩溃 - 您应用的 AndroidManifest.xml 中的必需元数据标记不存在

问题描述

我使用 Google OAuth 让用户通过 Google 帐户登录到 android 应用程序。当用户点击 Google 登录按钮时,它会立即崩溃并显示以下信息

您应用的 AndroidManifest.xml 中的必需元数据标记不存在。您必须在 <application> 元素中有以下声明:<meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />

当它存在时,它不存在于 AndroidManifest 中。google_play_services_versions 值为 12451000,硬编码它不会改变任何东西

堆栈跟踪

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.mateuszsiedlecki.whatsthere, PID: 578
    java.lang.IllegalStateException: A required meta-data tag in your app's AndroidManifest.xml does not exist.  You must have the following declaration within the <application> element:     <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
        at com.google.android.gms.common.GooglePlayServicesUtilLight.isGooglePlayServicesAvailable(com.google.android.gms:play-services-basement@@17.1.1:17)
        at com.google.android.gms.common.GoogleApiAvailabilityLight.isGooglePlayServicesAvailable(com.google.android.gms:play-services-basement@@17.1.1:5)
        at com.google.android.gms.common.GoogleApiAvailability.isGooglePlayServicesAvailable(com.google.android.gms:play-services-base@@17.1.0:96)
        at com.google.android.gms.auth.api.signin.GoogleSignInClient.zzg(com.google.android.gms:play-services-auth@@18.0.0:9)
        at com.google.android.gms.auth.api.signin.GoogleSignInClient.getSignInIntent(com.google.android.gms:play-services-auth@@18.0.0:18)
        at com.mateuszsiedlecki.whatsthere.login.SocialLoginFragment.googleSignIn(SocialLoginFragment.kt:101)
        at com.mateuszsiedlecki.whatsthere.login.SocialLoginFragment.access$googleSignIn(SocialLoginFragment.kt:24)
        at com.mateuszsiedlecki.whatsthere.login.SocialLoginFragment$onViewCreated$2.onClick(SocialLoginFragment.kt:70)
        at android.view.View.performClick(View.java:7161)
        at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:967)
        at android.view.View.performClickInternal(View.java:7133)
        at android.view.View.access$3500(View.java:804)
        at android.view.View$PerformClick.run(View.java:27416)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:241)
        at android.app.ActivityThread.main(ActivityThread.java:7604)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:941)

代码

class SocialLoginFragment : Fragment() {

    val gso: GoogleSignInOptions = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
        .requestEmail()
        .requestProfile()
        .requestId()
        .build()
    private val facebookRequestedData = "id,first_name,last_name,email,picture,name"
    private var fbCallbackManager: CallbackManager = CallbackManager.Factory.create()


    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_social_login, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        FacebookSdk.sdkInitialize(this.context)

        LoginManager.getInstance().registerCallback(
            fbCallbackManager,
            object : FacebookCallback<LoginResult?> {
                override fun onSuccess(loginResult: LoginResult?) {
                    Log.d("login", "Facebook Login")
                    val fbUser = getFbUserData(loginResult!!.accessToken)
                    UserDataManager.user = fbUser
                    loginFinished()
                }

                override fun onCancel() {
                    Log.d("login", "Facebook Login Cancel")
                }

                override fun onError(exception: FacebookException) {
                    Log.d("login", "Facebook Login error")
                }
            }
        )


        val googleLoginButton = getView()?.findViewById<Button>(R.id.googleLogin)
        googleLoginButton?.setOnClickListener {
            googleSignIn()
        }

        val facebookLoginButton = getView()?.findViewById<Button>(R.id.facebookLogin)
        facebookLoginButton?.setOnClickListener {
            LoginManager.getInstance().logInWithReadPermissions(
                this,
                listOf("public_profile", "email")
            )
        }

        val emailLoginButton = getView()?.findViewById<Button>(R.id.emailLogin)
        emailLoginButton?.setOnClickListener {
            val intent = Intent(this.context, EmailLoginActivity::class.java)
            startActivity(intent)
        }

        val noLogin: Button = getView()?.findViewById<Button>(R.id.noLogin) as Button
        noLogin.setOnClickListener {
            (activity as LoginActivity?)?.openEmailFragment()
        }
    }


    private fun googleSignIn() {
        val mGoogleSignInClient: GoogleSignInClient = GoogleSignIn.getClient(
            this.context!!,
            gso
        )
        val signInIntent: Intent = mGoogleSignInClient.signInIntent // crashing here
        startActivityForResult(signInIntent, 1)
    }
...

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.mateuszsiedlecki.whatsthere">
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <application
        android:allowBackup="false"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <meta-data
            android:name="com.google.android.gms.version"
            android:value="@integer/google_play_services_version" />

        <activity android:name=".EmailLoginActivity" />
        <activity
            android:name=".osmMapsActivity"
            android:label="@string/title_activity_maps" />
        <activity android:name=".login.LoginActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <meta-data
            android:name="com.facebook.sdk.ApplicationId"
            android:value="@string/facebook_app_id" />
        
        <activity
            android:name="com.facebook.FacebookActivity"
            android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation"
            android:label="@string/app_name" />
        <activity
            android:name="com.facebook.CustomTabActivity"
            android:exported="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="@string/fb_login_protocol_scheme" />
            </intent-filter>
        </activity>


    </application>

</manifest>

标签: androidkotlin

解决方案


推荐阅读