一、前言
这篇文章主要来讲解推送的使用,例如我们一打开手机或者一联网经常看到微博客户端或者新闻客户端推送一条信息,我们可以点开通知栏上通知的信息,跳到相应的新闻页面,这些功能的实现看似都是通过服务端发消息给客户端来实现的,实则不然。
推送的原理大都相似,都是通过一个中转服务器,初始化的时候客户端和服务端都在服务器上注册好自己的设备信息,一旦服务端需要发推送消息时,就会给中转服务器发送一条请求,把需要推送的消息以某种形式发送过去,一旦中转服务器接收到服务端发送的消息,就会按照一定的分类推送到对应的提前注册好的客户端的设备上,这一过程其实相当于发送一个广播,客户端接收到广播,就可以做出相应的处理。
此处讲解的极光推送是免费使用的一个推送平台,当然市场上还有很多其他的推送平台,例如信鸽推送、个推等,以后有机会会给大家分享。
二、集成步骤
1、添加依赖:
compile 'cn.jiguang:jpush:2.1.8'
2、添加配置信息到app Moodule的配置文件:主要是添加so库
ndk { //选择要添加的对应cpu类型的.so库。 abiFilters 'armeabi', 'armeabi-v7a', 'armeabi-v8a' // 还可以添加 'x86', 'x86_64', 'mips', 'mips64' } manifestPlaceholders = [ JPUSH_PKGNAME : applicationId, JPUSH_APPKEY : "5fb3633d94f621b14850b194", //JPush上注册的包名对应的appkey. JPUSH_CHANNEL : "developer-default", //暂时填写默认值即可. ]
3、添加ndk权限:
android.useDeprecatedNdk=true
4、添加推送权限
<!-- Required --> <permission android:name="com.project.fors.jpush.permission.JPUSH_MESSAGE" android:protectionLevel="signature" /> <!-- Required --> <uses-permission android:name="com.project.fors.jpush.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.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.WRITE_SETTINGS" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <!-- Optional. Required for location feature --> <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" />
5、添加manifests配置信息:此配置信息中很多地方需要修改为你自己的项目的包名,需仔细检查并修改,所配置的相应service或者receiver都是配置文件中所必须的核心类,万不可删去
<!-- Required SDK 核心功能--> <!-- option since 2.0.5 可配置PushService,DaemonService,PushReceiver,AlarmReceiver的android:process参数 将JPush相关组件设置为一个独立进程 --> <!-- 如:android:process=":remote" --> <service android:name="cn.jpush.android.service.PushService" android:enabled="true" android:exported="false"> <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 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="com.project.fors.jpush" /> </intent-filter> </service> <!-- Required --> <receiver android:name="cn.jpush.android.service.PushReceiver" android:enabled="true"> <intent-filter android:priority="1000"> <action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED_PROXY" /> <category android:name="com.project.fors.jpush" /> </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核心功能--> <activity android:name="cn.jpush.android.ui.PushActivity" android:configChanges="orientation|keyboardHidden" android:exported="false"> <intent-filter> <action android:name="cn.jpush.android.ui.PushActivity" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="com.project.fors.jpush" /> </intent-filter> </activity> <!-- Required SDK核心功能--> <service android:name="cn.jpush.android.service.DownloadService" android:enabled="true" android:exported="false"></service> <!-- Required SDK核心功能--> <receiver android:name="cn.jpush.android.service.AlarmReceiver" /> <!-- User defined. 用户自定义的广播接收器--> <receiver android:name="com.project.fors.jpush.MyReceiver" android:enabled="true"> <intent-filter> <!--Required 用户注册SDK的intent--> <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 用户打开自定义通知栏的intent--> <action android:name="cn.jpush.android.intent.NOTIFICATION_OPENED" /> <!-- 接收网络变化 连接/断开 since 1.6.3 --> <action android:name="cn.jpush.android.intent.CONNECTION" /> <category android:name="com.project.fors.jpush" /> </intent-filter> </receiver> <!-- Required. For publish channel feature --> <!-- JPUSH_CHANNEL 是为了方便开发者统计APK分发渠道。--> <!-- 例如: --> <!-- 发到 Google Play 的APK可以设置为 google-play; --> <!-- 发到其他市场的 APK 可以设置为 xxx-market。 --> <!-- 目前这个渠道统计功能的报表还未开放。--> <meta-data android:name="JPUSH_CHANNEL" android:value="developer-default" /> <!-- Required. AppKey copied from Portal --> <meta-data android:name="JPUSH_APPKEY" android:value="Your AppKey" />
6、添加自定义接收器MyReceiver类:待接收到推送消息后用来做客户端自己的处理,根据接受消息的不同,可以做出相应的处理
/** * 自定义接收器 * * 如果不定义这个 Receiver,则: * 1) 默认用户会打开主界面 * 2) 接收不到自定义消息 */ public class MyReceiver extends BroadcastReceiver { private static final String TAG = "JPush"; @Override public void onReceive(Context context, Intent intent) { Bundle bundle = intent.getExtras(); Log.d(TAG, "[MyReceiver] onReceive - " + intent.getAction() + ", extras: " + printBundle(bundle)); if (JPushInterface.ACTION_REGISTRATION_ID.equals(intent.getAction())) { String regId = bundle.getString(JPushInterface.EXTRA_REGISTRATION_ID); Log.d(TAG, "[MyReceiver] 接收Registration Id : " + regId); //send the Registration Id to your server... } else if (JPushInterface.ACTION_MESSAGE_RECEIVED.equals(intent.getAction())) { Log.d(TAG, "[MyReceiver] 接收到推送下来的自定义消息: " + bundle.getString(JPushInterface.EXTRA_MESSAGE)); // processCustomMessage(context, bundle); } else if (JPushInterface.ACTION_NOTIFICATION_RECEIVED.equals(intent.getAction())) { Log.d(TAG, "[MyReceiver] 接收到推送下来的通知"); int notifactionId = bundle.getInt(JPushInterface.EXTRA_NOTIFICATION_ID); Log.d(TAG, "[MyReceiver] 接收到推送下来的通知的ID: " + notifactionId); } else if (JPushInterface.ACTION_NOTIFICATION_OPENED.equals(intent.getAction())) { Log.d(TAG, "[MyReceiver] 用户点击打开了通知"); //打开自定义的Activity Intent i = new Intent(context, MainActivity.class); i.putExtras(bundle); //i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP ); context.startActivity(i); } else if (JPushInterface.ACTION_RICHPUSH_CALLBACK.equals(intent.getAction())) { Log.d(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); Log.w(TAG, "[MyReceiver]" + intent.getAction() +" connected state change to "+connected); } else { Log.d(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 (bundle.getString(JPushInterface.EXTRA_EXTRA).isEmpty()) { Log.i(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) { Log.e(TAG, "Get message extra JSON error!"); } } else { sb.append("\nkey:" + key + ", value:" + bundle.getString(key)); } } return sb.toString(); } //send msg to MainActivity // private void processCustomMessage(Context context, Bundle bundle) { // if (MainActivity.isForeground) { // String message = bundle.getString(JPushInterface.EXTRA_MESSAGE); // String extras = bundle.getString(JPushInterface.EXTRA_EXTRA); // Intent msgIntent = new Intent(MainActivity.MESSAGE_RECEIVED_ACTION); // msgIntent.putExtra(MainActivity.KEY_MESSAGE, message); // if (!ExampleUtil.isEmpty(extras)) { // try { // JSONObject extraJson = new JSONObject(extras); // if (null != extraJson && extraJson.length() > 0) { // msgIntent.putExtra(MainActivity.KEY_EXTRAS, extras); // } // } catch (JSONException e) { // // } // // } // context.sendBroadcast(msgIntent); // } // } }
7、申请Appkey:在极光推送的官网申请到Appkey之后,修改之前在步骤1和步骤三中自己对应的Appkey
8、代码使用:此处只是简单实用推送,其次还可以设置设备标签Tag和设备别名Alias,通过标签和别名将推送群体细分化,做到相应的新闻推送到相应的群体,增加推送效率
//推送注册 JPushInterface.setDebugMode(true);JPushInterface.init(this);