FirebaseInstanceIdService 的 getToken 方法返回 null

5

我正在尝试为我的应用程序添加FCM通知,但由于某些原因

FirebaseInstanceId.getInstance().getToken();

返回 null。

由于没有获取到任何堆栈跟踪,我的最佳猜测是 FirebaseInstanceIdService 没有工作。

  • Google Play Services 版本:9.6.1
  • Firebase-messaging 版本:9.6.1
  • 从 Firebase 控制台添加了 JSON 配置文件(尝试将两个客户端放在一个文件中,一个用于调试,另一个用于发布构建,并为各自的构建分别添加了两个文件)

我在模块的 Gradle 脚本底部应用了 Google Services 插件, 在项目的根 Gradle 脚本中包含了 Google 服务。

从官方文档中创建了两个服务:

public class MyFirebaseInsanceIDService  extends FirebaseInstanceIdService {

private static final String TAG = "MyFirebaseIIDService";

@Override
public void onTokenRefresh() {
    // Get updated InstanceID token.
    String refreshedToken = FirebaseInstanceId.getInstance().getToken();
    PreferencesHelper.putSharedPreferencesString(Constants.User.PUSH_NOTIFICATIONS, refreshedToken);

    Log.e("TOKEN", "Token: " + FirebaseInstanceId.getInstance().getToken());
}

以及清单文件:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.fc.test">

<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.INTERNET" />

<application
    android:name="fctest"
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="${appName}${appNameSuffix}"
    android:supportsRtl="true"
    android:theme="@style/AppTheme"
    tools:node="replace">

    <service
        android:name="com.fc.test.MyFirebaseInsanceIDService"
        android:enabled="true"
        android:exported="true">
        <intent-filter>
            <action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
        </intent-filter>
    </service>

    <service
        android:name="com.fc.test.MyFirebaseMessagingService"
        android:enabled="true"
        android:exported="true">
        <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT" />
        </intent-filter>
    </service>

    <activity
        android:name="com.fc.test.view.splash.Splash"
        android:screenOrientation="portrait"
        android:theme="@style/AppTheme.CenterAnimation">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

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

</application>

根Gradle:

buildscript {
    repositories {
        jcenter()
        maven { url 'https://maven.fabric.io/public' }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.1.2'
        classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
        //noinspection GradleDynamicVersion
        classpath 'io.fabric.tools:gradle:1.+'
        classpath 'com.google.gms:google-services:3.0.0'
    }
}

allprojects {
    repositories {
        jcenter()
        maven { url "http://dl.bintray.com/drummer-aidan/maven" }
        maven { url "https://maven.fabric.io/public" }
        maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
        maven { url "https://jitpack.io" }
    }
}

ext {
    buildToolsVersion = '24.0.1'
    compileSdkVersion = 24
    minSdkVersion = 15
    targetSdkVersion = 24
    supportLibraryVersion = '24.2.1'
}

这段内容是关于Gradle模块的主要部分。

