• Android开发笔记消息推送SDK


    推送的集成

    常用概念

    推送:从服务器把消息实时发到客户端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.jpush.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;
        	}
        	
        }
    
    }
  • 相关阅读:
    面试的一些问题关于k8s中,镜像自动化脚本
    无中微子双贝塔衰变
    Python基础入门篇【35】--面向对象实例:重构学生信息库
    计算机组成原理期末复习(二)
    Three.js使用InstancedMesh实现性能优化
    mysql面试题16:说说分库与分表的设计?常用的分库分表中间件有哪些?分库分表可能遇到的问题有哪些?
    瑞吉外卖 —— 13、项目优化:YApi、Swagger、项目部署
    idea如何设置jvm大小
    【考研数学】概率论与数理统计 —— 第三章 | 二维随机变量及其分布(3,二维随机变量函数的分布)
    必看!换了流量卡,原来的手机卡你就这么操作,绝对完美!
  • 原文地址:https://blog.csdn.net/cqn2bd2b/article/details/125556737