Android—push方案总结

简述push的实现方案并讲解厂商push需要注意的case

Posted by Nela on August 28, 2018

Android—push总结

本文简介

前文介绍了push的具体集成方式,本文介绍push的实现原理和方案,针对长链接方案,了解一种push实现的思路,并介绍sdk层如何将push和业务模块相互结合。

push原理

  1. 长链接

    长链接是为了 数据传输和推送。保证客户端和服务端一直处于通信状态。

    一种是app层的长链接,由apk自己维护,需要做进程保活断线重连等等。

    一种是系统级长链接,该进程由系统维护,例如小米手机,则维护了小米推送的长链接。

    系统级别的长链接,收到push消息后有两种选择,一种是交给notifiaction处理,一种是下发至app处理,也就是透传和非透传。所以透传消息的到达率是低于非透传消息的。因为透传消息走的也是app级别的通道。

    小米推送华为推送等如果在其对应的手机上走的都是系统及长链接。而像个推,极光推送等走的都是app级别的长链接。在三方推送中,其提供的通知和透传消息走的都是app级通道。

  2. SMS信令推送

    服务器有新消息时,发送1条类似短信的信令给客户端,客户端通过拦截信令,解析消息内容 / 向服务器获取信息 此种方案基本可以理解为付费通道。

  3. 轮询

    定时拉取服务器消息。

    心跳和轮询的区别,心跳是建立在已经有的链接上,轮训需要经历一次tcp+断开,3次握手4次挥手

长链接的实现

BIO和NIO

传统的实现一个长链接的方式是BIO.也就是阻塞式,更合理的实现方式为NIO.

BIO模型分析:

传统阻塞线程io,需要创建线程,线程的创建和销毁成本很高,在Linux这样的操作系统中,线程本质上就是一个进程。创建和销毁都是重量级的系统函数。

线程本身占用较大内存,像Java的线程栈,一般至少分配512K~1M的空间,如果系统中的线程数过千,恐怕整个JVM的内存都会被吃掉一半。

线程的切换成本是很高的。操作系统发生线程切换的时候,需要保留线程的上下文,然后执行系统调用。如果线程数过高,可能执行线程切换的时间甚至会大于线程执行的时间,这时候带来的表现往往是系统load偏高、CPU sy使用率特别高(超过20%以上),导致系统几乎陷入不可用的状态。

NIO:

NIO同步非阻塞,BIO里用户最关心“我要读”,NIO里用户最关心”我可以读了”,在AIO模型里用户更需要关注的是“读完了”。

NIO一个重要的特点是:socket主要的读、写、注册和接收函数,在等待就绪阶段都是非阻塞的,真正的I/O操作是同步阻塞的(消耗CPU但性能非常高)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
  interface ChannelHandler{
      void channelReadable(Channel channel);
      void channelWritable(Channel channel);
   }
   class Channel{
     Socket socket;
     Event event;//读,写或者连接
   }

   //IO线程主循环:
   class IoThread extends Thread{
   public void run(){
   Channel channel;
   while(channel=Selector.select()){//选择就绪的事件和对应的连接
      if(channel.event==accept){
         registerNewChannelHandler(channel);//如果是新连接,则注册一个新的读写处理器
      }
      if(channel.event==write){
         getChannelHandler(channel).channelWritable(channel);//如果可以写,则执行写事件
      }
      if(channel.event==read){
          getChannelHandler(channel).channelReadable(channel);//如果可以读,则执行读事件
      }
    }
   }
   Map<ChannelChannelHandler> handlerMap;//所有channel的对应事件处理器
  }

NIO等方案,实现起来比较复杂。可以使用框架MINA等第三方框架实现长连接。该框架实现了心跳包,断线重连的基础逻辑。

进程保活

完成长链接后重要的问题就是进程保活。由于不是系统级的进程,因此非常容易被杀死。

通常的手段为:监听广播,应用间广播互相拉起

service 进程后台进程 优先级位为 4 变为前台进程则为2

sdk集成Push

我司集成push,主要采用的方式为集成三方厂商的长链接和普通app接入三方推送并无差异。 流程如下: ->业务服务器 推送模版+token->推送服务器 ->三方长链接服务器 上行注册

客户端->业务服务器->推送服务器->三方长链接服务器 判断是否注册 发送下行消息/上行消息

由业务服务器决定,push是否发起,当push消息需要发送时,先发送给推送服务器,推送服务器根据之前约定好的payload ,替换占位符,在发送给三方推送服务器。最终下发至客户端,走系统长连接。

系统级push集成

系统级push集成的注意事项

华为push

需要签名文件生成的sh256key 填写到华为平台

1
2
3
4
5
6
7
    private static OnConnectionFailedListener sConnectionFailedListener = new OnConnectionFailedListener() {
        @Override
        public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
            Log.d("Failedresult",connectionResult.getErrorCode()+":");
        }
    };

可通过上述接口获取token失败的原因,如6003则为服务未注册到华为平台。

小米push

需要:

1
2
3
4
    private static final String MIPUSH_APP_ID
    private static final String MIPUSH_APP_KEY 
    packagename 
    

小米和华为的透传类型

  • 小米透传: though 0
  • 小米非透传: through 1
  • 华为透传 “type”: 3
  • 华为非透传 “type”: 1

和华为push一样小米push 的如果能收到通知栏消息,那么透传消息是会收到的,需要在小米安全中设置应用自启动权限,华为则是手机管家。

fcm

需要注意服务器端使用的协议 旧协议通知消息:

1
2
3
4
5
6
7
8
9
{
    "notification" : {
      "body" : "You have a new message",
      "title" : "",
      "icon" : "myicon" // Here you can put your app icon name
    },
    "to" : "token..."
}

旧协议透传消息:

1
2
3
4
5
6
7
{
    "data" : {
      "Nick" : "Obito",
      "xxx" : "xxx"
    },
    "to" : "token..."
}

注意 如果原本使用旧协议,结果是用新协议组装payload那么是会收到透传类型的消息,但是没有任何消息内容。

延伸翻墙原理

翻墙用到的是ShadowSocks,简单的说就是,中国大陆所有的请求都被墙代理,所以导致某些关键字过滤。

解决方案是,通过海外服务器,通过ssh端口转发的方式,讲目标内容通过海外服务器再次转发回来。因为内容是通过加密通道,所以无法过滤。

但是本地发起请求时,可能会被识别。最终shadowSockS提供了解决方案,本地创建ss-client,海外ss-service,本地请求通过ss-client,进行socket5一顿操作,最终走上述流程。

所以可以设置代理使某些访问不翻墙,绕过局域网:pac 一般在软件中有选项。

详细内容参考如下文章 https://www.jianshu.com/p/44c7b9aab614

参考文章

https://tech.meituan.com/nio.html

https://www.jianshu.com/p/b61a49e0279f

https://blog.csdn.net/woorh/article/details/9854779

https://blog.csdn.net/carson_ho/article/details/79522975 https://blog.csdn.net/MCshidi/article/details/51590297