Ошибка обратного вызова для трансляции: result = CANCELED forIntent {act = com.google.android.c2dm.intent.RECEIVE pkg = com.flagg327.guicomaipu(есть дополнительные функции)}
Я получаю эту ошибку от Android Studio Android Monitor. Эта ошибка появляется, когда я отправляю push-уведомление через GCM на реальном устройстве, и приложение еще не запущено или было остановлено. Вчера все работает нормально, сегодня вообще не работает (работает, только если приложение работает в фоновом режиме или на переднем плане).
Я думаю, что это может быть ошибка AndroidManifest
, но я устал искать проблему и ничего не могу найти.
манифеста
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.flagg327.guicomaipu">
...
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
...
<!--GOOGLE CLOUD MESSAGE-->
<receiver
android:name="com.google.android.gms.gcm.GcmReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<!-- for Gingerbread GSF backward compat -->
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.flagg327.guicomaipu" />
</intent-filter>
</receiver>
<service
android:name="com.flagg327.guicomaipu.gcm.RegistrationService"
android:exported="false" />
<service
android:name="com.flagg327.guicomaipu.gcm.TokenRefreshListenerService"
android:exported="false">
<intent-filter>
<action
android:name="com.google.android.gms.iid.InstanceID" />
</intent-filter>
</service>
<service
android:name="com.flagg327.guicomaipu.gcm.NotificacionsListenerService"
android:exported="false" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
</aplication>
<permission
android:name="com.flagg327.guicomaipu.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.flagg327.guicomaipu.permission.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
TokenRefreshListenerService.java
Обновления "токенов" регистрации каждый день. Это потому, что каждое приложение для Android, использующее GCM, должно иметь InstanceIDListenerService, который управляет этими обновлениями.
public class TokenRefreshListenerService extends InstanceIDListenerService{
@Override
public void onTokenRefresh() {
// Launch the registration process.
Intent i = new Intent(this, RegistrationService.class);
startService(i);
}
}
NotificacionsListenerService.java
GCM автоматически отображает push-уведомления, но только если связанное приложение имеет GCMListenerService
public class NotificacionsListenerService extends GcmListenerService {
@Override
public void onMessageReceived(String from, Bundle data) {
Log.d("A", "onMessageReceived()");
// Do something
}
}
RegistrationService.java
GCM определяет устройства Android, использующие регистрационные карточки ( "токены" ). Мое приложение должно иметь возможность регистрироваться на каждом устройстве Android, на котором оно установлено.
public class RegistrationService extends IntentService {
/**
* Constructor
*/
public RegistrationService() {
super("RegistrationService");
}
@Override
protected void onHandleIntent(Intent intent) {
// Generate or download the registration 'token'.
InstanceID myID = InstanceID.getInstance(this);
String registrationToken = null;
try {
// Get the registration 'token'.
registrationToken = myID.getToken(
getString(R.string.gcm_defaultSenderId),
GoogleCloudMessaging.INSTANCE_ID_SCOPE,
null
);
// Subscribe to a topic. The app is able now to receive notifications from this topic.
GcmPubSub subscription = GcmPubSub.getInstance(this);
subscription.subscribe(registrationToken, "/topics/guico_maipu_topic", null);
} catch (IOException e) {
e.printStackTrace();
}
Log.e("Registration Token", registrationToken);
}
}
Ошибка
Эта ошибка появляется, когда я отправляю push-уведомление через python.
09-13 21:21:44.800 1851-1851/? W/GCM-DMM: broadcast intent callback: result=CANCELLED forIntent { act=com.google.android.c2dm.intent.RECEIVE pkg=com.flagg327.guicomaipu (has extras) }
Вчера работала... Любая идея? Чем вы на какое-то время.
Ответы
Ответ 1
Я получил ту же ошибку
09-13 21:21:44.800 1851-1851/? W/GCM-DMM: broadcast intent callback: result=CANCELLED forIntent { act=com.google.android.c2dm.intent.RECEIVE pkg=com.XXX.XXX (has extras) }
после убийства приложения.
После некоторых исследований я понял, что это всего лишь "Debug-Issue". "Подписанный APK" корректно обрабатывает трансляцию, даже если приложение было отключено.
Надеюсь, что это поможет!
Ответ 2
Поскольку ни один из ответов не дает официальной ссылки, я решил спросить команду Firebase и получил официальный ответ от них.
Похоже, у вас есть проблема, когда ваше приложение было принудительно остановлено или убито. На самом деле, это работает как задумано. Платформа Android рекомендует, чтобы приложения, которые были остановлены (то есть убиты/принудительно остановлены из настроек), не должны запускаться без явного взаимодействия с пользователем. FCM следует этой рекомендации, и поэтому ее услуги также не будут запущены. Это также означает, что сообщения не будут получены (FirebaseMessagingService не будет вызываться), когда приложение находится в состоянии "убит". Вот несколько полезных ссылок, чтобы вы могли лучше понять эту тему: https://developer.android.com/about/versions/android-3.1#launchcontrols https://github.com/firebase/quickstart-android/issues/368 # issuecomment-343567506
В сумме:
- приложение, убитое пользователем (из настроек/принудительной остановки), будет помечено флажком, который не сможет автоматически запускать любую службу, включающую службу сообщений firebase. Это не то же самое с приложением, убитым системой или проведением из недавнего приложения.
- Однако на некоторых ПЗУ от VIVO или ONEPLUS функция смахивания (нажмите кнопку недавнего приложения/смахивание) неправильно реализована, чтобы быть похожей с настройками/принудительной остановкой. Из-за этого служба сообщений Firebase не может запуститься.
- Вопрос был поднят здесь и во многих местах. Команда FCM знает об этой проблеме и работает над ней
ПРИМЕЧАНИЕ: даже вопрос касается GCM, но FCM выдает точно такую же ошибку в заголовке вопроса.
Ответ 3
Итак... Я решил проблему. Проблема заключалась в том, что устройство не зарегистрировано для получения GCM, если приложение закрыто принудительно или если приложение не было открыто с момента загрузки устройства. Решение прост, зарегистрируйте устройство при загрузке телефона. Для этого я внедрил BroadcastReceiver
и начал регистрацию процесса внутри него.
Модификации:
Добавлен в AndroidManifest
<receiver android:name="com.flagg327.guicomaipu.gcm.OnBootBroadcastReceiver">
<intent-filter >
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.HOME" />
</intent-filter>
</receiver>
OnBootBroadcastReceiver.java
public class OnBootBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent("com.flagg327.guicomaipu.gcm.RegistrationService");
i.setClass(context, RegistrationService.class);
context.startService(i);
}
}
Таким образом, при загрузке устройство зарегистрируется на сервере GCM и будет иметь возможность получать любые push-уведомления с моего сервера. Надеюсь, это полезно.
Ответ 4
После того, как это произошло, выяснилось, что это произойдет, если вы убьете приложение из Android Studio.
Если вы откроете приложение из панели запуска и проведите по нему, ваше приложение все равно получит уведомления.
(Протестировано на OnePlus One с FCM не GCM)
Ответ 5
Это потому, что ваше приложение оптимизировано для использования батареи, чтобы отключить его и получать уведомления, даже если ваше приложение не работает в фоновом режиме
Добавьте это разрешение для манифеста
<uses-permission
android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
При первом запуске вашего приложения пользователь запрашивает разрешение на игнорирование этого приложения для оптимизации заряда батареи.
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Intent intent = new Intent();
String packageName = getPackageName();
PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
if (!pm.isIgnoringBatteryOptimizations(packageName)) {
intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
intent.setData(Uri.parse("package:" + packageName));
startActivity(intent);
}
}
Ответ 6
Я тоже столкнулся с проблемой. Когда я удаляю приложение из стека, push-уведомление не получено. После многих Google я обнаружил, что у немногих телефонов есть функция оптимизации батареи, и это отключит фоновый запуск приложений. Когда я включаю, что мое приложение также может работать в фоновом режиме. Push-уведомление работает нормально. Только небольшое приложение, такое как "Приложение" и т.д., Может иметь только функцию включения по умолчанию. Вы можете посмотреть этот ниже URL.
https://github.com/firebase/quickstart-android/issues/89
Ответ 7
Для меня это был случай, когда была предоставлена функция автозапуска для моего приложения. Зайдите в настройки, выберите установленное приложение и включите автозапуск. Это решит проблему.
Ответ 8
Для решения этой проблемы нет официального решения, но здесь есть обходной путь, который вы можете использовать
2 вещи, которые вам нужны для управления автозапуском и оптимизацией батареи, тогда ваша проблема будет решена
- Автозапуск
Вам нужно запросить разрешение на автозапуск для запуска приложения в фоновом режиме после того, как пользователь был убит
Вы можете использовать ниже намерения для этого
private void enableAutoStart() {
if (Build.BRAND.equalsIgnoreCase("xiaomi")) {
new MaterialDialog.Builder(MainActivity.this).title("Enable AutoStart")
.content(
"Please allow QuickAlert to always run in the background,else our services can't be accessed when you are in distress")
.theme(Theme.LIGHT)
.positiveText("ALLOW")
.onPositive(new MaterialDialog.SingleButtonCallback() {
@Override
public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.miui.securitycenter",
"com.miui.permcenter.autostart.AutoStartManagementActivity"));
startActivity(intent);
}
})
.show();
} else if (Build.BRAND.equalsIgnoreCase("Letv")) {
new MaterialDialog.Builder(MainActivity.this).title("Enable AutoStart")
.content(
"Please allow QuickAlert to always run in the background,else our services can't be accessed when you are in distress")
.theme(Theme.LIGHT)
.positiveText("ALLOW")
.onPositive(new MaterialDialog.SingleButtonCallback() {
@Override
public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.letv.android.letvsafe",
"com.letv.android.letvsafe.AutobootManageActivity"));
startActivity(intent);
}
})
.show();
} else if (Build.BRAND.equalsIgnoreCase("Honor")) {
new MaterialDialog.Builder(MainActivity.this).title("Enable AutoStart")
.content(
"Please allow QuickAlert to always run in the background,else our services can't be accessed when you are in distress")
.theme(Theme.LIGHT)
.positiveText("ALLOW")
.onPositive(new MaterialDialog.SingleButtonCallback() {
@Override
public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.huawei.systemmanager",
"com.huawei.systemmanager.optimize.process.ProtectActivity"));
startActivity(intent);
}
})
.show();
} else if (Build.MANUFACTURER.equalsIgnoreCase("oppo")) {
new MaterialDialog.Builder(MainActivity.this).title("Enable AutoStart")
.content(
"Please allow QuickAlert to always run in the background,else our services can't be accessed when you are in distress")
.theme(Theme.LIGHT)
.positiveText("ALLOW")
.onPositive(new MaterialDialog.SingleButtonCallback() {
@Override
public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
try {
Intent intent = new Intent();
intent.setClassName("com.coloros.safecenter",
"com.coloros.safecenter.permission.startup.StartupAppListActivity");
startActivity(intent);
} catch (Exception e) {
try {
Intent intent = new Intent();
intent.setClassName("com.oppo.safe",
"com.oppo.safe.permission.startup.StartupAppListActivity");
startActivity(intent);
} catch (Exception ex) {
try {
Intent intent = new Intent();
intent.setClassName("com.coloros.safecenter",
"com.coloros.safecenter.startupapp.StartupAppListActivity");
startActivity(intent);
} catch (Exception exx) {
}
}
}
}
})
.show();
} else if (Build.MANUFACTURER.contains("vivo")) {
new MaterialDialog.Builder(MainActivity.this).title("Enable AutoStart")
.content(
"Please allow QuickAlert to always run in the background.Our app runs in background to detect when you are in distress.")
.theme(Theme.LIGHT)
.positiveText("ALLOW")
.onPositive(new MaterialDialog.SingleButtonCallback() {
@Override
public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
try {
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.iqoo.secure",
"com.iqoo.secure.ui.phoneoptimize.AddWhiteListActivity"));
startActivity(intent);
} catch (Exception e) {
try {
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.vivo.permissionmanager",
"com.vivo.permissionmanager.activity.BgStartUpManagerActivity"));
startActivity(intent);
} catch (Exception ex) {
try {
Intent intent = new Intent();
intent.setClassName("com.iqoo.secure",
"com.iqoo.secure.ui.phoneoptimize.BgStartUpManager");
startActivity(intent);
} catch (Exception exx) {
ex.printStackTrace();
}
}
}
}
})
.show();
}
}
public boolean checkServiceRunning() {
ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(
Integer.MAX_VALUE)) {
if ("com.sac.speechdemo.MyService".equals(service.service.getClassName())) {
return true;
}
}
return false;
}
Оптимизация заряда аккумулятора/Без фона/Режим DOZE
для управления оптимизацией батареи используйте приведенный ниже код с разрешения, он будет работать на стоковой Android
private void askIgnoreOptimization() {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, IGNORE_BATTERY_OPTIMIZATION_REQUEST);
} else {
openNextActivity();
}
}
а для кастомной ОС вам нужно перенаправить пользователя для разрешения оптимизации батареи, как показано ниже
для устройств OPPO
intent.setClassName("com.coloros.oppoguardelf", "com.coloros.powermanager.fuelgaue.PowerConsumptionActivity"); startActivity(intent);
звоните выше намерения, он перенаправит вас к параметру батареи "Отключить фоновое замораживание, оптимизацию ненормальных приложений и Doze от \" Энергосбережение → youAPP "
Примечание. После того, как вы вызовете вышеуказанное намерение, у вас могут появиться различные варианты отключения параметров экономии заряда батареи.
Этот параметр оптимизации аккумулятора можно найти в разделе "Параметры аккумулятора" в настройках устройства, он зависит от ПЗУ.