Сообщение GCM получено, но не отображается. Результат широковещательного приемника = ОТМЕНА. Принудительная остановка службы.

Я реализовал обмен сообщениями GCM в своем приложении и на сервере, и все работает нормально, но не на каждом телефоне!

Основная проблема заключается в следующем:

  • Когда приложение открыто, я получаю сообщение GCM и генерирую уведомление, как и предполагалось, но когда приложение закрывается, я вижу (через LOGCAT), что сообщение было получено, но отменено -> «Приемник вещания, результат = ОТМЕНА».

  • Следующее, что я не могу заставить свои службы приложений работать в фоновом режиме. Пока я «закрываю» свое приложение из меню «последние действия», оно также останавливается в фоновом режиме (в разделе «Настройки» -> «Приложения» -> «MY_APP» -> принудительная остановка отключена).

Я провел много исследований и думаю, что причина может заключаться в том, что Huawei P8 (основное тестовое устройство) принудительно автоматически закрывает все приложения, когда вы смахиваете их с вкладки «Недавние действия». Но если это так, другие приложения, такие как «Facebook», «Viber» и т. д., не будут отправлять мне push-уведомления.

Манифест.xml

<receiver
        android:name="com.happyhour.gcm.GcmBroadcastReceiver"
        android:permission="com.google.android.c2dm.permission.SEND">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED"/>
            <action android:name="android.intent.action.REBOOT"/>
            <action android:name="android.intent.action.PACKAGE_REPLACED"/>
            <action android:name="android.intent.action.BATTERY_CHANGED"/>
            <action android:name="android.intent.action.USER_PRESENT"/>
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />                
            <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
            <category android:name="com.happyhour.main" />
        </intent-filter>
    </receiver>
    <service
        android:name="com.happyhour.gcm.GcmIntentService" >
    </service>

    <receiver android:name="com.happyhour.gcm.UpdateReceiver">
        <intent-filter>
            <action android:name="android.intent.action.PACKAGE_REPLACED" />
            <action android:name="android.intent.action.PACKAGE_INSTALL"/>
            <data android:path="com.happyhour.main"
                 android:scheme="package" />
        </intent-filter>
    </receiver>

GCMBroadCastReceiver

public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {



@Override
public void onReceive(Context context, Intent intent) {
    // TODO Auto-generated method stub

    Log.i("GcmBroadcast",intent.getExtras().toString());


    SharedPreferences settings = context.getSharedPreferences("MyPrefsFile", 0);



        if (settings.getBoolean("my_first_time", true)) {
            //the app is being launched for first time, do something        

                  //do nothing

            // record the fact that the app has been started at least once
            settings.edit().putBoolean("my_first_time", false).commit(); 
        }else{
            ComponentName comp = new ComponentName(context.getPackageName(),
                   GcmIntentService.class.getName());
                // Start the service, keeping the device awake while it is launching.

            startWakefulService(context, (intent.setComponent(comp)));
            setResultCode(Activity.RESULT_OK);
        }

    }
}

GCMIntentService

public class GcmIntentService extends IntentService {

private String TAG = "GcmIntent";
public static final int NOTIFICATION_ID = 1;
private NotificationManager mNotificationManager;
NotificationCompat.Builder builder;

public GcmIntentService() {
    super("GcmIntentService");
}

@Override
public void onCreate(){
    super.onCreate();
}


@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    onHandleIntent(intent);
    return START_STICKY;
}



@Override
protected void onHandleIntent(Intent intent) {
    Bundle extras = intent.getExtras();
    GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
    // The getMessageType() intent parameter must be the intent you received
    // in your BroadcastReceiver.
    Log.i(TAG, "Received: " + extras.toString());
    String messageType = gcm.getMessageType(intent);

    Log.i(TAG, "Message type:" + messageType);
    if (!extras.isEmpty()) {  // has effect of unparcelling Bundle
        /*
         * Filter messages based on message type. Since it is likely that GCM
         * will be extended in the future with new message types, just ignore
         * any message types you're not interested in, or that you don't
         * recognize.
         */
         if (GoogleCloudMessaging.
                MESSAGE_TYPE_MESSAGE.equals(messageType)) {
            Log.i(TAG, "Completed work @ " + SystemClock.elapsedRealtime());
            // Post notification of received message.

             sendNotification(extras.getString("message"), extras.getString("title"));

             Log.i(TAG, "Received: " + extras.toString());
        }
    }
    // Release the wake lock provided by the WakefulBroadcastReceiver.
    GcmBroadcastReceiver.completeWakefulIntent(intent);
}

// Put the message into a notification and post it.
// This is just one simple example of what you might choose to do with
// a GCM message.
private void sendNotification(String msg, String title) {
    mNotificationManager = (NotificationManager)
            this.getSystemService(Context.NOTIFICATION_SERVICE);
    if(title.isEmpty()){
        title="Happy Hour plus";
    }

    PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
            new Intent(this, SplashScreen.class), 0);

    NotificationCompat.Builder mBuilder =
            new NotificationCompat.Builder(this)
    .setSmallIcon(R.drawable.ic_stat_notification)
    .setContentTitle(title)
    .setStyle(new NotificationCompat.BigTextStyle()
    .bigText(msg))
    .setContentText(msg)
    .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
    .setVibrate(new long[] {250,250,250,250})
    .setAutoCancel(true);


    mBuilder.setContentIntent(contentIntent);
    mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());

}

