当应用程序未运行时,某些设备上无法显示GCM推送通知

14

我在我的应用程序中实现了GCM推送通知,并且已经成功完成,但是在一些设备上,当应用程序关闭时,它不会显示通知。

未显示通知的设备清单:

Redmi-2

lenovo

Gionee

有谁能解释一下问题出在哪里以及如何解决它。

这是我的清单文件:-

     <?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  package="student.skoolstar.android.catalyst.com.schoolstar.skoolstarstudent">

  <uses-permission android:name="android.permission.INTERNET" />
  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />


  <uses-permission android:name="android.permission.GET_ACCOUNTS" />
  <uses-permission android:name="android.permission.WAKE_LOCK" />

  <permission
   android:name="student.skoolstar.android.catalyst.com.schoolstar.skoolstarstudent.permission.C2D_MESSAGE"
   android:protectionLevel="signature" />

  <uses-permission android:name="student.skoolstar.android.catalyst.com.schoolstar.skoolstarstudent.permission.C2D_MESSAGE" />
  <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
  <uses-permission android:name="android.permission.VIBRATE" />

  <application
   android:name="student.skoolstar.android.catalyst.com.schoolstar.skoolstarstudent.Controller"
   android:allowBackup="true"
   android:icon="@mipmap/ic_launcher"
   android:label="@string/app_name"
   android:supportsRtl="true"
   android:theme="@style/MyMaterialTheme">
   <activity android:name=".MainActivity">
    <intent-filter>
     <action android:name="android.intent.action.MAIN" />

     <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
   </activity>
   <activity
    android:name=".Login"
    android:screenOrientation="portrait"
    android:windowSoftInputMode="stateHidden">
   </activity>
   <activity
    android:name=".ListOfClass"
    android:screenOrientation="portrait">
   </activity>
   <activity
    android:name=".EditProfile"
    android:screenOrientation="portrait"
    android:windowSoftInputMode="stateHidden">
   </activity>
   <activity
    android:name=".ShowStudentList"
    android:screenOrientation="portrait"
    android:windowSoftInputMode="stateHidden">
   </activity>
   <receiver
    android:name="student.skoolstar.android.catalyst.com.schoolstar.skoolstarstudent.GcmBroadcastReceiver"
    android:permission="com.google.android.c2dm.permission.SEND" >
    <intent-filter>

     <!-- Receives the actual messages. -->
     <action android:name="com.google.android.c2dm.intent.RECEIVE" />
     <!-- Receives the registration id. -->
     <action android:name="com.google.android.c2dm.intent.REGISTRATION" />

     <category android:name="schoolstar.com.catalyst.android.skoolstar" />
    </intent-filter>
   </receiver>

   <service android:name=".GCMNotificationIntentService" />
   <activity
    android:name=".Message"
    android:screenOrientation="portrait"
    android:windowSoftInputMode="stateHidden">
   </activity>
   <activity
    android:name=".Attendance"
    android:screenOrientation="portrait"
    android:windowSoftInputMode="stateHidden">
   </activity>

   <activity
    android:name=".NewMessage"
    android:screenOrientation="portrait"
    android:windowSoftInputMode="stateHidden">
   </activity>
   <activity
    android:name=".GroupMessage"
    android:screenOrientation="portrait"
    android:windowSoftInputMode="stateHidden">
   </activity>
   <activity
    android:name=".Test_Chat"
    android:screenOrientation="portrait"
    android:windowSoftInputMode="stateHidden">
   </activity>
  </application>

 </manifest>

