Android集成极光推送和踩过的坑(一)
来源:互联网 发布:unity3d 5.3.4f1 下载 编辑:程序博客网 时间:2024/05/21 09:08
转载请标明出处
http://blog.csdn.net/mohan6/article/details/72960346
本文作者:【默寒的博客】
集成步骤以及集成过程遇到的坑:
这部分主要阐述了集成极光推送的sdk的步骤,以及我在集成过程中遇到的一些问题。集成步骤只是摘出了极光SDK中必须的骨子的部分,可以满足一般项目Push需求,这里只做了通知消息,自定义的穿透消息请详见极光的SDK集成文档。我主要是总结一下,集成过程中需要注意和可能出问题的地方(详见注的说明),如果你也遇到了类似的问题,希望可以通过这篇文章能迅速把坑填了。LZ表示,这些坑好心塞~
一.jcenter 自动集成步骤
1.确认android studio的 Project 根目录的主 gradle 中配置了jcenter支持。(新建project默认配置就支持,一般不需要配置,只要确认一下就好)
buildscript { repositories { jcenter() } ......}allprojects { repositories { jcenter() }}2.在 module 的 gradle 中添加依赖和AndroidManifest的替换变量。
android { ...... defaultConfig { applicationId "com.xxx.xxx" //JPush上注册的包名. ...... ndk { //选择要添加的对应cpu类型的.so库。 abiFilters 'armeabi', 'armeabi-v7a', 'arm64-v8a' // 还可以添加 'x86', 'x86_64', 'mips', 'mips64' } manifestPlaceholders = [ JPUSH_PKGNAME : applicationId, JPUSH_APPKEY : "你的appkey", //JPush上注册的包名对应的appkey. JPUSH_CHANNEL : "自定义渠道名称", //用户渠道统计的渠道名称 ] ...... } ......}dependencies { ...... compile 'cn.jiguang.sdk:jpush:3.0.5' compile 'cn.jiguang.sdk:jcore:1.1.2' ......}注 : 1. 如果在添加以上 abiFilter 配置之后android Studio出现以下提示:
NDK integration is deprecated in the current plugin. Consider trying the new experimental plugin则在 Project 根目录的gradle.properties文件中添加:
android.useDeprecatedNdk=true
二. AndroidManifest加权限
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.******"> <uses-permission android:name="android.permission.INTERNET"/> <!-- 访问当前网络状态权限 --> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <!-- 获取手机信息 --> <uses-permission android:name="android.permission.READ_PHONE_STATE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION"/> <!--2017.5.27 极光推送权限 ym start--> <uses-permission android:name="android.permission.WAKE_LOCK"/> <uses-permission android:name="android.permission.VIBRATE"/> <uses-permission android:name="android.permission.RECEIVE_USER_PRESENT"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_SETTINGS"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/> <permission android:name="com.******(包名).permission.JPUSH_MESSAGE" android:protectionLevel="signature"/> <uses-permission android:name="com.******(包名).permission.JPUSH_MESSAGE"/><!--2017.5.27 极光推送权限 ym end-->
注 :
1.记得修改极光自定义权限的包名。
2.【访问当前网络状态权限】和【获取手机信息】项目里一般已经添加,这里检查一下,缺的补上。【极光推送权限】是极光要求,但是项目里可能没有的,注意查看。
<permission android:name="com.******(包名).permission.JPUSH_MESSAGE" android:protectionLevel="signature"/> <uses-permission android:name="com.carspass.permission.JPUSH_MESSAGE"/>
三. 集成 JPush Android SDK 的混淆,否则打包后极光不好使
请下载4.x及以上版本的proguard.jar, 并替换你Android Sdk "tools\proguard\lib\proguard.jar"
请在工程的混淆文件中添加以下配置:
-dontoptimize-dontpreverify-dontwarn cn.jpush.**-keep class cn.jpush.** { *; }-dontwarn cn.jiguang.**-keep class cn.jiguang.** { *; }
注 : 别忘了往混淆文件里加这段代码。我第一次集成的时候给忘却了,后来大神找我说minifyEnabled true(minifyEnabled主要用来控制是否运行混淆的。true表示混淆), 极光打包以后不好使,提醒我忘记在混淆文件中加这段代码了。
dontwarn表示打包混淆的时候,消除极光的警告。keep表示保持极光的一些类,不被混淆。
四. JPushManger极光推送管理类
/** * Created by ym on 2017/5/27. * 极光推送管理类 */public class JPushManager { private String TAG = "JPushManager"; private final String KEY = "JpushConfig"; private Context context; private SharePreferenceUtil sp; public JPushManager(Context context) { this.context = context; sp = new SharePreferenceUtil(context); } /** * 初始化极光,一般可以放到程序的启动Activity或是Application的onCreate方法中调用 */ public void initJPush() { JPushInterface.setDebugMode(true); // 设置开启日志,发布时请关闭日志 JPushInterface.init(context); // 初始化 JPush } /** * 退出极光,一般是程序退出登录时候,具体还是需要看项目的实际需求 */ public void stopJPush() { JPushInterface.stopPush(context); //setAliasAndTags("", "");//通过清空别名来停止极光 } /** * 极光推送恢复正常工作 */ public void resumeJPush() { JPushInterface.resumePush(context); } /** * 设置AliasAndTag,设置多组tag,如果不需要设置tag的化,直接将此参数设为null;(这个方法设置别名,tag传null没有问题) * 一般在程序登录成功,注册成功等地方调用。别名一般是用户的唯一标识,如userId等 * * @param alias * @param tags */ public void setAliasAndTags(final String alias, Set<String> tags) { if (TextUtils.isEmpty(alias)) { //Toast.makeText(context, "别名为空", Toast.LENGTH_SHORT).show(); return; } // 调用 Handler 来异步设置别名 AliasAndTagsInfo aliasAndTagsInfo = new AliasAndTagsInfo(); aliasAndTagsInfo.setAlias(alias); aliasAndTagsInfo.setTag(tags); mHandler.sendMessage(mHandler.obtainMessage(MSG_SET_ALIAS, aliasAndTagsInfo)); }// /**// * 设置AliasAndTag,设置一组tag,如果不需要设置tag的化,直接将此参数设为null;(这个方法设置别名,不设置tag,tag传null会走6002,tag参数错误)// */// public void setAliasAndTags(final String alias, String tag) {// if (TextUtils.isEmpty(alias)) {// // Toast.makeText(context, "别名为空", Toast.LENGTH_SHORT).show();// return;// }// // 调用 Handler 来异步设置别名// AliasAndTagsInfo aliasAndTagsInfo = new AliasAndTagsInfo();// aliasAndTagsInfo.setAlias(alias);// Set<String> tags = new HashSet<String>();// tags.add(tag);// aliasAndTagsInfo.setTag(tags);// mHandler.sendMessage(mHandler.obtainMessage(MSG_SET_ALIAS,// aliasAndTagsInfo));// } private final TagAliasCallback mAliasCallback = new TagAliasCallback() { @Override public void gotResult(int code, String alias, Set<String> tags) { String logs; switch (code) { case 0: logs = "Set tag and alias success"; Log.d(TAG, logs); // 建议这里往 SharePreference 里写一个成功设置的状态。成功设置一次后,以后不必再次设置了。 saveAlias(alias); break; case 6002: logs = "Failed to set alias and tags due to timeout. Try again after 60s."; Log.d(TAG, logs); // 延迟 60 秒来调用 Handler 设置别名 mHandler.sendMessageDelayed( mHandler.obtainMessage(MSG_SET_ALIAS, alias), 1000 * 60); break; default: logs = "Failed with errorCode = " + code; Log.d(TAG, logs); } } }; /** * 保存别名到属性文件。 * * @param alias */ private void saveAlias(String alias) { sp.putString(KEY, alias); } /** * 从属性文件取得别名 * * @param userName * @return */ private String getAlias(String userName) { return sp.getString(KEY); } private static final int MSG_SET_ALIAS = 1001; private final Handler mHandler = new Handler() { @Override public void handleMessage(android.os.Message msg) { super.handleMessage(msg); AliasAndTagsInfo aliasAndTagsInfo = (AliasAndTagsInfo) msg.obj; switch (msg.what) { case MSG_SET_ALIAS: Log.d(TAG, "Set alias in handler."); LogUtil.e("ym", aliasAndTagsInfo.getAlias()); // 调用 JPush 接口来设置别名。 JPushInterface.setAliasAndTags(context, aliasAndTagsInfo.getAlias(), aliasAndTagsInfo.getTag(), mAliasCallback); break; default: Log.d(TAG, "Unhandled msg - " + msg.what); } } }; public class AliasAndTagsInfo implements Serializable { private static final long serialVersionUID = 1L; private String alias; private Set<String> tag; public String getAlias() { return alias; } public void setAlias(String alias) { this.alias = alias; } public Set<String> getTag() { return tag; } public void setTag(Set<String> tag) { this.tag = tag; } }}
注 :
1.这里提供了两个同时设置别名和标签的同名方法。不设置tag的话可以直接传null,但是传null的话,这两个重载的方法传的参数会一样,系统会不知道我们调的哪个方法。于是乎,我就把第一个注释了……然后就自己给自己挖了个很大的坑。亲测发现第一个方法Set<String>tags的位置传null,没问题。第二个String tag,传null,极光的接口回调回来走的6002,说tag的参数传的有问题。然后仔细一看,我相当于把一个null对象放到了Set<String>tags里,然后传给了极光。这里可以在原来基础上加个判空,然后再往Set里add。就跟第一种方法是一样的了。我现在只是把第二种方法注释掉了,没有做修改。如果项目需求只要求设置一个标签,用第二种方法的话,自行加判空处理就好。
public void setAliasAndTags(final String alias, Set<String> tags) {}public void setAliasAndTags(final String alias, String tag) {}2.项目需求只要求设置别名,没有要求设置标签的话。可以按照sdk文档上的setAlias()的方法设置就行。我们项目也是只要求设置别名,但是我怕产品回头又要设置标签,索性就直接用了上面的方法,方便以后修改。
3.这里设置别名是异步操作的,我们的大神有指出说我设置别名放到了登录回调里是不合理的,说有可能极光服务器down掉了,会卡死在登录界面,然后用户手动杀死进程再进来,这是已经是登录成功的状态,直接会进入首页。这样会导致极光设置别名失败。
但是我分析之后,个人觉得这个设置别名的操作是异步执行了,不存在大神说的那种卡死的情况。第一次设置的时候,会调这个方法。类似于我们做banner轮播图的时候,先发一条触发轮播的开始一样。发完就完事了,大神说的在登录回调中我设置极光别名的代码下边,打开首页等操作的代码会继续执行,并不会卡死。
mHandler.sendMessage(mHandler.obtainMessage(MSG_SET_ALIAS, aliasAndTagsInfo));第一次发完以后,会走handler中的handleMessage(),调极光的接口
// 调用 JPush 接口来设置别名。 JPushInterface.setAliasAndTags(context, aliasAndTagsInfo.getAlias(), aliasAndTagsInfo.getTag(), mAliasCallback);然后再回调中0表示设置成功,6002表示设置失败,设置失败以后会延迟60s以后重新调handler设置别名。不存在大神说的设置失败,就失败的问题。
private final TagAliasCallback mAliasCallback = new TagAliasCallback() { @Override public void gotResult(int code, String alias, Set<String> tags) { String logs; switch (code) { case 0: logs = "Set tag and alias success"; Log.d(TAG, logs); // 建议这里往 SharePreference 里写一个成功设置的状态。成功设置一次后,以后不必再次设置了。 saveAlias(alias); break; case 6002: logs = "Failed to set alias and tags due to timeout. Try again after 60s."; Log.d(TAG, logs); // 延迟 60 秒来调用 Handler 设置别名 mHandler.sendMessageDelayed( mHandler.obtainMessage(MSG_SET_ALIAS, alias), 1000 * 60); break; default: logs = "Failed with errorCode = " + code; Log.d(TAG, logs); } } };
五. 在Application的onCreate()中初始化极光
public class MyApplication extends Application {@Override public void onCreate() { super.onCreate(); //2017.5.27 极光推送初始化 ym start JPushManager jPushManager = new JPushManager(this); jPushManager.initJPush(); String registrationID = JPushInterface.getRegistrationID(MyApplication.this); LogUtil.e("ym", "registrationID" + registrationID);//美图测试机100d85590976ac4ac55 //2017.5.27 极光推送初始化 ym end }}
注 :
1. 关于获取 RegistrationID,官方说有两种方法可以拿。
SDK 初次注册成功后,开发者通过在自定义的 Receiver 里监听Action - cn.jpush.Android.intent.REGISTRATION来获取对应的 RegistrationID。注册成功后,也可以通过此函数获取
public static String getRegistrationID(Context context)。
Lz亲测,第一种是误导,应该在application中才能拿到!!!而不是自定义Receiver!我又看到别人也有说第一种拿不到的情况。
不知道什么原因,按理说,在注册极光成功以后,极光会发一个广播,我们可以在广播中拿到
RegistrationID
,但是亲测发现根本不走自定义的Reciver的这个广播,SDK文档中说是可以拿到的,但是人家这广播我都接受不到,所以拿不到,如果有谁知道是什么原因,请告之!万分感谢!
RegistrationID
所以我采用的是在
application
里拿RegistrationID
。
String registrationID = JPushInterface.getRegistrationID(MyApplication.this); LogUtil.e("ym", "registrationID" + registrationID);//美图测试机100d85590976ac4ac55有在自定义Receiver
里拿到的请留言~,让我知道一下自己问题出在哪里,相互学习嘛。如果你也拿不到,就跟我似的在里拿吧。当然如果项目需求根本没有要根据
application
RegistrationID个推,后台也不需要你这个
绑定用户的话,那就无关紧要了,那就不需要拿
RegistrationID
了。
RegistrationID
2.这个JPushManager网上有用单例初始化的,静态Context会导致内存泄露。
public class JPushManager { private String TAG = "JPushManager"; private final String KEY = "JpushConfig"; private static JPushManager jPushManager; private static Context context; public static JPushManager newInstence(Context context) { JPushManager.context = context; if (jPushManager == null) { jPushManager = new JPushManager(); } return jPushManager; }于是就改成下面这样的,这样Context就不是静态的了!但是同样会导致内存泄露。但是恰恰下面这种是单例导致内存泄露最典型的例子。由于单例的静态特性使得其生命周期跟应用的生命周期一样长,所以如果使用不恰当的话,很容易造成内存泄漏。
public class JPushManager { private String TAG = "JPushManager"; private final String KEY = "JpushConfig"; private static JPushManager jPushManager; private Context context; public JPushManager(Context context) { this.context = context; } public static JPushManager newInstence(Context context) { if (jPushManager == null) { jPushManager = new JPushManager(context); } return jPushManager; }当创建这个单例的时候,由于需要传入一个Context,所以这个Context的生命周期的长短至关重要:
1、如果此时传入的是 Application 的 Context,因为 Application 的生命周期就是整个应用的生命周期,所以这将没有任何问题。
2、如果此时传入的是 Activity 的 Context,当这个 Context 所对应的 Activity 退出时,由于该 Context 的引用被单例对象所持有,其生命周期等于整个应用程序的生命周期,所以当前 Activity 退出时它的内存并不会被回收,这就造成泄漏了。
正确的做法:public class JPushManager { private String TAG = "JPushManager"; private final String KEY = "JpushConfig"; private static JPushManager jPushManager; private Context context; public static JPushManager newInstence() { this.context = getApplicationContext(); if (jPushManager == null) { jPushManager = new JPushManager(); } return jPushManager; }
六. 极光推送自定义的广播接受者,用于获取推送到通知栏的消息内容、消息附加的参数字段处理消息的跳转
/** * Created by ym on 2017/5/27. * 自定义极光推送的广播接受者 */public class MyJPushReceiver extends BroadcastReceiver { private static final String TAG = "JPush"; @Override public void onReceive(Context context, Intent intent) { Bundle bundle = intent.getExtras(); LogUtil.e(TAG, "[MyReceiver] onReceive - " + intent.getAction() + ", extras: " + printBundle(bundle)); if (JPushInterface.ACTION_REGISTRATION_ID.equals(intent.getAction())) { String regId = bundle.getString(JPushInterface.EXTRA_REGISTRATION_ID); LogUtil.e(TAG, "[MyReceiver] 接收Registration Id : " + regId); } else if (JPushInterface.ACTION_MESSAGE_RECEIVED.equals(intent.getAction())) { LogUtil.e(TAG, "[MyReceiver] 接收到推送下来的自定义消息: " + bundle.getString(JPushInterface.EXTRA_MESSAGE));// processCustomMessage(context, bundle); } else if (JPushInterface.ACTION_NOTIFICATION_RECEIVED.equals(intent.getAction())) { LogUtil.e(TAG, "[MyReceiver] 接收到推送下来的通知"); int notificationId = bundle.getInt(JPushInterface.EXTRA_NOTIFICATION_ID); LogUtil.e(TAG, "[MyReceiver] 接收到推送下来的通知的ID: " + notificationId); } else if (JPushInterface.ACTION_NOTIFICATION_OPENED.equals(intent.getAction())) { LogUtil.e(TAG, "[MyReceiver] 用户点击打开了通知"); //解析json String string = bundle.getString(JPushInterface.EXTRA_EXTRA);//json串 LogUtil.e(TAG, "=====###########" + string); try { JSONObject jsonObject = new JSONObject(string); String type = jsonObject.getString("type"); LogUtil.e(TAG, "type:" + type); switch (type) { case "1"://打开应用 if (isBackground(context)) { Intent i = new Intent(context, ACT_Main.class); i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); context.startActivity(i); } break; case "2"://打开创建订单页 String sourse_id = jsonObject.getString("sourse_id"); if (!TextUtils.isEmpty(sourse_id)) { Intent intentOrder = new Intent(context, ACT_PlaceOrder.class); intentOrder.putExtra("id", Integer.parseInt(sourse_id)); intentOrder.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intentOrder); } break; case "3"://打开品牌 String brand_id = jsonObject.getString("brand_id"); String bra_name = jsonObject.getString("bra_name"); if (!TextUtils.isEmpty(brand_id)){ Intent intentBrand = new Intent(context, ACT_BrandCarList.class); intentBrand.putExtra("id", brand_id); intentBrand.putExtra("title", bra_name); intentBrand.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intentBrand); } break; case "4"://打开指定页面 String http_url = jsonObject.getString("http_url"); if (!TextUtils.isEmpty(http_url)){ Intent intentWeb = new Intent(context, ACT_Web.class); intentWeb.putExtra("title", ""); intentWeb.putExtra("url", http_url); intentWeb.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intentWeb); } break; case "5"://打开议价详情 String bargainid = jsonObject.getString("bargainid"); if (!TextUtils.equals(bargainid, "0") && !TextUtils.isEmpty(bargainid)) {//bargainid=0是议价已取消,不跳转 Intent bargainIntent = new Intent(context, ACT_BargainingDetail.class); bargainIntent.putExtra("id", bargainid); bargainIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(bargainIntent); } break; } } catch (JSONException e) { e.printStackTrace(); } } else if (JPushInterface.ACTION_RICHPUSH_CALLBACK.equals(intent.getAction())) { LogUtil.e(TAG, "[MyReceiver] 用户收到到RICH PUSH CALLBACK: " + bundle.getString(JPushInterface.EXTRA_EXTRA)); //在这里根据 JPushInterface.EXTRA_EXTRA 的内容处理代码,比如打开新的Activity, 打开一个网页等.. } else if (JPushInterface.ACTION_CONNECTION_CHANGE.equals(intent.getAction())) { boolean connected = intent.getBooleanExtra(JPushInterface.EXTRA_CONNECTION_CHANGE, false); LogUtil.e(TAG, "[MyReceiver]" + intent.getAction() + " connected state change to " + connected); } else { LogUtil.e(TAG, "[MyReceiver] Unhandled intent - " + intent.getAction()); } } // 打印所有的 intent extra 数据 private static String printBundle(Bundle bundle) { StringBuilder sb = new StringBuilder(); for (String key : bundle.keySet()) { if (key.equals(JPushInterface.EXTRA_NOTIFICATION_ID)) { sb.append("\nkey:" + key + ", value:" + bundle.getInt(key)); } else if (key.equals(JPushInterface.EXTRA_CONNECTION_CHANGE)) { sb.append("\nkey:" + key + ", value:" + bundle.getBoolean(key)); } else if (key.equals(JPushInterface.EXTRA_EXTRA)) { if (TextUtils.isEmpty(bundle.getString(JPushInterface.EXTRA_EXTRA))) { LogUtil.e(TAG, "This message has no Extra data"); continue; } try { JSONObject json = new JSONObject(bundle.getString(JPushInterface.EXTRA_EXTRA)); Iterator<String> it = json.keys(); while (it.hasNext()) { String myKey = it.next().toString(); sb.append("\nkey:" + key + ", value: [" + myKey + " - " + json.optString(myKey) + "]"); } } catch (JSONException e) { LogUtil.e(TAG, "Get message extra JSON error!"); } } else { sb.append("\nkey:" + key + ", value:" + bundle.getString(key)); } } return sb.toString(); } /** * 判断进程是否在后台 * * @param context * @return */ public static boolean isBackground(Context context) { ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); List<RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses(); for (RunningAppProcessInfo appProcess : appProcesses) { if (appProcess.processName.equals(context.getPackageName())) { LogUtil.i("ym", appProcess.processName + "前台"); return false; } else { LogUtil.i("ym", appProcess.processName + "后台"); return true; } } return false; }}
注:注意开启Activity的intent的flag,这里主要讲集成极光不坐赘述。有需要可以查看 Activity的启动模式和Intent标记位。
七. AndroidManifest中加极光推送自定义的广播接受者
<!--2017.5.27 极光推送自定义的广播接收器 ym start--> <receiver android:name=".module.MyJPushReceiver" android:enabled="true" android:exported="false"> <intent-filter> <action android:name="cn.jpush.android.intent.REGISTRATION"/> <!-- Required 用户注册SDK的intent --> <action android:name="cn.jpush.android.intent.MESSAGE_RECEIVED"/> <!-- Required 用户接收SDK消息的intent --> <action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED"/> <!-- Required 用户接收SDK通知栏信息的intent --> <action android:name="cn.jpush.android.intent.NOTIFICATION_OPENED"/> <!-- Required 用户打开自定义通知栏的intent --> <action android:name="cn.jpush.android.intent.NOTIFICATION_CLICK_ACTION"/> <action android:name="cn.jpush.android.intent.CONNECTION"/> <!-- 接收网络变化 连接/断开 since 1.6.3 --> <category android:name="com.*******(包名)"/> </intent-filter> </receiver><!--2017.5.27 极光推送自定义的广播接收器 ym end-->注意:记得修改包名,我直接复制的之前项目的,导致忘记修改包名,推送消息就是不走MyJPushReceiver。
八. 设置别名
在登录成功的回调中设置别名,这里用的token做的别名,大家可以根据需求自行更换。这里对token加盐以后做Md5加密处理以后做的别名。我们项目不涉及到加标签tag的需求,所以我这里直接传的null。
//2017.5.31 给极光设置别名 ym start String access_token = object.getString("access_token"); String alias = MD5Util.md5(access_token + Contants.Alias); LogUtil.e("ym", "极光别名:" + alias); JPushManager jPushManager = new JPushManager(ACT_Login.this); jPushManager.setAliasAndTags(alias, null);//2017.5.31 给极光设置别名 ym end
九. 清除别名
极光sdk文档上说,清除别名直接把别名设置成空串就行。但是一位大神亲测说设置成空串的做法有的时候会清除别名失败。建议设置成和自己别名差异很大的字符。如果你遇到把别名设置成空串,退出登录以后仍能接收到推送的情况,可以试试。
在退出登录成功的回调中清除别名,这样用户退出登录以后就不会收到Push了。用户再次登录的时候会重新设置别名。
//2017.6.2 清除极光推送的别名 ym start JPushManager jPushManager = new JPushManager(act); jPushManager.setAliasAndTags("*********(和别名区别很大的符合要求的字符)", null);//2017.6.2 清除极光推送的别名 ym endsdk文档说明:
参数定义 alias null 此次调用不设置此值。(注:不是指的字符串"null") "" (空字符串)表示取消之前的设置。 每次调用设置有效的别名,覆盖之前的设置。 有效的别名组成:字母(区分大小写)、数字、下划线、汉字、特殊字符(v2.1.6支持)@!#$&*+=.|。 限制:alias 命名长度限制为 40 字节。(判断长度需采用UTF-8编码)
其他极光推送踩过的坑
1.之前项目里遇到过Android 5.0的通知栏的图标不显示的Bug。
解决方案:若没有res/drawable-xxxx/jpush_notification_icon这个资源默认使用应用图标作为通知icon,在5.0以上系统将应用图标作为statusbar icon可能显示不正常,用户可定义没有阴影和渐变色的icon替换这个文件,文件名不要变。
2.广播接受者不走清单文件中<category>中包名是否修改
<receiver android:name=".module.MyJPushReceiver" android:enabled="true" android:exported="false"> <intent-filter> <action android:name="cn.jpush.android.intent.REGISTRATION"/> <!-- Required 用户注册SDK的intent --> <action android:name="cn.jpush.android.intent.MESSAGE_RECEIVED"/> <!-- Required 用户接收SDK消息的intent --> <action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED"/> <!-- Required 用户接收SDK通知栏信息的intent --> <action android:name="cn.jpush.android.intent.NOTIFICATION_OPENED"/> <!-- Required 用户打开自定义通知栏的intent --> <action android:name="cn.jpush.android.intent.NOTIFICATION_CLICK_ACTION"/> <action android:name="cn.jpush.android.intent.CONNECTION"/> <!-- 接收网络变化 连接/断开 since 1.6.3 --> <category android:name="com.******"/> </intent-filter></receiver>3.sdk文档各种手机收不到通知的
由于第三方 ROM 的管理软件需要用户手动操作
如果没有解决你的问题,请移步 Android集成极光推送踩坑(二)升级篇
小米【MIUI】
- 自启动管理:需要把应用加到【自启动管理】列表,否则杀进程或重新开机后进程无法开启
- 通知栏设置:应用默认都是显示通知栏通知,如果关闭,则收到通知也不会提示
- 网络助手:可以手动禁止已安装的第三方程序访问2G/3G和WIFI的网络和设置以后新安装程序是否允许访问2G/3G和WIFI的网络
- MIUI 7 神隐模式: 允许应用进行自定义配置模式,应用在后台保持联网可用,否则应用进入后台时,应用无法正常接收消息。【设置】下电量和性能中【神隐模式】
华为【Emotion】
- 自启动管理:需要把应用加到【自启动管理】列表,否则杀进程或重新开机后进程不会开启,只能手动开启应用
- 后台应用保护:需要手动把应用加到此列表,否则设备进入睡眠后会自动杀掉应用进程,只有手动开启应用才能恢复运行
- 通知管理:应用状态有三种:提示、允许、禁止。禁止应用则通知栏不会有任何提醒
魅族【Flyme】
- 自启动管理:需要把应用加到【自启动管理】列表,否则杀进程或重新开机后进程无法开启
- 通知栏推送:关闭应用通知则收到消息不会有任何展示
- 省电管理: 安全中心里设置省电模式,在【待机耗电管理】中允许应用待机时,保持允许,否则手机休眠或者应用闲置一段时间,无法正常接收消息。
VIVO【Funtouch OS】
- 内存一键清理:需要将应用加入【白名单】列表,否则系统自带的“一键加速”,会杀掉进程
- 自启动管理:需要将应用加入“i管家”中的【自启动管理】列表,否则重启手机后进程不会自启。但强制手动杀进程,即使加了这个列表中,后续进程也无法自启动。
OPPO【ColorOS】
- 冻结应用管理:需要将应用加入纯净后台,否则锁屏状态下无法及时收到消息
- 自启动管理:将应用加入【自启动管理】列表的同时,还需要到设置-应用程序-正在运行里锁定应用进程,否则杀进程或者开机后进程不会开启,只能手动开启应用
- 三星
- 内存一键优化:需要将应用加入【白名单】列表,否则系统内存优化后,会杀掉应用进程
- Android集成极光推送和踩过的坑(一)
- Android 极光推送的集成
- iOS 极光推送踩过的坑~
- Android集成极光推送踩坑(二)升级篇
- Android studio一分钟集成极光推送以及集成时遇到的混淆神坑
- Android 极光推送集成
- android极光推送集成
- Android集成极光推送
- android集成极光推送
- Android集成极光推送
- android 集成极光推送
- Android极光推送集成和跳转
- iOS 集成极光推送(一)
- Android 集成极光推送(Android studio)
- android studio极光推送的集成
- Android 集成极光推送的第三方
- Android集成极光推送 的异常
- Android JPush的集成 极光推送
- js,java上传文件到服务器
- python django web开发之项目创建
- 华为OJ系列(四)
- 安卓图片压缩
- String 操作方法
- Android集成极光推送和踩过的坑(一)
- 如何查看Activity任务栈以及dumpsys_activity命令的简要使用及介绍
- Java占位符替换工具类
- mysql数据库给表创建序列
- 深入理解JVM(2)——内存区域与内存溢出
- 学习笔记——JAVA 内部类
- 用递归方式将当前路径下的文件按行输出
- No route to host: Datagram send failed UDP广播异常
- Android shrinkResources 问题