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 end

sdk文档说明:

参数定义    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 的管理软件需要用户手动操作

  • 小米【MIUI】

    • 自启动管理:需要把应用加到【自启动管理】列表,否则杀进程或重新开机后进程无法开启
    • 通知栏设置:应用默认都是显示通知栏通知,如果关闭,则收到通知也不会提示
    • 网络助手:可以手动禁止已安装的第三方程序访问2G/3G和WIFI的网络和设置以后新安装程序是否允许访问2G/3G和WIFI的网络
    • MIUI 7 神隐模式: 允许应用进行自定义配置模式,应用在后台保持联网可用,否则应用进入后台时,应用无法正常接收消息。【设置】下电量和性能中【神隐模式】
  • 华为【Emotion】

    • 自启动管理:需要把应用加到【自启动管理】列表,否则杀进程或重新开机后进程不会开启,只能手动开启应用
    • 后台应用保护:需要手动把应用加到此列表,否则设备进入睡眠后会自动杀掉应用进程,只有手动开启应用才能恢复运行
    • 通知管理:应用状态有三种:提示、允许、禁止。禁止应用则通知栏不会有任何提醒
  • 魅族【Flyme】

    • 自启动管理:需要把应用加到【自启动管理】列表,否则杀进程或重新开机后进程无法开启
    • 通知栏推送:关闭应用通知则收到消息不会有任何展示
    • 省电管理: 安全中心里设置省电模式,在【待机耗电管理】中允许应用待机时,保持允许,否则手机休眠或者应用闲置一段时间,无法正常接收消息。
  • VIVO【Funtouch OS】

    • 内存一键清理:需要将应用加入【白名单】列表,否则系统自带的“一键加速”,会杀掉进程
    • 自启动管理:需要将应用加入“i管家”中的【自启动管理】列表,否则重启手机后进程不会自启。但强制手动杀进程,即使加了这个列表中,后续进程也无法自启动。
  • OPPO【ColorOS】

    • 冻结应用管理:需要将应用加入纯净后台,否则锁屏状态下无法及时收到消息
    • 自启动管理:将应用加入【自启动管理】列表的同时,还需要到设置-应用程序-正在运行里锁定应用进程,否则杀进程或者开机后进程不会开启,只能手动开启应用
  • 三星
    • 内存一键优化:需要将应用加入【白名单】列表,否则系统内存优化后,会杀掉应用进程
如果没有解决你的问题,请移步 Android集成极光推送踩坑(二)升级篇











原创粉丝点击