推送的集成
常用概念
推送:从服务器实时向客户端发送消息app这是推送,可用于发送系统通知、推荐信息、聊天信息等。 别名:用来给移动设备取个好记的名字。比如电脑有电脑名,可以把别名理解为开发者给移动设备起的外号。但是多个移动设备可以有相同的别名,这些设备会同时收到发给别名的消息。 标记:用于标记移动设备可以理解为分类。例如,超市里的泰国大米不仅可以贴上粮食产品的标签,还可以贴上进口商品的标签。服务器可以统一向某种类型的移动设备发送信息;如果移动设备贴上设备手机号码的标签,服务器可以将该号码的手机单独发送信息。 自定义消息:推送的消息内容一般由sdk直接显示在系统的通知栏中,但有时我们希望控制显示通知的时间,如提前处理事务,或以对话框的形式显示信息等,此时,定制信息派上用场,app您可以先接收服务器发送的自定义信息,然后独立选择下一个处理逻辑。
集成步骤
推送sdk分为客户端和服务端两部分,开发者在客户端app集成客户端sdk,服务端必须在服务器程序上集成sdk。但是,推送客户端和服务端sdk不直接通信,必须通过推送厂家的推送服务器中转。以下是推送sdk集成时的数据流过程: 1.客户端集成sdk的app启动后,应首先进行初始化(注册)操作,即客户端sdk初始请求(包括推送服务器(推送制造商)appkey、master secret),推送服务器为移动设备分配了唯一的标志。 2、客户端sdk将别名和标记设置发送到推送服务器,并将推送服务器注册到移动设备上。 3、客户端sdk向推送服务器发送启动推送请求,推送服务器表示知道,如果有消息会告诉你。 4、服务端sdk包括封装信息推送请求,包括appkey、master secret、别名、标记、推送内容等信息。 5、服务端sdk向推送服务器发送消息推送请求,推送服务器首先校验appkey和master secret是否合法;通过验证,然后根据其他姓名和标记选择需要接收通知的客户端设备集合;最后,将推送内容推送到合格的客户端设备。
极光推送
极光推送是一种使用量大的推送sdk,支持ios、android、winphone等待平台。极光推送客户端sdk包为jpush-android-2.1.5.jar,服务端sdk包为jpush-client-3.2.9.jar,服务端的sdk还依赖于gson、slf4j、log4j等jar包。
推动调用接口
在APP上启用极光推送,使用JPushInterface类,下面是JPushInterface常用方法说明: init : 初始化MainApplication或者MainActivity中调用。 stopPush : 暂停接收通知。 resumePush : 恢复接收通知。 isPushStopped : 判断推送是否停止 getRegistrationID : 获取注册id。 setAliasAndTags : 设置设备的别名和标记。如果服务器指定将消息推送到手机号码,则app调用此方法将手机号码设置为别名或标记。 setAlias : 设置别名。 setTags : 设置标记。 clearAllNotifications : 清除所有通知。 setPushNotificationBuilder : 设置通知栏样式。类型为1,表示本样式,2表示自定义样式。 setPushTime : 设置接收通知的时间段。可设置周一到周日,每天的起始时间与结束时间。
广播推送事件
极光推送的所有事件都是通过广播发出的,不使用监听器,所以我们必须在那里app中自定义广播接收器处理事件。以下是极光推送的几个常见事件介绍: 1、JPushInterface.ACTION_REGISTRATION_ID 表示注册SDK对应事件intent-filter是<action android:name="cn.jpush.android.intent.REGISTRATION" /> 2、JPushInterface.ACTION_MESSAGE_RECEIVED 接收自定义信息的事件是相应的intent-filter是<action android:name="cn.jpush.android.intent.MESSAGE_RECEIVED" /> 3、JPushInterface.ACTION_NOTIFICATION_RECEIVED 表示接收通知的事件对应intent-filter是<action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED" /> 4、JPushInterface.ACTION_NOTIFICATION_OPENED 点击通知栏中的事件,对应intent-filter是<action android:name="cn.jpush.android.intent.NOTIFICATION_OPENED" /> 5、JPushInterface.ACTION_RICHPUSH_CALLBACK 表示收到富文本(如网页、多媒体等)回调的事件,对应intent-filter是<action android:name="cn.jpush.android.intent.ACTION_RICHPUSH_CALLBACK" /> 6、JPushInterface.ACTION_CONNECTION_CHANGE 表示网络连接变化(连接、断开)事件,对应intent-filter是<action android:name="cn.jpush.android.intent.CONNECTION" /> 下面是在AndroidManifest.xml注册极光广播接收器xml例子:
<receiver android:name=".JpushReceiver" android:exported="false" android:enabled="true"> <intent-filter> <action android:name="cn.jpush.android.intent.REGISTRATION" /> <action android:name="cn.jpush.android.intent.MESSAGE_RECEIVED" /> <action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED" /> <action android:name="cn.jpush.android.intent.NOTIFICATION_OPENED" /> <action android:name="cn.jpush.android.intent.ACTION_RICHPUSH_CALLBACK" /> <action android:name="cn.jpush.android.intent.CONNECTION" /> <category android:name="com.example.exmpushjpush" /> </intent-filter> </receiver>
发送服务器通知
APP代码实现了客户端接收和推送的功能。接下来,服务器必须配合,服务器程序发送推送信息,客户端app接收消息。 以下是服务器发送消息的具体步骤: 1、构造一个JPushClient对象包含以下信息:AppKey、Master Secret、重试次数、超时间等参数。 2.根据参数分别生成Platform平台对象、Audience受众对象、Notification通知对象、Message定制消息对象。 3.根据第二步生成的对象构建PushPayload对象。 4、调用JPushClient对象的sendPush方法,把PushPayload发送对象信息。 5、sendPush如果方法调用失败,则抛出异常,如果调用成功,则返回PushResult结果对象包含此次发送的消息号。 第三步PushPayload对象是整个发送过程的关键,对象的构建采用建造者模式PushPayload.Builder设置各参数,说明如下: setPlatform : 设置信息接收平台。主要有三种类型:Platform.ios()、Platform.android()、Platform.winphone()。 setAudience : 设置信息接收组。观众主要有三种,Audience.all()表示所有用户,Audience.alias(alias)指定别名的用户,Audience.tag(tag)用户表示指定标记。 setNotification : 设置通知内容。根据不同的平台,有三种设置方法:Notification.ios、Notification.android、Notification.winphone。 setMessage : 设置自定义信息。请注意,只有android和winphone可设置自定义消息,ios只能设置通知。 build : 根据设置内容构建PushPayload对象。 下面是服务器发送通知的代码示例:
import cn.jpush.api.JPushClient; import cn.jpush.api.common.ClientConfig; import cn.jpush.api.common.resp.APIConnectionException; import cn.jpush.api.common.resp.APIRequestException; import cn.jpush.api.push.PushResult; import cn.jpush.api.push.model.Message; import cn.jush.api.push.model.Platform; import cn.jpush.api.push.model.PushPayload; import cn.jpush.api.push.model.audience.Audience; import cn.jpush.api.push.model.notification.Notification; import java.util.Map; import java.util.Set; public class MessagePush { public static long IOS = 0L; public static long Android = 1L; private String mTitle; private String mMessage; private long mPlatformType; private JPushClient mJpushClient; private Platform mPlatform; private Audience mAudience; private Notification mNotify; private Message mMsg; public long mMsgId; public String mStatus; public String mErrCode; public String mErrMsg; public MessagePush(String appKey, String masterSecret, String message) { ClientConfig conf = ClientConfig.getInstance(); conf.setMaxRetryTimes(3); mJpushClient = new JPushClient(masterSecret, appKey, null, conf); mMessage = message; mTitle = ""; mPlatform = Platform.all(); mMsg = Message.content(message); mAudience = Audience.all(); setMsg(-1L, 0, 0, ""); } public MessagePush(String appKey, String masterSecret, String message, String title) { this(appKey, masterSecret, message); mTitle = title; } public MessagePush(String appKey, String masterSecret, String message, String title, Long platformType, Map<String, String> extras) { this(appKey, masterSecret, message, title); mPlatformType = platformType.longValue(); System.out.println("MessagePush platformType=" + platformType); if (platformType.longValue() == IOS) { mPlatform = Platform.ios(); mNotify = Notification.ios(mMessage, extras); } else if (platformType.longValue() == Android) { mPlatform = Platform.android(); mNotify = Notification.android(mMessage, mTitle, extras); } else { mPlatform = Platform.winphone(); mNotify = Notification.winphone(mMessage, extras); } } public void setAlias(Set<String> alias) { mAudience = Audience.alias(alias); } public void setTag(String[] tag) { mAudience = Audience.tag(tag); } public void sendPush() { PushPayload payload = build(); try { PushResult result = mJpushClient.sendPush(payload); mMsgId = result.msg_id; System.out.println("Got result - " + result); } catch (APIConnectionException e) { System.out.println("Connection error. Should retry later. " + e.getMessage()); setMsg(-1L, -1, -1, e.getMessage()); } catch (APIRequestException e) { System.out.println("HTTP Status: " + e.getStatus()); System.out.println("Error Code: " + e.getErrorCode()); System.out.println("Error Message: " + e.getErrorMessage()); System.out.println("Msg ID: " + e.getMsgId()); setMsg(e.getMsgId(), e.getStatus(), e.getErrorCode(), e.getErrorMessage()); } } private void setMsg(long msgId, int status, int errCode, String errMsg) { mMsgId = msgId; mStatus = String.valueOf(status); mErrCode = String.valueOf(errCode); mErrMsg = errMsg; } private PushPayload build() { System.out.println("build platformType=" + mPlatformType); PushPayload push; if (mPlatformType == IOS) { push = PushPayload.newBuilder().setPlatform(mPlatform) .setAudience(mAudience).setNotification(mNotify) .build(); } else if (mPlatformType == Android) { push = PushPayload.newBuilder().setPlatform(mPlatform) .setAudience(mAudience).setMessage(mMsg).build(); //.setAudience(mAudience).setNotification(mNotify).build(); } else { push = PushPayload.newBuilder().setPlatform(mPlatform) .setAudience(mAudience).setMessage(mMsg).build(); } return push; } }
个推
个推是另一个使用较多的推送sdk,它支持ios和android,但不支持winphone,不过服务器除了java,还支持PHP、Python、C++、C#等等。个推的客户端sdk包为GetuiSDK2.8.1.0.jar和GetuiExt-2.0.3.jar,服务端sdk包为gexin-rp-sdk-base-4.0.0.7.jar、gexin-rp-sdk-http-4.0.1.2.jar和gexin-rp-sdk-template-4.0.0.4.jar,服务端的sdk还依赖于commons、jackson、protobuf等jar包。
推送调用的接口
在APP上启用个推,用到的是PushManager类,下面是PushManager的常用方法说明: getInstance : 获得PushManager的单例。 initialize : 初始化。 turnOnPush : 开启推送。 turnOffPush : 关闭推送。 isPushTurnedOn : 判断推送是否开启。 getClientid : 获取客户端id。 setTag : 设置标签。 bindAlias : 绑定别名。 unBindAlias : 解绑别名。 setSilentTime : 设置静默时间段。即从几点到几点不接收通知。
推送事件的广播
个推也使用广播来发送事件,不过不像极光那样细分了许多事件,也需要自定义广播接收器。下面是个推几个常用的事件介绍: 事件类型根据bundle.getInt(PushConsts.CMD_ACTION)来区分 1、PushConsts.GET_CLIENTID : 获得客户端id。其实就是注册,相当于极光的JPushInterface.ACTION_REGISTRATION_ID 2、PushConsts.GET_MSG_DATA : 收到自定义消息。相当于极光的JPushInterface.ACTION_MESSAGE_RECEIVED 下面是在AndroidManifest.xml注册个推广播接收器的xml例子:
<receiver android:name=".GexinReceiver" android:exported="false" > <intent-filter> <action android:name="com.igexin.sdk.action.应用分配的AppID值" /> </intent-filter> </receiver>
服务器发送通知
下面是服务器发送消息的具体步骤: 1、构造IGtPush对象,该对象包含以下信息:个推服务器地址、AppKey、Master Secret。 2、按照参数分别生成Template模板对象、AppConditions条件对象、AppID队列等等。 3、根据第二步产生的各对象,构建AppMessage对象。 4、调用IGtPush对象的pushMessageToApp方法,把AppMessage对象信息发送出去。 5、pushMessageToApp方法调用失败则抛出异常,调用成功则返回IPushResult结果对象,里面包含本次发送的结果信息。 上面步骤三的AppMessage对象是整个发送过程的关键,该对象的常用方法说明如下: setAppIdList : 设置AppID队列。即往绑定哪些AppID的用户发送消息。 setConditions : 设置条件信息。包括手机类型、区域、标签等等。 setData : 设置模板数据。模板Template定义了消息的具体样式,下面是个推包装好的几个常用模板: --NotificationTemplate : 通知模板。自动在通知栏里显示消息,点击后跳到app首页。该模板相当于极光的Notification。 --TransmissionTemplate : 透传模板。不会自动展示通知栏,由开发者在广播接收器的PushConsts.GET_MSG_DATA分支中自行处理。该模板相当于极光的Message。 --LinkTemplate : 链接模板。自动在通知栏里显示消息,点击后跳转到指定URL。 --NotyPopLoadTemplate : 下载提示模板。自动在通知栏里显示消息,点击后下载指定安装包。 下面是服务器发送通知的代码示例:
import java.util.ArrayList; import java.util.List; import com.gexin.rp.sdk.base.IPushResult; import com.gexin.rp.sdk.base.impl.AppMessage; import com.gexin.rp.sdk.base.uitls.AppConditions; import com.gexin.rp.sdk.http.IGtPush; import com.gexin.rp.sdk.template.NotificationTemplate; public class PushtoAppNotify { //采用"Java SDK 快速入门", "第二步 获取访问凭证 "中获得的应用配置,用户可以自行替换 private static String appId = "FJ9uNM6WkS8laiS3C05W9"; private static String appKey = "cpV7gRK6IlAo26aDZGMtI1"; private static String masterSecret = "QSvOwGnx0E9jEMpiXtqJ39"; static String host = "http://sdk.open.api.igexin.com/apiex.htm"; public static void main(String[] args) throws Exception { IGtPush push = new IGtPush(host, appKey, masterSecret); NotificationTemplate template = NotificationTemplateDemo(); AppMessage message = new AppMessage(); message.setData(template); message.setOffline(true); //离线有效时间,单位为毫秒,可选 message.setOfflineExpireTime(24 * 1000 * 3600); //推送给App的目标用户需要满足的条件 AppConditions cdt = new AppConditions(); List<String> appIdList = new ArrayList<String>(); appIdList.add(appId); message.setAppIdList(appIdList); //手机类型 List<String> phoneTypeList = new ArrayList<String>(); //省份 List<String> provinceList = new ArrayList<String>(); //自定义tag List<String> tagList = new ArrayList<String>(); cdt.addCondition(AppConditions.PHONE_TYPE, phoneTypeList); cdt.addCondition(AppConditions.REGION, provinceList); cdt.addCondition(AppConditions.TAG,tagList); message.setConditions(cdt); IPushResult ret = push.pushMessageToApp(message,"任务别名_toApp"); System.out.println(ret.getResponse().toString()); } public static NotificationTemplate NotificationTemplateDemo() throws Exception { NotificationTemplate template = new NotificationTemplate(); template.setAppId(appId); template.setAppkey(appKey); template.setTitle("PushtoAppNotify标题"); template.setText("PushtoAppNotify内容"); template.setLogo("icon.png"); template.setLogoUrl(""); template.setIsRing(true); template.setIsVibrate(true); template.setIsClearable(true); // 透传消息设置,1为强制启动应用,客户端接收到消息后就会立即启动应用;2为等待应用启动 template.setTransmissionType(1); template.setTransmissionContent("PushtoAppNotify请输入您要透传的内容"); return template; } public static class NotificationTemplateDemo { public static NotificationTemplate notificationTemplateDemo(String appId, String appkey) { NotificationTemplate template = new NotificationTemplate(); // 设置APPID与APPKEY template.setAppId(appId); template.setAppkey(appkey); // 设置通知栏标题与内容 template.setTitle("请输入通知栏标题"); template.setText("请输入通知栏内容"); // 配置通知栏图标 template.setLogo("icon.png"); // 配置通知栏网络图标 template.setLogoUrl(""); // 设置通知是否响铃,震动,或者可清除 template.setIsRing(true); template.setIsVibrate(true); template.setIsClearable(true); // 透传消息设置,1为强制启动应用,客户端接收到消息后就会立即启动应用;2为等待应用启动 template.setTransmissionType(1); template.setTransmissionContent("请输入您要透传的内容"); // 设置定时展示时间 // template.setDuration("2015-01-16 11:40:00", "2015-01-16 12:24:00"); return template; } } }