小米推送(MiPush)是小米公司向开发者提供的消息推送服务,总的流程如官方文档所示:
由图可知,推送是双向的:
1.推送是可以由app的后台端发起,应用服务器的后台会先将消息传给小米的消息云服务器(MiPush Server),然后MIPush云服务器再把消息送达到app客户端。
2.推送是可以由app客户端发起,app Client先将消息发送到MiPush Server,经MiPush Server中转把消息再推到后台。
推送其实底层本质上还是socket通讯。一般Android开发过程中,即时通讯都会自己引socketIo写socket的方式来做,但可能因为种种原因,比如通讯太频繁,socket的长连接太久导致出现了消息送达率偏低不理想(传丢了的情况多到难以忍受),socket接收端响应太慢的问题(根本说还是送达的慢),用推送来实现就是最理想的选择,国内Android其他的三方消息推送都是跟小米推送相似的推送业务逻辑,像极光推送,小米推送都是很好的开发选择标的,但是小米推送最大的好处是对MIUI系统的设备有得天独厚的支持,如果设备的系统是MIUI,那么推送的长连接是由MIUI系统来维持的,而在非MIUI系统,维护小米推送服务的长连接Service的任务就交给app来办了,系统级的维护和app维护这种常规操作来比较,不必多言。在MIUI上不管需要推送的Client数量再多,消息的送达率,传达的速度都是优于其他的推送。
小米推送的消息总共有两种:透传消息和通知栏消息,对于他们俩的介绍和区别官网说的已经很好了,下为原文摘录:
基本上实际开发很少应用原生的通知栏消息,都是自己绘制通知栏界面布局,后台发送透传消息,app端在透传的广播接受器拿到消息json后反序列化,然后弹出自己的自定义通知栏。
关于集成小米推送,小米给的sdk Demo已经很简单了,稍微看看就能轻易的嵌入到自己的项目中,一言以蔽之:DemoMessageReceiver一个嵌进项目就妥了,在项目中注册小米推送服务和接收服务的广播都由它来接收。注册操作成功后会得到regId,这个是设备标识用来发给服务器后台为下一步通讯用的,当消息送达的广播被捕获到后,就能在广播接收器的相应回调取写逻辑了,网上已经有很详细的教程:https://www.jianshu.com/p/b1134bebc2d4。下面只列出收到透传消息后弹出通知栏的核心代码:
//方法用来接收服务器向客户端发送的透传消息
@Override
public void onReceivePassThroughMessage(Context context, MiPushMessage message) {
if (!TextUtils.isEmpty(message.getTopic())) {
mTopic = message.getTopic();
} else if (!TextUtils.isEmpty(message.getAlias())) {
mAlias = message.getAlias();
}
bean = gson.fromJson(message.getContent(), EventInfoBean.class);
showNotification(App.getInst(),bean);
RxBus.getDefault().post(100, ""); //100 重新渲染界面
}
//自定义的弹窗消息
private void showNotification(Context context,EventInfoBean bean) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
String content = "";
if (bean.getYjType() == 1) {
content = bean.getDeviceName() + "有一个" + bean.getEventTypeName() + bean.getEventStatusName() + ",点击查看";
} else {
content = bean.getDeviceName() + "报警已解除点击查看";
}
builder.setAutoCancel(true);//点击后消失
builder.setSmallIcon(R.mipmap.ic_launcher);//设置通知栏消息标题的头像
builder.setDefaults(NotificationCompat.DEFAULT_ALL);//设置通知铃声
builder.setTicker(content);
builder.setContentText(content);//通知内容
builder.setContentTitle(bean.getEventTypeName());
builder.setPriority(Notification.PRIORITY_MAX);
//利用PendingIntent来包装我们的intent对象,使其延迟跳转
if (bean.gettClass() != null){
Intent intent = new Intent(context, bean.gettClass());//将要跳转的界面
intent.putExtra("bean",bean);
PendingIntent intentPend = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
builder.setContentIntent(intentPend);
}
NotificationManager manager = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);
manager.notify(0, builder.build());
}