Ответ 1
токен извлекается асинхронно при первом запуске приложения. Вы должны подождать, пока onTokenRefresh()
будет вызван в вашем FirebaseInstanceIdService
до того, как будет доступен доступ к токену.
Я использую FCM для предоставления уведомлений в своем приложении. Все работало хорошо, но теперь я понял, что, когда я устанавливаю свое приложение с помощью Android Studio (а не из GooglePlay), токен сначала пуст. Когда я закрываю приложение и перезапускаю его, токен больше не равен нулю. Что вызывает эту проблему и как ее избежать?
InstanceIDService:
public class InstanceIDService extends FirebaseInstanceIdService {
@Override
public void onTokenRefresh() {
String token = FirebaseInstanceId.getInstance().getToken();
registerToken(token);
}
private void registerToken(String token) {
OkHttpClient client = new OkHttpClient();
RequestBody body = new FormBody.Builder()
.add("Token",token)
.build();
Request request = new Request.Builder()
.url("url_to_registration_script")
.post(body)
.build();
try {
client.newCall(request).execute();
} catch (IOException e) {
e.printStackTrace();
}
}
}
В MainActivity:
FirebaseMessaging.getInstance().subscribeToTopic("topic");
String token = FirebaseInstanceId.getInstance().getToken();
Log.d("TOKEN", token);
Последний журнал возвращает null, когда приложение установлено и запускается в первый раз
Регистрация script:
<?php
if (isset($_POST["Token"])) {
$_uv_Token=$_POST["Token"];
$conn = mysqli_connect("localhost","user","pass","db") or die("Error connecting");
$q="INSERT INTO users (Token) VALUES ( '$_uv_Token') "
." ON DUPLICATE KEY UPDATE Token = '$_uv_Token';";
mysqli_query($conn,$q) or die(mysqli_error($conn));
mysqli_close($conn);
}
?>
токен извлекается асинхронно при первом запуске приложения. Вы должны подождать, пока onTokenRefresh()
будет вызван в вашем FirebaseInstanceIdService
до того, как будет доступен доступ к токену.
удалите приложение из эмулятора и запустите его снова, чтобы снова вызвать метод onTokenRefreshed.
Чтобы проверить, что вы уже зарегистрированы, и вы просто хотите узнать токен FCM
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
добавьте вышеприведенную строку в класс MyFirebaseMessagingService где угодно (в методе oncreate) и просто нажмите Toast или запустите файл refreshedToken.
Просто замените:
String token = instanceID.getToken();
с:
String token = instanceID.getToken($SENDER_ID, "FCM");
и он будет работать.
У меня была та же проблема. Я просмотрел много сообщений SO и других форумов, и я нашел решение, которое сработало для меня. В документации FCM используется этот метод для получения токена.
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
Я нашел сообщение в Интернете (я прошу прощения, я не помню, какой из них я нашел некоторое время назад), который использовал этот метод вместо этого:
String refreshedToken = FirebaseInstanceId.getInstance().getToken() (String authorizedEntity, String scope);
Документация FCM описывает первый метод как:
Вернуть главный токен для проекта Firebase по умолчанию.
В то время как второй описывается как
Возвращает токен, который разрешает Entity выполнять действие от имени приложения, идентифицированного с помощью идентификатора экземпляра. Это похоже на токен OAuth2, за исключением того, что он применяется к экземпляру приложения вместо пользователя. Например, чтобы получить токен, который можно использовать для отправки сообщений в приложение через FirebaseMessaging, установите идентификатор отправителя и установите "FCM".
Я искал, почему первый вызов метода занимает больше времени, чтобы вернуть токен, но я еще не нашел ответа. Надеюсь, это поможет.
Даже у меня была такая же проблема. Я дал инструкции Log для печати токена в onCreate моей активности запуска. Требуется время, чтобы обновить токен после удаления приложения. Вот почему вы получаете нуль. Вам нужно подождать немного, чтобы обновить токен.
Иногда могут возникать проблемы с сетью, даже если интернет работает нормально... проверьте класс FirebaseInstancId
определенный в файле Manifest в вашем проекте Android.
Я только что упал в одной и той же проблеме, и именно так я ее исправил. Вызовите блок где-нибудь в методе onCreate()
вашей деятельности. Я хочу отправить токен на свой сервер Parse, поэтому вы должны изменить его на основе ваших потребностей.
Это образец, который я выполнил.
private void subscribeUserToParse() {
String deviceToken = FirebaseInstanceId.getInstance().getToken();
if (TextUtils.isEmpty(deviceToken)) {
Intent intent = new Intent(this, MyFirebaseInstanceIDService.class);
startService(intent);
return;
}
User user = UserUtil.retrieveUserFromDB(mRealm);
String objectId = user.getParseObjectId();
if (!TextUtils.isEmpty(objectId)) {
ParseUtils.subscribeWithUsersObjectId(objectId, deviceToken);
}
}
Самая большая проблема, с которой я столкнулся после написания правильного кода: не последняя версия сервисов google play в build- gradle, Поэтому всегда используйте версию google-play-services, показанную firebase при настройке диалога
У меня была такая же проблема в устройстве Android 4.2. Итак, для решения проблемы сначала проверьте, есть ли у вашего сервиса в манифесте такой приоритет:
<service
android:name=".other.MyFirebaseInstanceIDService"
android:exported="false">
<intent-filter android:priority="1000">
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
Во-вторых, используйте широковещательное намерение, чтобы уведомить вашу MainActivity, которая изменила токен:
public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {
@Override
public void onTokenRefresh() {
// Get updated InstanceID token.
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
final Intent intent = new Intent("tokenReceiver");
final LocalBroadcastManager broadcastManager = LocalBroadcastManager.getInstance(this);
intent.putExtra("token",refreshedToken);
broadcastManager.sendBroadcast(intent);
}
Затем в MainActivity, в onCreate, добавьте это:
@Override
protected void onCreate(Bundle savedInstanceState) {
...
LocalBroadcastManager.getInstance(this).registerReceiver(tokenReceiver,
new IntentFilter("tokenReceiver"));
}
и в MainActivity добавьте новый BroadcastReceiver:
BroadcastReceiver tokenReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String token = intent.getStringExtra("token");
if(token != null)
{
Log.e("firebase", String.valueOf(token));
// send token to your server
}
}
};
Поскольку метод getToken()
устарел, вы должны заменить его слушателем.
Просто замените String token = FirebaseInstanceId.getInstance().getToken();
следующим фрагментом кода:
FirebaseInstanceId.getInstance().getInstanceId()
.addOnCompleteListener(new OnCompleteListener<InstanceIdResult>() {
@Override
public void onComplete(@NonNull Task<InstanceIdResult> task) {
if (!task.isSuccessful()) {
Log.w(TAG, "getInstanceId failed", task.getException());
return;
}
// Get new Instance ID token
String token = task.getResult().getToken();
// Log and toast
String msg = getString(R.string.msg_token_fmt, token);
Log.d(TAG, msg);
Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();
}
});
Вы можете найти официальную документацию Google здесь: https://firebase.google.com/docs/cloud-messaging/android/client
И хороший средний пост также поможет вам: https://medium.com/@cdmunoz/fcm-getinstance-gettoken-in-android-is-now-deprecated-how-to-fix-it-3922a94f4fa4