public boolean checkApp(){
    ActivityManager am = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);

    // get the info from the currently running task
    List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1);

    ComponentName componentInfo = taskInfo.get(0).topActivity;
    if (componentInfo.getPackageName().equalsIgnoreCase("com.happyhour.main")) {
        return true;
        } else {
            return false;
        }
    }
}

Я сбит с толку! Не могу найти корень причины.

Заранее спасибо.




Ответы (2)


Таким образом, похоже, что интерфейс EMUI Huawei (P8 в моем случае) имеет особый способ обработки вещей.

После установки каждого приложения появится кнопка-переключатель с вопросом, разрешить ли этому конкретному приложению работать в фоновом режиме.

введите здесь описание изображения

  • Поэтому, если приложение поступает прямо из магазина Google Play, оно не будет предлагать вам эту кнопку разрешения «Запускать в фоновом режиме», потому что это «надежный источник».

  • Если вы просто экспортируете свой .apk из Android Studio и устанавливаете его прямо на свой телефон, он предложит кнопку, как показано выше, потому что установка прямо на ваш телефон падает в случае «ненадежного источника».

  • Наконец, если вы используете опцию USB-отладчика для установки .apk на телефон, он НИКОГДА не будет запрашивать кнопку и всегда будет действовать так, как будто вы нажали «Выкл.». Каждый раз, когда вы закрываете приложение, оно принудительно закрывает все его задачи.

Итак, что я сделал, так это перенес сгенерированный Android-Studio .apk на свой телефон и установил его вручную. Когда он предложил кнопку, я переключил ее на «ВКЛ», и все. Наконец-то я могу получать сообщения GCM, когда приложение закрыто!

Я думаю, что это ошибка EMUI/проблема с обработкой специальных приложений.

Отдельное спасибо @TeChNo_DeViL за помощь.

person Jodee    schedule 01.02.2016
comment
вы правы. но неофициальные приложения телеграммы работают без разрешения времени установки - person Mojtabye; 11.04.2016

Вы используете очень старые библиотеки. Рассмотрите возможность перехода на последние официальные библиотеки GCM. Сделайте так, чтобы ваш слушатель расширял GcmListenerService. Посмотрите официальные документы для того же. Также его намного проще обслуживать.

Убедитесь, что все перечисленные ниже TODO выполнены правильно:

  1. Зарегистрируйтесь в проекте в консоли разработчика Google с уникальным именем проекта и именем пакета, ваше имя пакета для вашего приложения и имена проекта приложения должны совпадать с именами в консоли.
  2. Поместите файл конфигурации google_services.json в каталог app/. Откройте его и проверьте, совпадают ли API_KEY в файле и тот, который указан в конфигурации в консоли разработчика Google, а также имена ваших пакетов. Также проверьте статус облачных сообщений Google, который должен быть 2.
  3. Следуйте подробным инструкциям в разделе Настройка клиентского приложения GCM на Android. Все слушатели должны быть правильно реализованы.
  4. Как только ваше приложение запустится, зарегистрируйте сгенерированный токен регистрации GCM, отправьте его на свой сервер и сверите токен, зарегистрированный в консоли adb, с полученным на сервере, оба должны совпадать.
  5. Тем не менее, если ничего не работает, используйте этот образец приложения в качестве примера. Вы можете скопировать прослушиватели, файл RegistrationIntentService.java и манифест, но не забудьте изменить имена пакетов на имя вашего пакета (также в ссылках на имена пакетов AndroidManifest.xml, специально для слушателей)
person TeChNo_DeViL    schedule 26.01.2016
comment
Пытаюсь последние 2 дня обновить все свои библиотеки на новые! Я дам вам знать, если это было причиной. Спасибо за ответ! - person Jodee; 27.01.2016
comment
Итак, по-видимому, я обновил все свои устаревшие и устаревшие библиотеки, и то же самое я сделал для GCM. Проблема остается точно такой же, как описано выше :( - person Jodee; 31.01.2016
comment
Тогда, возможно, ваша проблема заключается где-то в вашей реализации. Я обновил свой ответ контрольным списком TODO для функций GCM, потому что совсем недавно я завершил очень сложное приложение с использованием GCM, просто перепроверьте. - person TeChNo_DeViL; 31.01.2016
comment
Я правильно выполнил все шаги, но Huawei P8 все равно не получит уведомление, когда приложение будет закрыто. Должна ли быть включена кнопка «Принудительная остановка» (единственная фоновая служба, которую я использую, — это служба GCM), чтобы она работала правильно? В других устройствах (+эмуляторах) все отлично работает, а вот в Huawei P8... не знаю. Остается только думать, что этот телефон автоматически принудительно останавливает любое приложение, удаленное из списка последних приложений. - person Jodee; 01.02.2016