除了我的设备以外,其他设备上的FCM令牌检索失败

时间:2018-11-19 18:13:40

标签: android firebase android-studio push-notification firebase-cloud-messaging

我正在做演示,在某些情况下检查呼叫状态并发送FCM通知,我主要在我的Xiaomi Redmi 5 Plus(API 27)上进行测试,并且工作正常,但是当我尝试在其他设备上测试三星S6时Edge(API 24),Samsung A5(API 21)和仿真器(API 26及更低版本)不愿意运行。我的注册令牌有问题,其他设备为空。我也尝试过onNewToken(),但事实并非如此。我不知道为什么它会在我的设备以外的其他设备上崩溃?

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.aliaskarurakov.android.democall, PID: 19586
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.aliaskarurakov.android.democall/com.aliaskarurakov.android.democall.MainActivity}: java.lang.NullPointerException: value == null
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2808)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2873)
        at android.app.ActivityThread.access$900(ActivityThread.java:181)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1482)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:145)
        at android.app.ActivityThread.main(ActivityThread.java:6145)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
     Caused by: java.lang.NullPointerException: value == null
        at okhttp3.FormBody$Builder.add(FormBody.java:120)
        at com.aliaskarurakov.android.democall.MainActivity.registerToken(MainActivity.java:134)
        at com.aliaskarurakov.android.democall.MainActivity.onCreate(MainActivity.java:48)
        at android.app.Activity.performCreate(Activity.java:6374)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1119)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2752)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2873) 
        at android.app.ActivityThread.access$900(ActivityThread.java:181) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1482) 
        at android.os.Handler.dispatchMessage(Handler.java:102) 
        at android.os.Looper.loop(Looper.java:145) 
        at android.app.ActivityThread.main(ActivityThread.java:6145) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at java.lang.reflect.Method.invoke(Method.java:372) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194) 
I/Process: Sending signal. PID: 19586 SIG: 9
Application terminated.

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.aliaskarurakov.android.democall">
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <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>
        </activity>
        <service
            android:name=".MyFirebaseMessagingService">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT"/>
            </intent-filter>
        </service>
    </application>
</manifest>

build.gradle(app)

apply plugin: 'com.android.application'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.aliaskarurakov.android.democall"
        minSdkVersion 19
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support:design:28.0.0'
    implementation 'com.android.support:support-v4:28.0.0'
    implementation 'com.android.support:support-media-compat:28.0.0'
    implementation 'com.android.support:recyclerview-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    implementation 'com.google.firebase:firebase-core:16.0.5'
    implementation 'com.google.firebase:firebase-messaging:17.3.4'
    implementation 'com.squareup.okhttp3:okhttp:3.11.0'
}

apply plugin: 'com.google.gms.google-services'

build.gradle

buildscript {

    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.2.1'
        classpath 'com.google.gms:google-services:4.2.0'
    }
}

allprojects {
    repositories {
        google()
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

MainActivity.java

public class MainActivity extends AppCompatActivity {

    Button mButton;

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

        mButton = (Button)findViewById(R.id.send);

        final String token = FirebaseInstanceId.getInstance().getToken();
        //Toast.makeText(getApplicationContext(), token, Toast.LENGTH_SHORT).show();

        TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);

        String phoneState = String.valueOf(telephonyManager.getCallState());
        //Toast.makeText(getApplicationContext(), phoneState, Toast.LENGTH_LONG).show();

        registerToken(token, phoneState);

        PhoneStateListener callStateListener = new PhoneStateListener() {
            public void onCallStateChanged(int state, String incomingNumber) {
                if (state == TelephonyManager.CALL_STATE_RINGING) {
                    updateState(token, String.valueOf(state));

                }
                if (state == TelephonyManager.CALL_STATE_OFFHOOK) {
                    updateState(token, String.valueOf(state));
                }

                if (state == TelephonyManager.CALL_STATE_IDLE) {
                    updateState(token, String.valueOf(state));
                }
            }
        };
        telephonyManager.listen(callStateListener,PhoneStateListener.LISTEN_CALL_STATE);

        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                sendNotification();
            }
        });
    }

    private void updateState(String token, String state) {
        OkHttpClient client = new OkHttpClient();
        RequestBody body = new FormBody.Builder()
                .add("token", token)
                .add("state", state)
                .build();

        Request request = new Request.Builder()
                .url("http://update_state.php")
                .post(body)
                .build();

        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.d("OkHttp", call.toString());
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response.isSuccessful()) {
                    String responseStr = response.body().string();
                    Log.d("OkHttp", responseStr);
                }
            }
        });
    }

    public void sendNotification() {
        OkHttpClient client = new OkHttpClient();
        RequestBody body = new FormBody.Builder()
                .add("send", "send")
                .build();

        Request request = new Request.Builder()
                .url("http://send_notification.php")
                .post(body)
                .build();

        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.d("OkHttp", call.toString());
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response.isSuccessful()) {
                    String responseStr = response.body().string();
                    Log.d("OkHttp", responseStr);
                }
            }
        });

    }

    private static void registerToken(String token, String state) {
        OkHttpClient client = new OkHttpClient();
        RequestBody body = new FormBody.Builder()
                .add("token", token)
                .add("state", state)
                .build();

        Request request = new Request.Builder()
                .url("http://register_user.php")
                .post(body)
                .build();

        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.d("OkHttp", call.toString());
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response.isSuccessful()) {
                    String responseStr = response.body().string();
                    Log.d("OkHttp", responseStr);
                }
            }
        });

    }

}

MyFirebaseMessagingService.java

public class MyFirebaseMessagingService extends FirebaseMessagingService {

    NotificationHelper helper;

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {


        if (Build.VERSION.SDK_INT >= 26) {
            showNotification26(remoteMessage.getData().get("message"), remoteMessage.getData().get("title"));
        } else {
            showNotification(remoteMessage.getData().get("message"), remoteMessage.getData().get("title"));
        }
    }

    private void showNotification(String message, String title) {
        Intent i = new Intent(this, MainActivity.class);
        i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, i, PendingIntent.FLAG_UPDATE_CURRENT);
        Uri defaultSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
                .setAutoCancel(true)
                .setSound(defaultSound)
                .setContentTitle(title)
                .setContentText(message)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentIntent(pendingIntent);

        NotificationManager manager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
        manager.notify(0, builder.build());
    }

    @RequiresApi(api = Build.VERSION_CODES.O)
    private void showNotification26(String message, String title) {
        Notification.Builder builder = null;
        helper = new NotificationHelper(this);
        builder = helper.getAndroidChannelNotification(message, title);

        if (builder != null){
            helper.getManager().notify(0, builder.build());
        }
    }

}

1 个答案:

答案 0 :(得分:0)

根据documentation getToken()调用返回:

  • 主令牌;如果令牌尚不可用,则为null

不建议使用此方法,而推荐使用getInstanceId(),该方法返回一个Task<InstanceIdResult>,因此您可以在主线程上使用它并获取结果:

FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(MainActivity.this, new OnSuccessListener<InstanceIdResult>() {
     @Override
     public void onSuccess(InstanceIdResult instanceIdResult) {
         String token = instanceIdResult.getToken();
         Log.d("Token", token);
     }  
});

或者,您也可以在FirebaseMessagingService中重写onNewToken(String token)方法以获取令牌:

public class MyFirebaseMessagingService extends FirebaseMessagingService {

    @Override
    public void onNewToken(String token) {
        super.onNewToken(token);
        Log.d("Token", token);
    }
}