这里是我的服务名称GCMNotificationIntentService:

    public class GCMNotificationIntentService extends GCMBaseIntentService {
    public static final int NOTIFICATION_ID = 1;
    private NotificationManager mNotificationManager;
    NotificationCompat.Builder builder;
    Database db;

    private Controller aController = null;

    public GCMNotificationIntentService() {
        // Call extended class Constructor GCMBaseIntentService
        super(Constants.GOOGLE_SENDER_ID);
    }

    public static final String TAG = "GCMNotificationIntentService";

    @Override
    protected void onRegistered(Context context, String registrationId) {

    }
    @Override
    protected void onUnregistered(Context context, String registrationId) {
        Log.d("unref",registrationId);
        if(aController == null)
            aController = (Controller) getApplicationContext();
        Toast.makeText(getApplicationContext(),"hello no",Toast.LENGTH_LONG).show();

        aController.displayMessageOnScreen(context,
                getString(R.string.gcm_unregistered));
        aController.unregister(context, registrationId);
    }

    @Override
    public void onError(Context context, String errorId) {

        Log.d("error","");

        if(aController == null)
            aController = (Controller) getApplicationContext();

        aController.displayMessageOnScreen(context,

                getString(R.string.gcm_error, errorId));
    }
    @Override
    protected void onMessage(Context context, Intent intent) {

        if(aController == null)
            aController = (Controller) getApplicationContext();

        aController.acquireWakeLock(getApplicationContext());

        String message = intent.getExtras().getString("message");
        String formuser = intent.getExtras().getString("formuser");

        Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT+5:30"));
        Date currentLocalTime = cal.getTime();
        DateFormat date = new SimpleDateFormat("HH:mm a");
        date.setTimeZone(TimeZone.getTimeZone("GMT+5:30"));
        String localTime = date.format(currentLocalTime);


        db = new Database(context);
        int  from_id = 0;

        List<FetchData> fetchdata = db.getAllContacts();
        for (FetchData fd : fetchdata)
        {

            from_id=fd.getID();//get ser no
        }

        db.storeMessage(420, formuser, from_id + "", message, "text", localTime, "F", "ST", "R");

        aController.displayMessageOnScreen(context, message);
        // notifies user
        sendNotification(context,message);
    }

    private void sendNotification(Context context,String msg) {
        String app_name = context.getResources().getString(R.string.app_name);
        mNotificationManager = (NotificationManager) this
                .getSystemService(Context.NOTIFICATION_SERVICE);

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

        Uri alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);

        NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
                this).setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle(app_name)
                .setStyle(new NotificationCompat.BigTextStyle().bigText(msg))
                .setContentText("New Message")
                .setSound(alarmSound);

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

        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "TAG");
        wl.acquire(15000);
        //  Log.d(TAG, "Notification sent successfully.");
    }
}

当我看到 WhatsApp、Hike 和其他通知应用程序时,它们总是在后台线程中运行,但我的应用程序并不总是在后台运行。所以这也可能是原因之一。我最近正在开发 Android 应用,请帮帮我。提前致谢!


你能否尝试使用WakefulBroadcastReceiver实现新的GCM实现方式,其中我们启动一个Intent Service? - Prashanth Debbadwar
你尝试过使用Instance ID API进行GCM注册吗? - Rajesh Jadav
4个回答

1
我在Redmi-2上遇到了类似的问题。代码没有问题,但是由于制造商提供的自定义UI(如MIUI 6),导致出现了问题。 为了启用GCM通知,请执行以下操作: 打开安全应用程序 >> 点击权限 >> 点击自动启动并启用您的应用程序的自动启动。

我能否像 WhatsApp、Hike 和其他应用程序一样通过编程实现这个吗? - om_jaipur

1

这有两个主要原因:

1- 有些设备不允许你在后台运行服务,例如红米2(几乎所有小米设备都是如此)。即使是 WhatsApp 也无法在这些设备上正常工作,除非用户通过转到"安全应用程序" >> 点击"权限" >> 点击"自启动"并启用 WhatsApp 的自启动权限来允许它们。在这种情况下,您所能做的就是在应用程序启动时向用户显示这些详细信息。如果可能的话,打开该屏幕并引导用户,类似于 Clean Master。

2- 第二个原因是,在其中一个未正确安装 Google Play Services 应用程序(对于 GCM 来说至关重要)的手机上,它无法正常工作。在这些设备上,您无法做任何事情。在这种情况下,您能做的唯一一件事就是向用户展示一些有关此问题的消息。

因此,根据我的经验,总会有一部分用户(但非常小的百分比)无法接收 GCM 推送。


如何找到需要自动启动代码的手机?我的意思是,我知道在MI设备中需要自动启动,但不知道其他设备。 - Bhavin Patel

1
小米手机有白名单的概念。因此,如果您在gcm的onReceive中放置日志,则会注意到gcm正在接收消息,但不会进一步处理消息,因为您的应用程序未被列入白名单。
为了安全起见,小米禁用每个应用程序的通知。请按照以下步骤,在他们退出使用清理工具之后在后台接收消息:
启用自启动:
1.打开安全应用。 2.转到权限,然后单击自启动管理。 3.添加/启用自启动应用程序(例如WhatsApp)。
启用浮动窗口和锁屏通知:
1.打开设置应用。 2.单击通知,然后单击管理通知。 3.点击您要查找的应用程序(例如WhatsApp)。 4.启用在通知栏中显示/在锁定屏幕上显示并在下拉选项中显示。

参考此链接:http://support.hike.in/entries/55998480-I-m-not-getting-notification-on-my-Xiaomi-Phone-For-MIUI-6-

我用这个方法成功了,希望对你有帮助。


1
如何找出哪些手机需要执行自启动代码?我的意思是,我知道在MI设备中需要自启动,但其他设备我不清楚。 - Bhavin Patel
@bdevloper 你能知道哪些设备有自动启动选项吗?因为这个选项在一些原生安卓设备上不可用。 - Jishant

0
面对相同的问题,我们所做的唯一事情就是教育小米用户按照@anup-dasari提到的步骤进行操作,并将gcm优先级设置为高,未来可能会有持久化服务。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接