本文中涉及到的全部代码现已在Github上开源,地址: https://github.com/xuexiangjys/JPushSamplejava
极光推送是国内最先作第三方消息推送平台的公司,在消息推送界仍是相对有影响力的。我最先是在2016年接触到极光消息推送的,那时候公司须要作消息推送业务,可是因为以前没作过消息推送,且自建消息推送平台代价过高,并且稳不稳定谁也不敢打包票,因而就选择了当时较为有名的极光推送。android
那么当时我为何选择极光推送呢?git
那么极光推送真的有那么好吗?其实也不全是,我在使用的过程当中也发现了一些问题:github
不过若是你是消息推送的初学者的话,我想极光推送确定是你不二的选择。那么下面来跟着我学习如何使用极光推送吧!json
本文是基于jpush:3.5.4
和jcore:2.2.6
版本介绍的,暂只介绍最新推荐的使用方法,那些过期的用法这里我就很少介绍了,想了解的能够去 极光推送官方文档查看。
在接入极光推送前,首先须要获取到应用的AppKey,它是应用的惟一标识。
1.建立极光推送开发者账号服务器
要建立极光推送开发者账号,请访问极光推送官方网站: https://www.jiguang.cn/push网络
2.建立应用并发
进入极光控制台后,点击“建立应用”按钮,填写应用名称便可建立应用成功。同时点击“推送设置”,在 Android 版块填上你的应用包名,选择保存便可。app
3.获取应用的AppKey框架
在极光控制台点击"应用设置"中的"应用信息",获取应用的AppKey。
使用 jcenter 自动集成的开发者,不须要在项目中添加 jar 和 so,jcenter 会自动完成依赖;在 AndroidManifest.xml 中不须要添加任何 JPush SDK 相关的配置,jcenter 会自动导入。
1.配置项目的build.gradle
文件
android { defaultConfig { applicationId "com.xxx.xxx" //JPush平台上注册的应用包名. ... ndk { //选择要添加的对应 cpu 类型的 .so 库。 abiFilters 'armeabi', 'armeabi-v7a', 'arm64-v8a' //,'x86', 'x86_64', 'mips', 'mips64' } manifestPlaceholders = [ JPUSH_PKGNAME: defaultConfig.applicationId, JPUSH_APPKEY : "你的 Appkey ",//值来自开发者平台取得的AppKey JPUSH_CHANNEL: "default_developer", ] } } dependencies { ... //引入JPush依赖库 implementation 'cn.jiguang.sdk:jpush:3.5.4' implementation 'cn.jiguang.sdk:jcore:2.2.6' }
2.配置项目的AndroidManifest.xml
文件
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.xuexiang.jpush"> <application> <!-- 1.这个是自定义Service,要继承极光JCommonService,能够在更多手机平台上使得推送通道保持的更稳定 --> <service android:name=".PushService" android:enabled="true" android:exported="false" android:process=":pushcore"> <intent-filter> <action android:name="cn.jiguang.user.service.action" /> </intent-filter> </service> <!-- 2.用户自定义接收消息器,全部你想要知道的消息都在这里--> <receiver android:name=".core.push.PushMessageReceiver"> <intent-filter> <action android:name="cn.jpush.android.intent.RECEIVE_MESSAGE" /> <category android:name="${applicationId}" /> </intent-filter> </receiver> </application> </manifest>
1.首先你须要先去下载SDK,下载地址: https://docs.jiguang.cn/jpush...
2.解压SDK,将压缩包下的libs内容复制到项目的libs下
3.配置项目的build.gradle
文件
android { defaultConfig { applicationId "com.xxx.xxx" //JPush平台上注册的应用包名. ... ndk { //选择要添加的对应 cpu 类型的 .so 库。 abiFilters 'armeabi', 'armeabi-v7a', 'arm64-v8a' //,'x86', 'x86_64', 'mips', 'mips64' } manifestPlaceholders = [ JPUSH_PKGNAME: defaultConfig.applicationId, JPUSH_APPKEY : "你的 Appkey ",//值来自开发者平台取得的AppKey JPUSH_CHANNEL: "default_developer", ] } sourceSets { //设置libs目录为so包的加载目录 main { jniLibs.srcDirs = ['libs'] } } }
4.配置项目的AndroidManifest.xml
文件
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.xxx.xxx"> <permission android:name="${applicationId}.permission.JPUSH_MESSAGE" android:protectionLevel="signature" /> <!-- Required 一些系统要求的权限,如访问网络等--> <uses-permission android:name="${applicationId}.permission.JPUSH_MESSAGE" /> <uses-permission android:name="android.permission.RECEIVE_USER_PRESENT" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_SETTINGS" /> <uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <!-- 用于开启 debug 版本的应用在6.0 系统上 层叠窗口权限 --> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <!-- Optional for location --> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" /> <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /> <uses-permission android:name="android.permission.GET_TASKS" /> <application> <!-- Required SDK核心功能--> <activity android:name="cn.jpush.android.ui.PushActivity" android:configChanges="orientation|keyboardHidden" android:exported="false" android:theme="@android:style/Theme.NoTitleBar"> <intent-filter> <action android:name="cn.jpush.android.ui.PushActivity" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="${applicationId}" /> </intent-filter> </activity> <!-- Required SDK 核心功能--> <!-- 可配置android:process参数将PushService放在其余进程中 --> <service android:name="cn.jpush.android.service.PushService" android:exported="false" android:process=":pushcore"> <intent-filter> <action android:name="cn.jpush.android.intent.REGISTER" /> <action android:name="cn.jpush.android.intent.REPORT" /> <action android:name="cn.jpush.android.intent.PushService" /> <action android:name="cn.jpush.android.intent.PUSH_TIME" /> </intent-filter> </service> <!-- since 3.0.9 Required SDK 核心功能--> <provider android:name="cn.jpush.android.service.DataProvider" android:authorities="${applicationId}.DataProvider" android:exported="false" /> <!-- since 1.8.0 option 可选项。用于同一设备中不一样应用的JPush服务相互拉起的功能。 --> <!-- 若不启用该功能可删除该组件,将不拉起其余应用也不能被其余应用拉起 --> <service android:name="cn.jpush.android.service.DaemonService" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="cn.jpush.android.intent.DaemonService" /> <category android:name="${applicationId}" /> </intent-filter> </service> <!-- since 3.1.0 Required SDK 核心功能--> <provider android:name="cn.jpush.android.service.DownloadProvider" android:authorities="${applicationId}.DownloadProvider" android:exported="true" /> <!-- Required SDK核心功能--> <receiver android:name="cn.jpush.android.service.PushReceiver" android:enabled="true" android:exported="false"> <intent-filter android:priority="1000"> <!--Required 显示通知栏 --> <action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED_PROXY" /> <category android:name="${applicationId}" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.USER_PRESENT" /> <action android:name="android.net.conn.CONNECTIVITY_CHANGE" /> </intent-filter> <!-- Optional --> <intent-filter> <action android:name="android.intent.action.PACKAGE_ADDED" /> <action android:name="android.intent.action.PACKAGE_REMOVED" /> <data android:scheme="package" /> </intent-filter> </receiver> <!-- Required SDK核心功能--> <receiver android:name="cn.jpush.android.service.AlarmReceiver" android:exported="false" /> <!--since 3.3.0 Required SDK核心功能--> <activity android:name="cn.jpush.android.service.JNotifyActivity" android:exported="true" android:taskAffinity="jpush.custom" android:theme="@android:style/Theme.Translucent.NoTitleBar"> <intent-filter> <action android:name="cn.jpush.android.intent.JNotifyActivity" /> <category android:name="${applicationId}" /> </intent-filter> </activity> <!-- *********************下面这两个是须要你本身定义的**************************** --> <!-- since 3.3.0 Required SDK 核心功能--> <!-- 1.这个是自定义Service,要继承极光JCommonService,能够在更多手机平台上使得推送通道保持的更稳定 --> <service android:name=".PushService" android:enabled="true" android:exported="false" android:process=":pushcore"> <intent-filter> <action android:name="cn.jiguang.user.service.action" /> </intent-filter> </service> <!-- 2.用户自定义接收消息器,全部你想要知道的消息都在这里--> <receiver android:name=".core.push.PushMessageReceiver"> <intent-filter> <action android:name="cn.jpush.android.intent.RECEIVE_MESSAGE" /> <category android:name="${applicationId}" /> </intent-filter> </receiver> <meta-data android:name="JPUSH_CHANNEL" android:value="${JPUSH_CHANNEL}" /> <!-- 值来自开发者平台取得的AppKey--> <meta-data android:name="JPUSH_APPKEY" android:value="${JPUSH_APPKEY}" /> </application> </manifest>
1.在Application中初始化JPush
public class MyApp extends Application { @Override public void onCreate() { super.onCreate(); initJPush(); } } /** * 初始化极光推送 */ private void initJPush() { JPushInterface.setDebugMode(BuildConfig.DEBUG); //只须要在应用程序启动时调用一次该 API 便可 JPushInterface.init(this); }
2.在应用的第一个页面申请权限(可选)
因为Android手机定制ROM太多,部分手机的通知栏权限默认是关闭的,须要用户手动打开。若是不打开通知栏权限的话,即便你连上了推送,也没法收到推送消息。
/** * 申请定位、存储和通知栏的权限 * * @param activity */ public static void requestPermission(Activity activity) { //打开通知栏的权限 if (JPushInterface.isNotificationEnabled(activity) == 0) { new AlertDialog.Builder(activity) .setCancelable(false) .setMessage("通知权限未打开,是否前去打开?") .setPositiveButton("是", (d, w) -> JPushInterface.goToAppNotificationSettings(activity)) .setNegativeButton("否", null) .show(); } //申请定位、存储权限 JPushInterface.requestPermission(activity); }
当完成以上步骤后,可直接运行程序,并查看logcat日志,设置过滤条件为"JIGUANG",若是出现"Register succeed"和"registrationId:xxxxxxxxxxxxxx"字样,即为集成成功!以下图所示:
注意事项:
配置项目的proguard-rules.pro
文件。
-dontoptimize -dontpreverify -dontwarn cn.jpush.** -keep class cn.jpush.** { *; } -dontwarn cn.jiguang.** -keep class cn.jiguang.** { *; } -keep class cn.jiguang.** { *; } -keep class * extends cn.jpush.android.service.JPushMessageReceiver{*;}
1.上面已经讲过了,推送初始化建议在自定义的 Application 中的 onCreate 中调用,且推送初始化只须要调用一次便可。
JPushInterface.init(Context context);
2.推送初始化成功后,平台会返回一个惟一的token令牌,那就是RegistrationID
,获取它的方法以下:
JPushInterface.getRegistrationID(Context context);
3.获取当前推送的链接状态方法以下:
JPushInterface.getConnectionState(Context context)
1.中止推送。在某些业务中,咱们须要临时暂停推送,例如帐户退出登录等,这个时候咱们能够调用以下方法:
JPushInterface.stopPush(Context context);
须要注意的是,这里的中止推送只是个本地客户端的操做,并不会通知到推送服务平台。其表现效果相似设备断网,将不会收到任何推送消息,而且极光推送全部的其余 API 调用都无效,除了resumePush
恢复推送服务的方法。
2.恢复推送。当调用了中止推送的方法后,只有调用恢复推送的方法后,极光推送服务才能正常工做。方法以下:
JPushInterface.resumePush(Context context);
3.获取推送的工做状态。想要知道当前推送服务是否正在工做,可经过以下方法:
JPushInterface.isPushStopped(Context context);
别名在极光推送中尤其重要,一般咱们用得最多的就是根据别名进行推送。咱们一般的作法是用户登录后,业务平台会返回一个平台生成的惟一识别号做为推送的别名,而后后台须要推送的时候,就直接拿着这个别名通知极光推送服务进行消息推送。
1.绑定别名alias。
JPushInterface.setAlias(Context context, int sequence, String alias);
2.解绑别名alias。
JPushInterface.deleteAlias(Context context, int sequence);
3.获取绑定的别名alias。
JPushInterface.getAlias(Context context, int sequence);
注意事项:
1.这里的sequence
主要就是操做识别码,用于识别操做类型,由使用者本身定义。
2.以上全部的方法返回的都是void(都是异步操做),方法的返回都在自定义的消息接收器中,就是上面继承JPushMessageReceiver由使用者自定义的广播接收器中获取。
3.别名相关操做的结果都在JPushMessageReceiver
的onAliasOperatorResult
方法中回调,须要获取别名操做结果的可重写该方法。
标签比如一个分组,当咱们须要对某一类特殊群体进行消息推送时,即可使用标签进行推送。
1.增长标签Tags。这是一个增量请求。
JPushInterface.addTags(Context context, int sequence, Set<String> tags);
2.删除标签Tags。
JPushInterface.deleteTags(Context context, int sequence, Set<String> tags);
3.获取标签Tags。
JPushInterface.getAllTags(Context context, int sequence);
4.设置标签Tags。这是一个全量请求,会覆盖以前设置的标签。
JPushInterface.setTags(Context context, int sequence, Set<String> tags);
5.清除全部标签。
JPushInterface.cleanTags(Context context, int sequence);
6.查询指定 tag 与当前用户绑定的状态。
JPushInterface.checkTagBindState(Context context, int sequence, String tag);
注意事项:
1.这里的sequence
和别名方法中的同样,也是操做识别码,用于识别操做类型,由使用者本身定义。
2.以上全部的方法返回的都是void(都是异步操做),方法的返回都在自定义的消息接收器中,就是上面继承JPushMessageReceiver由使用者自定义的广播接收器中获取。
3.标签相关操做的结果都在JPushMessageReceiver
的onTagOperatorResult
方法中回调,须要获取标签操做结果的可重写该方法。
4.checkTagBindState
方法的结果是在JPushMessageReceiver
的onCheckTagOperatorResult
方法中回调,须要获取标签查询匹配结果的可重写该方法。
这里的操做主要包括:注册、别名(绑定、解绑、获取)、标签(添加、删除、获取、设置、清除、状态检查)、手机号设置等。因为极光提供的这些操做都是异步的,且方法不能直接返回结果和提供回调接口,所以只能经过重写
JPushMessageReceiver
中相应的方法获取。
全部的操做结果均可以从JPushMessageReceiver
提供的回调方法中获取。可是JPushMessageReceiver
最多只能做为消息的中转站,使用起来极为不便,所以咱们能够结合一些事件机制来处理,将这些结果包装为一个个推送事件向外发出去,这样只须要在须要的地方订阅一下事件就能够获取到结果了。下面我以RxBus为例简单编写,使用的库是个人开源库RxUtil2
1.定义操做事件的类型,用于识别操做类型。上文中提到的sequence
参数就可使用它。
/** * 推送事件的类型 */ @IntDef({TYPE_REGISTER, TYPE_UNREGISTER, TYPE_CONNECT_STATUS_CHANGED, TYPE_ADD_TAGS, TYPE_DEL_TAGS, TYPE_GET_TAGS, TYPE_BIND_ALIAS, TYPE_UNBIND_ALIAS, TYPE_GET_ALIAS}) @Retention(RetentionPolicy.SOURCE) public @interface EventType { /** * 注册推送 */ int TYPE_REGISTER = 2000; /** * 取消注册推送 */ int TYPE_UNREGISTER = 2001; /** * 推送链接状态发生变化 */ int TYPE_CONNECT_STATUS_CHANGED = 2002; /** * 绑定别名 */ int TYPE_BIND_ALIAS = 2010; /** * 解绑别名 */ int TYPE_UNBIND_ALIAS = 2011; /** * 获取别名 */ int TYPE_GET_ALIAS = 2012; /** * 添加标签[增量] */ int TYPE_ADD_TAGS = 2020; /** * 删除标签 */ int TYPE_DEL_TAGS = 2021; /** * 获取标签 */ int TYPE_GET_TAGS = 2022; /** * 设置标签[全量] */ int TYPE_SET_TAGS = 2023; /** * 清除全部标签 */ int TYPE_CLEAN_TAGS = 2024; /** * 查询指定 tag 与当前用户绑定的状态 */ int TYPE_CHECK_TAG_BIND_STATE = 2025; }
2.定义推送事件的载体.
该载体只须要定义三个成员变量:mType(事件类型)、mIsSuccess(是否成功)、mData(携带的数据)。以下所示:
/** * 推送事件的载体 */ public final class PushEvent { public static final String KEY_PUSH_EVENT = "com.xuexiang.jpushsample.core.push.event.KEY_PUSH_EVENT"; /** * 事件类型 */ private int mType; /** * 是否成功(也能够定义为int型的结果码) */ private boolean mIsSuccess; /** * 携带的数据(也能够定义为String型的数据) */ private Object mData; public PushEvent(@EventType int type) { mType = type; } public PushEvent(@EventType int type, boolean isSuccess) { mType = type; mIsSuccess = isSuccess; } public PushEvent(@EventType int type, Object data) { mType = type; mData = data; } public int getType() { return mType; } public PushEvent setType(@EventType int type) { mType = type; return this; } public boolean isSuccess() { return mIsSuccess; } public PushEvent setSuccess(boolean success) { mIsSuccess = success; return this; } public Object getData() { return mData; } public PushEvent setData(Object data) { mData = data; return this; } }
3.事件处理并发送.
在JPushMessageReceiver
中重写指定的方法,并将结果转译为一个个PushEvent
发送出去。
/** * 极光推送消息接收器 */ public class PushMessageReceiver extends JPushMessageReceiver { private static final String TAG = "JPush-Receiver"; //======================下面的都是操做的回调=========================================// @Override public void onRegister(Context context, String registrationId) { Log.e(TAG, "[onRegister]:" + registrationId); RxBusUtils.get().post(KEY_PUSH_EVENT, new PushEvent(EventType.TYPE_REGISTER, true, registrationId)); } /** * 链接状态发生变化 * * @param context * @param isConnected 是否已链接 */ @Override public void onConnected(Context context, boolean isConnected) { Log.e(TAG, "[onConnected]:" + isConnected); RxBusUtils.get().post(KEY_PUSH_EVENT, new PushEvent(EventType.TYPE_CONNECT_STATUS_CHANGED, isConnected)); } /** * 全部和标签相关操做结果 * * @param context * @param jPushMessage */ @Override public void onTagOperatorResult(Context context, JPushMessage jPushMessage) { Log.e(TAG, "[onTagOperatorResult]:" + jPushMessage); PushEvent pushEvent = new PushEvent(jPushMessage.getSequence(), jPushMessage.getErrorCode() == 0) .setData(JPushInterface.getStringTags(jPushMessage.getTags())); RxBusUtils.get().post(KEY_PUSH_EVENT, pushEvent); } /** * 全部和别名相关操做结果 * * @param context * @param jPushMessage */ @Override public void onAliasOperatorResult(Context context, JPushMessage jPushMessage) { Log.e(TAG, "[onAliasOperatorResult]:" + jPushMessage); PushEvent pushEvent = new PushEvent(jPushMessage.getSequence(), jPushMessage.getErrorCode() == 0) .setData(jPushMessage.getAlias()); RxBusUtils.get().post(KEY_PUSH_EVENT, pushEvent); } /** * 标签状态检测结果 * * @param context * @param jPushMessage */ @Override public void onCheckTagOperatorResult(Context context, JPushMessage jPushMessage) { Log.e(TAG, "[onCheckTagOperatorResult]:" + jPushMessage); PushEvent pushEvent = new PushEvent(jPushMessage.getSequence(), jPushMessage.getErrorCode() == 0) .setData(jPushMessage); RxBusUtils.get().post(KEY_PUSH_EVENT, pushEvent); } }
4.在须要获取结果的地方订阅或者取消事件。
@Override protected void initListeners() { //订阅推送事件 mPushEvent = RxBusUtils.get().onMainThread(KEY_PUSH_EVENT, PushEvent.class, this::handlePushEvent); } /** * 处理推送事件,获取操做的结果 * @param pushEvent */ private void handlePushEvent(PushEvent pushEvent) { String content = pushEvent.getData().toString(); switch (pushEvent.getType()) { case TYPE_BIND_ALIAS: if (pushEvent.isSuccess()) { tvAlias.setText(content); XToastUtils.success("别名[" + content + "]绑定成功"); } else { XToastUtils.error("别名[" + content + "]绑定失败"); } break; case TYPE_UNBIND_ALIAS: //别名解绑 break; case TYPE_GET_ALIAS: //获取别名 break; case TYPE_ADD_TAGS: //添加标签 break; case TYPE_DEL_TAGS: //删除标签 break; case TYPE_GET_TAGS: //获取标签 break; case TYPE_SET_TAGS: //设置标签 break; case TYPE_CLEAN_TAGS: //清除标签 break; case TYPE_CHECK_TAG_BIND_STATE: //检查标签 break; ........ default: break; } } @Override public void onDestroyView() { if (mPushEvent != null) { //取消订阅推送事件 RxBusUtils.get().unregister(KEY_PUSH_EVENT, mPushEvent); mPushEvent = null; } super.onDestroyView(); }
点击参见自定义JPushMessageReceiver的源码
自定义消息,又称之为透传消息。顾名思义是由使用者本身定义一套解析格式的消息,这种消息在接收到后不会有任何界面上的展现,携带内容为String型,一般的作法是传一个json。这种比较灵活的消息推送方式是最经常使用的一种。可是这里须要注意的是,这种消息是一种应用内的消息,一旦应用被杀死,将没法及时收到该消息。
1.自定义消息体(CustomMessage)介绍
字段名 | 类型 | 字段说明 |
---|---|---|
messageId | String | 消息ID,对应推送平台上的消息惟一号 |
message | String | 对应推送消息界面上的“自定义消息内容”字段 |
extra | String | 保存服务器推送下来的附加字段。这是个 JSON 字符串,对应推送消息界面上的“可选设置”里的附加字段。 |
title | String | 消息的标题(没多大做用) |
2.自定义消息接收
若是想要接收自定义消息,只需重写JPushMessageReceiver
中的onMessage
方法便可。在onMessage
方法中将会回调CustomMessage
自定义消息体。
普统统知消息,就是在系统通知栏上显示的消息。可是若是通知的内容为空,则不会在通知栏上展现通知。
1.通知消息体(NotificationMessage)介绍
字段名 | 类型 | 字段说明 |
---|---|---|
messageId | String | 消息ID,对应推送平台上的消息惟一号 |
notificationId | int | 通知栏的 Notification ID,用于清除 Notification |
notificationTitle | String | 通知的标题,对应推送通知界面上的“通知标题”字段 |
notificationContent | String | 通知的内容,对应推送通知界面上的“通知内容”字段 |
notificationExtras | String | 附加字段,对应推送通知界面上的“可选设置”里的附加字段 |
notificationTitle | String | 通知的标题,对应推送通知界面上的“通知标题”字段 |
2.普统统知消息接收
若是想要接收自定义消息,只需重写JPushMessageReceiver
中的onNotifyMessageArrived
方法便可。在onNotifyMessageArrived
方法中将会回调NotificationMessage
通知消息体。
3.通知消息被点击
在作消息推送开发的时候,咱们必定会有一个需求:但愿用户点击通知后,可以自动跳转到咱们应用的某个页面。这个页面多是某一个活动宣传页面,也有多是某个新闻或者视频页面。这个时候,咱们就须要对通知消息点击后的动做进行自定义。
那么咱们该如何自定义通知消息被点击后的动做呢?很简单,咱们只须要重写JPushMessageReceiver
中的onNotifyMessageOpened
方法,在方法中读取传递过来的参数,而后结合页面路由机制(例如:ARouter)直接跳转至指定页面便可。
下面我将经过两种不一样的途径来实现 点击通知消息后跳转至某一特定界面:
1.重写JPushMessageReceiver
中的onNotifyMessageOpened
方法。
public class PushMessageReceiver extends JPushMessageReceiver { /** * 点击通知回调 * * @param context * @param message 通知消息 */ @Override public void onNotifyMessageOpened(Context context, NotificationMessage message) { Log.e(TAG, "[onNotifyMessageOpened]:" + message); //自定义打开到通知栏点击后的容器页 Intent intent = parseNotificationMessage(IntentUtils.getIntent(context, NotificationTransferActivity.class, null, true), message); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); ActivityUtils.startActivity(intent); } /** * 解析极光通知消息:NotificationMessage */ public static Intent parseNotificationMessage(@NonNull Intent intent, NotificationMessage message) { //这只是一个例子,暂时把跳转的目标页设为 "通知信息展现" intent.putExtra("pageName", "通知信息展现"); //通知标题 intent.putExtra("title", message.notificationTitle); //通知内容 intent.putExtra("content", message.notificationContent); //通知附带拓展内容 intent.putExtra("extraMsg", message.notificationExtras); //通知附带键值对 intent.putExtra("keyValue", message.notificationExtras); return intent; } }
2.经过DeepLink
技术和通知栏中可选设置的自定义(打开指定页面)
相结合的方法。
(1)首先须要在AndroidManifest.xml
中定义deeplink拦截。
<!--通知被点击以后跳转的页面--> <activity android:name=".activity.NotificationTransferActivity"> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <data android:host="com.xuexiang.jpush" android:path="/notification" android:scheme="jpush" /> </intent-filter> </activity>
(2)在容器界面NotificationTransferActivity
中解析传递过来的参数。
/** * 通知栏点击后的容器页 * * deeplink格式 * * jpush://com.xuexiang.jpush/notification?pageName=通知信息展现&title=这是一个通知&content=这是通知的内容&extraMsg=xxxxxxxxx&keyValue={"param1": "1111", "param2": "2222"} * */ @Router(path = "/push/notification/transfer") public class NotificationTransferActivity extends BaseActivity { @AutoWired String pageName; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); XRouter.getInstance().inject(this); Uri uri = getIntent().getData(); Bundle bundle = getIntent().getExtras(); if (uri != null) { //deeplink跳转 pageName = uri.getQueryParameter("pageName"); bundle = Utils.parseNotificationDeepLinkUri(uri, bundle); } if (!StringUtils.isEmpty(pageName)) { //打开指定页面 if (openPage(pageName, bundle) == null) { XToastUtils.toast("页面未找到!"); finish(); } } else { XToastUtils.toast("页面未找到!"); finish(); } } /** * DeepLink的格式: * jpush://com.xuexiang.jpush/notification?pageName=xxxxx&title=这是一个通知&content=这是通知的内容&extraMsg=xxxxxxxxx&keyValue={"param1": "1111", "param2": "2222"} * @param uri * @param bundle * @return */ public static Bundle parseNotificationDeepLinkUri(@NonNull Uri uri, Bundle bundle) { if (bundle == null) { bundle = new Bundle(); } bundle.putString("pageName", uri.getQueryParameter("pageName")); //通知标题 bundle.putString("title", uri.getQueryParameter("title")); //通知内容 bundle.putString("content", uri.getQueryParameter("content")); //通知附带拓展内容 bundle.putString("extraMsg", uri.getQueryParameter("extraMsg")); //通知附带键值对 bundle.putString("keyValue", uri.getQueryParameter("keyValue")); return bundle; } }
注意:上面的openPage
方法主要使用了个人开源XPage,主要的做用就是Fragment页面路由,加载一个Fragment页面。
(3)发通知消息的时候,记得设置上自定义(打开指定页面)
的连接,以下图所示:
jpush://com.xuexiang.jpush/notification?pageName=xxxxx&title=这是一个通知&content=这是通知的内容&extraMsg=xxxxxxxxx&keyValue={"param1": "1111", "param2": "2222"}
一样的,自定义消息和通知消息都是在JPushMessageReceiver
的回调方法中获取,和上面的操做结果相似,JPushMessageReceiver
最多只是做为消息的中转站,若是咱们想要在任何页面都可以订阅到接收到的消息,那么咱们依旧能够和上面处理得同样,使用RxBus将这些消息向外发送出去。
下面我给出实现的简要步骤:
1.定义消息的类型,这里暂时就是自定义消息和通知消息。
/** * 消息的类型 */ @IntDef({TYPE_CUSTOM, TYPE_NOTIFICATION}) @Retention(RetentionPolicy.SOURCE) public @interface MessageType { /** * 自定义消息 */ int TYPE_CUSTOM = 1000; /** * 普统统知消息 */ int TYPE_NOTIFICATION = 1001; }
2.定义推送消息的载体.
目前为了偷懒,暂时就只定义了两个成员变量:mType(消息类型)和mMessage(消息数据)。以下所示:
/** * 推送消息 */ public final class PushMessage { public static final String KEY_PUSH_MESSAGE = "com.xuexiang.jpushsample.core.push.event.KEY_PUSH_MESSAGE"; /** * 消息类型 */ private int mType; /** * 消息数据 */ private Object mMessage; public static PushMessage wrap(@MessageType int type, Object message) { return new PushMessage(type, message); } public PushMessage(@MessageType int type, Object message) { mType = type; mMessage = message; } public int getType() { return mType; } public PushMessage setType(int type) { mType = type; return this; } public <T> T getMessage() { return (T) mMessage; } public PushMessage setMessage(Object message) { mMessage = message; return this; } public String getMessageType() { switch (mType) { case TYPE_CUSTOM: return "自定义消息"; case TYPE_NOTIFICATION: return "普统统知消息"; default: return "未知消息"; } } }
3.消息接收并分发.
在JPushMessageReceiver
中重写onMessage
和onNotifyMessageArrived
方法,并将结果转译为一个个PushMessage
发送出去。
/** * 极光推送消息接收器 */ public class PushMessageReceiver extends JPushMessageReceiver { private static final String TAG = "JPush-Receiver"; /** * 收到自定义消息回调 * * @param context * @param message 自定义消息 */ @Override public void onMessage(Context context, CustomMessage message) { Log.e(TAG, "[onMessage]:" + message); RxBusUtils.get().post(KEY_PUSH_MESSAGE, PushMessage.wrap(MessageType.TYPE_CUSTOM, message)); } /** * 收到通知回调 * * @param context * @param message 通知消息 */ @Override public void onNotifyMessageArrived(Context context, NotificationMessage message) { Log.e(TAG, "[onNotifyMessageArrived]:" + message); RxBusUtils.get().post(KEY_PUSH_MESSAGE, PushMessage.wrap(MessageType.TYPE_NOTIFICATION, message)); } }
此外,若是因业务须要,在消息发送出去以前,咱们还能够在发送前添加一个过滤器处理,对一些重复、无效的消息进行过滤,或者对同时接收到的消息进行消息合并等操做。
4.在须要获取推送消息的地方订阅。
@Override protected void initListeners() { //订阅消息 RxBusUtils.get().onMainThread(KEY_PUSH_MESSAGE, PushMessage.class, this::handlePushMessage); } /** * 处理接收到的推送消息 */ private void handlePushMessage(PushMessage pushMessage) { tvType.setText(pushMessage.getMessageType()); tvMessage.setText(pushMessage.getMessage().toString()); } @Override public void onDestroyView() { //取消订阅 RxBusUtils.get().unregisterAll(KEY_PUSH_MESSAGE); super.onDestroyView(); }
好啦,以上就是《极光推送之Android客户端使用指南--基础篇》的所有内容,本文主要介绍了极光推送最经常使用也是最基础的几部份内容,相信若是你能彻底掌握上面的内容的话,推送基本上也算是得心应手了.下面我还将深刻挖掘极光推送的几个高级使用,敬请期待吧!