    dependencies {
    final PLAY_SERVICES_VERSION = '9.6.1'
    final SUPPORT_LIBRARY_VERSION = '24.2.1'
    final RETROFIT_VERSION = '2.1.0'
    final DAGGER_VERSION = '2.5'
    final DEXMAKER_VERSION = '1.4'
    final HAMCREST_VERSION = '1.3'
    final ESPRESSO_VERSION = '2.2.1'
    final RUNNER_VERSION = '0.4'
    final BUTTERKNIFE_VERSION = '8.1.0'
    def daggerCompiler = "com.google.dagger:dagger-compiler:$DAGGER_VERSION"
    def jUnit = "junit:junit:4.12"
    def mockito = "org.mockito:mockito-core:1.10.19"
    // App Dependencies
    compile "com.google.android.gms:play-services-gcm:$PLAY_SERVICES_VERSION"
    compile "com.google.firebase:firebase-messaging:$PLAY_SERVICES_VERSION"
    compile "com.android.support:appcompat-v7:$SUPPORT_LIBRARY_VERSION"
    compile "com.android.support:recyclerview-v7:$SUPPORT_LIBRARY_VERSION"
    compile "com.android.support:cardview-v7:$SUPPORT_LIBRARY_VERSION"
    compile "com.android.support:design:$SUPPORT_LIBRARY_VERSION"
    compile "com.android.support:support-annotations:$SUPPORT_LIBRARY_VERSION"
    compile "com.android.support:support-v4:$SUPPORT_LIBRARY_VERSION"
    compile "com.squareup.retrofit2:retrofit:$RETROFIT_VERSION"
    compile "com.squareup.retrofit2:converter-gson:$RETROFIT_VERSION"
    compile "com.squareup.retrofit2:adapter-rxjava:$RETROFIT_VERSION"
    compile "com.jakewharton:butterknife:$BUTTERKNIFE_VERSION"
    compile('com.crashlytics.sdk.android:crashlytics:2.6.5@aar') {
        transitive = true;
    }
}
apply plugin: 'com.google.gms.google-services
  • 请注意,我在根应用程序标签中使用了tools:node="replace"。 由于FirebaseInstanceIdService和我的FirebaseInstanceService具有相同的意图过滤器,因此是否有可能未将其添加到清单中而未被调用?

因此,我的问题是官方文档或我的实现是否存在问题,导致实例令牌为空?


1
请检查 Firebase 控制台项目设置中 Cloud Messaging 选项卡上显示的“发送者 ID”是否与您的 google-services.json 文件中包含的“project_number”匹配。 - Bob Snyder
@qbix 嗯,我在使用Braintree SDK时也遇到了同样的问题,因为清单合并器没有将他们的活动合并到我的清单中。而且,由于我有多个库在根应用程序标签中定义了android:label,所以我的构建失败了。我通过手动将他们的Activity添加到我的清单中来解决了Braintree的问题,我会尝试挖掘默认的FCM接收器并手动将它们包含在清单中。 - Ivan Milisavljevic
嗨@qbix,清单中不需要tools:node="replace"。你为什么需要它?很可能它会阻止清单合并。 出于好奇,你为什么要使用那个标签? - Diego Giorgini
@DiegoGiorgini:你的评论是针对我,但应该是发给@Ivan的。他将不得不解释为什么要使用tools:node="replace"。这是问题的原因,他在下面简要描述了。 - Bob Snyder
@DiegoGiorgini 我的项目中有多个库,其中一些在其清单文件的应用程序标签中定义了应用程序属性(图标、标签等...)。由于这些属性在构建时会产生冲突,我必须使用顶层清单文件(我的应用程序清单)中定义的值替换低级清单文件(库清单文件)中的每个冲突,因此使用 tools:node="replace"。更多信息请参见 https://developer.android.com/studio/build/manifest-merge.html。 - Ivan Milisavljevic
显示剩余4条评论
4个回答

8

在研究 FCM 的旧实现和生成的清单后,我现在可以说,清单合并是问题所在。

解决此问题的方法是将这些类手动添加到应用程序的清单中。

 <activity
        android:name="com.google.android.gms.common.api.GoogleApiActivity"
        android:exported="false"
        android:theme="@android:style/Theme.Translucent.NoTitleBar" />

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

    <service
        android:name="com.google.firebase.messaging.FirebaseMessagingService"
        android:exported="true" >
        <intent-filter android:priority="-500" >
            <action android:name="com.google.firebase.MESSAGING_EVENT" />
        </intent-filter>
    </service>

    <receiver
        android:name="com.google.firebase.iid.FirebaseInstanceIdReceiver"
        android:exported="true"
        android:permission="com.google.android.c2dm.permission.SEND" >
        <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
            <action android:name="com.google.android.c2dm.intent.REGISTRATION" />

            <category android:name="com.fc.debug" />
        </intent-filter>
    </receiver>


    <receiver
        android:name="com.google.firebase.iid.FirebaseInstanceIdInternalReceiver"
        android:exported="false" />
    <!--

    -->
    <service
        android:name="com.google.firebase.iid.FirebaseInstanceIdService"
        android:exported="true" >
        <intent-filter android:priority="-500" >
            <action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
        </intent-filter>
    </service>

