Android 使用解析的推送在一段时间后停止工作
Android push using parse stops working after some time
我正在使用 Parse 在 Android 上发送有针对性的推送通知。按照教程进行了几次(包括不眠之夜)并且效果很好,但是在某些不可预测的事件中,android 应用程序的用户停止接收通知。在 Google Play.
上传更新几个小时后肯定会发生这种情况。
为了在不上传到 Google Play 的情况下重现它,我将其缩小到从清单更新应用程序版本号并重新 运行 而不删除和重新安装。然而,在清单中做一个简单的改变就可以让它再次工作。然而,该解决方案并不可靠,因为它会在几个小时后/上传到生产环境后再次停止工作。
我正在使用自定义 ParsePushBroadcastReceiver 来播放自定义声音。我正在使用 Google Play Services 5 进行位置更新。我正在订阅我稍后要推送的频道 activity。关于可能导致此类问题的任何想法?下面粘贴代码:
清单
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.xxx.xxx"
android:versionCode="19"
android:versionName="3.077" >
<uses-feature
android:glEsVersion="0x00020000"
android:required="true"/>
<!-- GCM PERMISSIONS -->
<permission android:name="com.xxx.xxx.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="com.xxx.xxx.permission.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
<uses-permission android:name="com.xxx.xxx.permission.MAPS_RECEIVE" />
<application
android:name="com.xxx.xxx.MyApplication"
android:allowBackup="true"
android:allowClearUserData="true"
android:enabled="true"
android:icon="@drawable/icon"
android:logo= "@drawable/icon"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<uses-library android:name="com.google.android.maps" />
<service android:name="com.xxx.xxx.xxxLocationService" />
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="xxxxxxxxxxx"/>
<meta-data android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<meta-data android:name="com.parse.push.gcm_sender_id"
android:value="id:xxxxx" />
<service android:name="com.parse.PushService" />
<receiver android:name="com.parse.ParseBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.USER_PRESENT" />
</intent-filter>
</receiver>
<receiver android:name="com.xxx.xxx.xxxBroadcastReceiver"
android:exported="false">
<intent-filter>
<action android:name="com.parse.push.intent.RECEIVE" />
<action android:name="com.parse.push.intent.DELETE" />
<action android:name="com.parse.push.intent.OPEN" />
</intent-filter>
</receiver>
<receiver android:name="com.parse.GcmBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<!--
IMPORTANT: Change "com.parse.starter" to match your app's package name.
-->
<category android:name="com.xxx.xxx" />
</intent-filter>
</receiver>
</application>
</manifest>
申请class
public class MyApplication extends Application {
@Override
public void onCreate(){
Parse.initialize(this, "xxxxxx", "xxxxxx");
ParseInstallation.getCurrentInstallation().saveInBackground();
}
}
依赖关系
dependencies {
compile 'com.google.android.gms:play-services:5.+'
compile 'com.google.code.gson:gson:2.3'
compile 'com.actionbarsherlock:actionbarsherlock:4.4.0@aar'
compile 'com.android.support:support-v4:22.0.0'
compile files('libs/PayPal_MPL.jar')
compile files('libs/libGoogleAnalyticsServices.jar')
compile 'com.parse.bolts:bolts-android:1.1.4'
compile fileTree(dir: 'libs', include: 'Parse-*.jar')
compile files('libs/Parse-1.8.3.jar')
}
ParsePushBroadcastReceiver
public class xxxBroadcastReceiver extends ParsePushBroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
try {
String jsonData = intent.getExtras().getString("com.parse.Data");
JSONObject json = new JSONObject(jsonData);
String title = null;
if(json.has("title")) {
title = json.getString("title");
}
String message = null;
if(json.has("alert")) {
message = json.getString("alert");
}
if(message != null) {
generateNotification(context, title, message);
}
} catch(Exception e) {
Log.e("NOTIF ERROR", e.toString());
}
}
private void generateNotification(Context context, String title, String message) {
Intent intent = new Intent(context, MainActivity.class);
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, intent, 0);
NotificationManager mNotifM = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if(title == null) {
title = context.getResources().getString(R.string.app_name);
}
final NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.icon)
.setContentTitle(title)
.setContentText(message)
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(message))
.addAction(0, "View", contentIntent)
.setAutoCancel(true)
.setDefaults(new NotificationCompat().DEFAULT_VIBRATE)
.setSound(Uri.parse("android.resource://" + context.getPackageName() + "/" + R.raw.whistle));
mBuilder.setContentIntent(contentIntent);
mNotifM.notify(randInt(100000000, 999999999), mBuilder.build());
}
public static int randInt(int min, int max) {
// NOTE: Usually this should be a field rather than a method
// variable so that it is not re-seeded every call.
Random rand = new Random();
// nextInt is normally exclusive of the top value,
// so add 1 to make it inclusive
int randomNum = rand.nextInt((max - min) + 1) + min;
return randomNum;
}
}
正在订阅频道
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_jobs);
...
ParsePush.subscribeInBackground("driver");
}
更新
这是我目前重现问题的方式。我 运行 在调试模式下运行,然后我更改应用程序的版本号并导出签名的生产应用程序(没有 运行ning)。我将已签名的 APK 安装到设备上(删除后),通知停止工作。似乎覆盖 ParsePushBroadcastReceiver 与它无关。如果我在调试模式下使用相同的版本号删除并重新 运行,它将无法工作,直到我更改清单中的某些内容(如 BroadcastReceiver)。这是我设法重现它的方式,但是通知在到达 Google 播放时无论如何都会停止工作(现在再试一次)。我错过了什么?
example implementation 中是这样的评论:
// Check if app was updated; if so, it must clear the registration ID
// since the existing registration ID is not guaranteed to work with
// the new app version.
我确定您 运行 喜欢这个。所以解决方案是在更新后注册您的应用程序。我想在你的情况下最好的选择是查看 PACKAGE_REPLACED
事件,你应该在那里重新注册你的应用程序。另请检查 this question 以了解其工作原理。
我正在使用 Parse 在 Android 上发送有针对性的推送通知。按照教程进行了几次(包括不眠之夜)并且效果很好,但是在某些不可预测的事件中,android 应用程序的用户停止接收通知。在 Google Play.
上传更新几个小时后肯定会发生这种情况。为了在不上传到 Google Play 的情况下重现它,我将其缩小到从清单更新应用程序版本号并重新 运行 而不删除和重新安装。然而,在清单中做一个简单的改变就可以让它再次工作。然而,该解决方案并不可靠,因为它会在几个小时后/上传到生产环境后再次停止工作。
我正在使用自定义 ParsePushBroadcastReceiver 来播放自定义声音。我正在使用 Google Play Services 5 进行位置更新。我正在订阅我稍后要推送的频道 activity。关于可能导致此类问题的任何想法?下面粘贴代码:
清单
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.xxx.xxx"
android:versionCode="19"
android:versionName="3.077" >
<uses-feature
android:glEsVersion="0x00020000"
android:required="true"/>
<!-- GCM PERMISSIONS -->
<permission android:name="com.xxx.xxx.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="com.xxx.xxx.permission.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
<uses-permission android:name="com.xxx.xxx.permission.MAPS_RECEIVE" />
<application
android:name="com.xxx.xxx.MyApplication"
android:allowBackup="true"
android:allowClearUserData="true"
android:enabled="true"
android:icon="@drawable/icon"
android:logo= "@drawable/icon"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<uses-library android:name="com.google.android.maps" />
<service android:name="com.xxx.xxx.xxxLocationService" />
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="xxxxxxxxxxx"/>
<meta-data android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<meta-data android:name="com.parse.push.gcm_sender_id"
android:value="id:xxxxx" />
<service android:name="com.parse.PushService" />
<receiver android:name="com.parse.ParseBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.USER_PRESENT" />
</intent-filter>
</receiver>
<receiver android:name="com.xxx.xxx.xxxBroadcastReceiver"
android:exported="false">
<intent-filter>
<action android:name="com.parse.push.intent.RECEIVE" />
<action android:name="com.parse.push.intent.DELETE" />
<action android:name="com.parse.push.intent.OPEN" />
</intent-filter>
</receiver>
<receiver android:name="com.parse.GcmBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<!--
IMPORTANT: Change "com.parse.starter" to match your app's package name.
-->
<category android:name="com.xxx.xxx" />
</intent-filter>
</receiver>
</application>
</manifest>
申请class
public class MyApplication extends Application {
@Override
public void onCreate(){
Parse.initialize(this, "xxxxxx", "xxxxxx");
ParseInstallation.getCurrentInstallation().saveInBackground();
}
}
依赖关系
dependencies {
compile 'com.google.android.gms:play-services:5.+'
compile 'com.google.code.gson:gson:2.3'
compile 'com.actionbarsherlock:actionbarsherlock:4.4.0@aar'
compile 'com.android.support:support-v4:22.0.0'
compile files('libs/PayPal_MPL.jar')
compile files('libs/libGoogleAnalyticsServices.jar')
compile 'com.parse.bolts:bolts-android:1.1.4'
compile fileTree(dir: 'libs', include: 'Parse-*.jar')
compile files('libs/Parse-1.8.3.jar')
}
ParsePushBroadcastReceiver
public class xxxBroadcastReceiver extends ParsePushBroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
try {
String jsonData = intent.getExtras().getString("com.parse.Data");
JSONObject json = new JSONObject(jsonData);
String title = null;
if(json.has("title")) {
title = json.getString("title");
}
String message = null;
if(json.has("alert")) {
message = json.getString("alert");
}
if(message != null) {
generateNotification(context, title, message);
}
} catch(Exception e) {
Log.e("NOTIF ERROR", e.toString());
}
}
private void generateNotification(Context context, String title, String message) {
Intent intent = new Intent(context, MainActivity.class);
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, intent, 0);
NotificationManager mNotifM = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if(title == null) {
title = context.getResources().getString(R.string.app_name);
}
final NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.icon)
.setContentTitle(title)
.setContentText(message)
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(message))
.addAction(0, "View", contentIntent)
.setAutoCancel(true)
.setDefaults(new NotificationCompat().DEFAULT_VIBRATE)
.setSound(Uri.parse("android.resource://" + context.getPackageName() + "/" + R.raw.whistle));
mBuilder.setContentIntent(contentIntent);
mNotifM.notify(randInt(100000000, 999999999), mBuilder.build());
}
public static int randInt(int min, int max) {
// NOTE: Usually this should be a field rather than a method
// variable so that it is not re-seeded every call.
Random rand = new Random();
// nextInt is normally exclusive of the top value,
// so add 1 to make it inclusive
int randomNum = rand.nextInt((max - min) + 1) + min;
return randomNum;
}
}
正在订阅频道
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_jobs);
...
ParsePush.subscribeInBackground("driver");
}
更新
这是我目前重现问题的方式。我 运行 在调试模式下运行,然后我更改应用程序的版本号并导出签名的生产应用程序(没有 运行ning)。我将已签名的 APK 安装到设备上(删除后),通知停止工作。似乎覆盖 ParsePushBroadcastReceiver 与它无关。如果我在调试模式下使用相同的版本号删除并重新 运行,它将无法工作,直到我更改清单中的某些内容(如 BroadcastReceiver)。这是我设法重现它的方式,但是通知在到达 Google 播放时无论如何都会停止工作(现在再试一次)。我错过了什么?
example implementation 中是这样的评论:
// Check if app was updated; if so, it must clear the registration ID
// since the existing registration ID is not guaranteed to work with
// the new app version.
我确定您 运行 喜欢这个。所以解决方案是在更新后注册您的应用程序。我想在你的情况下最好的选择是查看 PACKAGE_REPLACED
事件,你应该在那里重新注册你的应用程序。另请检查 this question 以了解其工作原理。