【问题标题】:GCM message received but not displayed - Broadcast receiver result=CANCELLED - Service force stopGCM 消息已收到但未显示 - 广播接收器结果 = CANCELLED - 服务强制停止
【发布时间】:2016-02-02 07:01:58
【问题描述】:

我已经在我的应用和服务器上实现了 GCM 消息传递,一切正常,但不是在每部手机上!

主要问题是:

  • 当应用程序打开时,我收到 GCM 消息并按预期生成通知,但是当应用程序关闭时,我可以(通过 LOGCAT)看到消息已收到但已取消 -> “广播接收器,结果=取消”。

  • 接下来我无法让我的应用服务在后台运行。只要我从“最近的活动”菜单“关闭”我的应用程序,它也会在后台停止(进入设置 -> 应用程序 -> “MY_APP” -> 强制停止被禁用)。

我做了很多研究,我认为原因可能是华为 P8(主要测试设备)在您将所有应用程序从“最近活动”选项卡上滑开时自动强行关闭它们。但如果是这种情况,“Facebook”、“Viber”等其他应用程序就不会向我发送推送通知。

Manifest.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;
        }
    }
}

我很困惑!我找不到原因。

提前致谢。

【问题讨论】:

    标签: android google-cloud-messaging android-service android-broadcastreceiver


    【解决方案1】:

    看来华为的EMUI界面(我是P8)似乎有一种特殊的处理方式。

    在安装每个应用程序后,它会提示一个切换按钮,询问您是否允许该特定应用程序在后台运行。

    • 因此,如果应用直接来自 Google Play 商店,它不会提示您“在后台运行”允许按钮,因为它是“受信任的来源”。

    • 如果您只是从 Android Studio 导出您的 .apk 并直接安装到您的手机上,它会提示如上图所示的按钮,因为直接安装在您的手机上属于“不受信任的来源”的情况。

    • 最后,如果您使用 USB 调试器选项在手机上安装 .apk,它将永远不会提示该按钮,并且始终会像您按下“关闭”一样。每次关闭应用程序时,它都会强制关闭其所有任务。

    所以,我所做的是将 Android-Studio 生成的 .apk 传输到我的手机中并手动安装。当它提示按钮时,我将其切换到“ON”,就是这样。应用关闭后,我终于可以收到 GCM 消息了!

    我认为这是一个 EMUI 错误/特殊应用处理问题。

    特别感谢@TeChNo_DeViL 的帮助。

    【讨论】:

    • 你是对的。但是电报非官方应用程序无需安装时间权限即可运行
    【解决方案2】:

    您正在使用非常旧的库。考虑切换到最新的官方 GCM 库。让你的监听器扩展 GcmListenerService。查找相同的官方文档。而且它更容易维护。

    确保下面提到的所有 TODO 都正确完成:

    1. 使用唯一的项目名称和包名称在 Google Developer Console 中注册项目,您的应用程序包名称和应用项目名称必须与控制台中的名称一致。
    2. 将 google_services.json 配置文件放到 app/ 目录下。打开它并验证文件中的 API_KEY 是否与 Google Developer Console 中的配置中显示的匹配,以及您的包名称是否匹配。还要检查谷歌云消息的状态必须是 2。
    3. 按照Set up a GCM Client App on Android 中的详细步骤操作。必须正确实现所有侦听器。
    4. 一旦您的应用程序运行,记录生成的 GCM 注册令牌,将其发送到您的服务器,并交叉检查登录到 adb 控制台的令牌和服务器上收到的令牌,两者必须匹配。
    5. 如果没有任何效果,请使用 this 示例应用程序作为参考。您可以复制侦听器、RegistrationIntentService.java 文件和清单,但不要忘记将包名更改为您的包名(在 AndroidManifest.xml 包名引用中也是如此,专门针对侦听器)

    【讨论】:

    • 过去 2 天尝试将我所有的库更新为新库!我会让你知道这是否是原因。感谢回复!
    • 所以,显然我更新了我所有的老式和不推荐使用的库,所以我为 GCM 做了。问题仍然与上面描述的完全一样:(
    • 那么,您的问题可能出在您的实现中。我已经用 GCM 功能的 TODO 清单更新了我的答案,因为我最近使用 GCM 完成了一个非常复杂的应用程序,只需交叉检查即可。
    • 我已经正确地执行了每一个步骤,但是当应用程序关闭时,华为 P8 仍然不会收到我的通知。是否应该启用“强制停止”按钮(我使用的唯一后台服务是 GCM 之一)才能正常工作?在其他设备(+模拟器)中一切正常,但在华为 P8 中......我不知道。剩下要考虑的是,这款手机会自动强制停止从“最近的应用程序”列表中清除的任何应用程序。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多