    <provider
        android:name="com.google.firebase.provider.FirebaseInitProvider"
        android:authorities="com.fc.debug.firebaseinitprovider"
        android:exported="false"
        android:initOrder="100" />

    <receiver
        android:name="com.google.android.gms.measurement.AppMeasurementReceiver"
        android:enabled="true" >
        <intent-filter>
            <action android:name="com.google.android.gms.measurement.UPLOAD" />
        </intent-filter>
    </receiver>

    <service
        android:name="com.google.android.gms.measurement.AppMeasurementService"
        android:enabled="true"
        android:exported="false" />

2
在迁移过程中,我遇到了一个问题,就是没有收到任何通知。为解决这个问题,如果您的GCM正常工作,请在获取Firebase令牌时不要忘记包含您的发送者ID。要查询此ID,您需要导航到Firebase项目并单击“项目名称”。单击设置图标,然后选择“项目设置”菜单。选择“Could Messaging”选项卡,并在页面上使用发送者ID。
当说要编写以下代码时:
     token = FirebaseInstanceId.getInstance().getToken();

你需要使用这个:
     token = FirebaseInstanceId.getInstance().getToken("YOUR_SENDER_ID", "FCM");

对我来说有效,希望这可以帮助你 ;)


1
这对我有用:

此代码适用于我:

String token = FirebaseInstanceId.getInstance().getInstanceId().getResult().getToken();

-1

首先生成 "google-services.json" 文件,并将其添加到您的 Android Studio 中,就像这样 projectFolder/APP/google-services.json

在顶层 build.gradle 中添加 classpath

 dependencies {
        classpath 'com.android.tools.build:gradle:2.1.2'
        classpath 'com.google.gms:google-services:3.0.0'
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }

在应用的build.gradle中添加以下插件和依赖项。
apply plugin: 'com.google.gms.google-services'
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:24.0.0'
    compile 'com.google.firebase:firebase-core:9.4.0'
    compile 'com.google.firebase:firebase-messaging:9.4.0'
}

在你的Java文件中添加以下Firebase服务

FirebaseIDService.java

package com.galleonsoft.firebase.push;

import android.util.Log;

import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.FirebaseInstanceIdService;

public class FirebaseIDService extends FirebaseInstanceIdService {
    private static final String TAG = "FirebaseIDService";

    @Override
    public void onTokenRefresh() {
        // Get updated InstanceID token.
        String refreshedToken = FirebaseInstanceId.getInstance().getToken();
        Log.d(TAG, "Refreshed token: " + refreshedToken);

        // TODO: Implement this method to send any registration to your app's servers.
        sendRegistrationToServer(refreshedToken);
    }

    private void sendRegistrationToServer(String token) {
        // Add custom implementation, as needed.
    }
}

MyFirebaseMessagingService.java

package com.galleonsoft.firebase.push;

import android.util.Log;

import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;

public class MyFirebaseMEssagingService extends FirebaseMessagingService {
    private static final String TAG = "FCM Service";
    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        // TODO: Handle FCM messages here.
        // If the application is in the foreground handle both data and notification messages here.
        // Also if you intend on generating your own notifications as a result of a received FCM
        // message, here is where that should be initiated.
        Log.d(TAG, "From: " + remoteMessage.getFrom());
        Log.d(TAG, "Notification Message Body: " + remoteMessage.getNotification().getBody());
    }
}

在你的 AndroidMainifest.xml 文件中添加服务。
<service android:name=".MyFirebaseMEssagingService">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT"/>
    </intent-filter>
</service>

<service android:name=".FirebaseIDService">
    <intent-filter>
        <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
    </intent-filter>
</service>

1
我已经完成了所有这些,顺便说一下,你的示例中有一个错误。'apply plugin: 'com.google.gms.google-services'' 应该放在应用程序模块的底部。 - Ivan Milisavljevic
请在清单文件中添加以下代码以获取网络权限: <uses-permission android:name="android.permission.INTERNET" /> - Jigar Patel
谢谢 :) 但我也有那个。 - Ivan Milisavljevic
在两个文件中添加Gradle代码。从Firebase获取google-services.json文件并放置在app文件夹中。 - Jigar Patel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接