android即时消息处理机制
一、唤醒机制
am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, (triggerAtTime + time), pi);2、闹铃时间优化
public class AlarmTime { public static final AtomicLong alarmTime=new AtomicLong(0); /** * 初始化闹铃时间,重连或者收到消息初始化一下 */ public static long initAlarmTime(){ alarmTime.set(Global.ALARM_TRIGGER_TIME); return alarmTime.get(); } /** * 优化闹铃时间,重连错误数超过一定次数,优化闹铃时间再尝试重连到错误数 * 10分钟,30秒、30秒、;;;;到达错误数,10分钟 ;;;;; * @return */ public static long optimizeAlarmTime(){ alarmTime.set(Global.ALARM_TRIGGER_OPTIMIZE_TIME);//10分钟 return alarmTime.get(); } public static long incrementTime(){ long time =alarmTime.get(); if(time==0) return alarmTime.addAndGet(Global.ALARM_TRIGGER_TIME);//默认30秒开始 else if(time<Global.ALARM_TRIGGER_MAX_TIME)//25分钟 return alarmTime.addAndGet(Global.ALARM_TRIGGER_TIME_INCREMENT);//每次递增5秒 else return time; } }3、唤醒机制
public final class IMWakeLock { private static final String TAG = IMWakeLock.class.getSimpleName(); private WakeLock wakeLock = null; private String tag=""; private PowerManager pm; public IMWakeLock(Context paramContext,String tag){ this.tag =tag; pm= ((PowerManager) paramContext. getSystemService(Context.POWER_SERVICE)); wakeLock = pm.newWakeLock( PowerManager.PARTIAL_WAKE_LOCK , tag); } /** * 获取电源锁,保持该服务在屏幕熄灭时仍然获取CPU时,保持运行 */ public synchronized void acquireWakeLock() { if(!pm.isScreenOn()) { if (null != wakeLock&&!wakeLock.isHeld()) { ImLog.d(TAG, tag+"@@===>获取唤醒休眠锁"); wakeLock.acquire(); } } } /** * 释放设备电源锁 */ public synchronized void releaseWakeLock() { if (null != wakeLock && wakeLock.isHeld()) { ImLog.d(TAG, tag+"@@===>释放唤醒休眠锁"); wakeLock.release(); } } public synchronized void finalize(){ if (null != wakeLock && wakeLock.isHeld()) { ImLog.d(TAG, tag+"@@===>释放唤醒休眠锁"); wakeLock.release(); } wakeLock = null; } public boolean isScreenOn(){ return pm.isScreenOn(); } }4、唤醒时机
private void startApNotify(){ if(this.sessionID==0||this.ticket==null) return; if(wakeLock.isScreenOn()){ ImLog.d(TAG, "NotifyService@@===>启动空请求"); apNotifyThread=new ApNotifyThread(this,false); }else{ wakeLock.acquireWakeLock(); apNotifyThread=new ApNotifyThread(this,true); } exec=Executors.newSingleThreadExecutor(); exec.execute(apNotifyThread); exec.shutdown(); }
二、消息收取
public class ApNotifyThread extends Thread{ private static final String TAG = ApNotifyThread.class.getSimpleName(); protected volatile boolean isRunning=false; protected volatile APHold.Client client; protected volatile VRVTHttpClient thc; protected volatile TProtocol protocol; protected volatile long sessionID; protected volatile String ticket; protected final long ERRORNUM=15; protected NotifyService service; protected boolean isOld=false; protected boolean isDoShortRequest=false; public ApNotifyThread(NotifyService service,boolean isDoShortRequest){ this.sessionID=service.getSessionID(); this.ticket=service.getTicket(); this.service=service; this.isDoShortRequest=isDoShortRequest; } @Override public void run(){ ImLog.d(TAG, "ApNotifyThread@@===>空请求开始处理 threadID="+Thread.currentThread().getId()); this.isRunning=true; if(this.isDoShortRequest){ if(shortEmptyRequest()&&this.isRunning) longEmptyRequest(); //再开启长空请求 }else{ longEmptyRequest(); } ImLog.d(TAG, "ApNotifyThread@@===>"+(this.isOld?"上一个":"")+"空请求终止 threadID="+Thread.currentThread().getId()); this.isRunning=false; } /** * 初始化 * @param isLongTimeOut * @throws Exception */ private void init(boolean isLongTimeOut) throws Exception{ thc= NotifyHttpClientUtil.getVRVTHttpClient(isLongTimeOut); protocol = new TBinaryProtocol(thc); } /** * 长空请求 */ private void longEmptyRequest(){ try{ this.init(true); client= new APHold.Client(protocol); for (;;) { if(!NetStatusUtil.havActiveNet(IMApp.getApp())){ ImLog.d(TAG, "longEmptyRequest@@===>无可用网络"); break; } try { if(!handleMessage()) break; } catch (TException e) { if(!this.isRunning) break; ImLog.d(TAG, "longEmptyRequest@@===>发请求异常:"+ e.getMessage()); if(exceptionHandler(e)){ throw new IMException("连接失败次数过多",MessageCode.IM_EXCEPTION_CONNECT); } continue; } } ImLog.d(TAG, "longEmptyRequest@@===>"+(this.isOld?"上一个":"")+"空请求正常退出"); } catch (Exception e) { ImLog.d(TAG, "longEmptyRequest@@===>"+(this.isOld?"上一个":"")+"空请求异常退出"+e.getMessage()); if (exceptionHandler(e)) { // 调用重连 ImLog.d(TAG, "longEmptyRequest@@===>调用重连"); this.service.getDataSyncer().setValue(UserProfile.RECONNECT, "0"); } }finally{ close(); } } /** * 短空请求 * @return */ private boolean shortEmptyRequest(){ boolean isDoLongRequest=true; try{ long messageNum=0; if(!NetStatusUtil.havActiveNet(IMApp.getApp())){ ImLog.d(TAG, "shortEmptyRequest@@===>无可用网络"); return false; } this.init(false); //获取消息数 APService.Client apclient = new APService.Client(protocol); this.service.getDataSyncer().setValue(UserProfile.LASTREQUESTTIME, String.valueOf(SystemClock.elapsedRealtime())); ImLog.d(TAG, "shortEmptyRequest@@===>notifyID:"+NotifyID.notifyID.get()); messageNum= apclient.getNotifyMsgSize(sessionID, ticket, NotifyID.notifyID.get()); NotifyError.notifyErrorNum.set(0); ImLog.d(TAG, "shortEmptyRequest@@===>获取消息条数:"+messageNum); if(messageNum==-1) throw new IMException("session 失效",MessageCode.IM_BIZTIPS_SESSIONINVAILD); //如果有消息接收消息 if(messageNum>0&&this.isRunning){ long receiveMessageNum=0; client= new APHold.Client(protocol); for (;;) { if(!NetStatusUtil.havActiveNet(IMApp.getApp())){ ImLog.d(TAG, "shortEmptyRequest@@===>无可用网络"); break; } if(!handleMessage()) break; receiveMessageNum++; if(receiveMessageNum==messageNum) //短连接接收完后退出 break; } } ImLog.d(TAG, "shortEmptyRequest@@===>"+(this.isOld?"上一个":"")+"空请求正常退出"); }catch(Exception e){ ImLog.d(TAG, "shortEmptyRequest@@===>"+(this.isOld?"上一个":"")+"空请求异常退出"+e.getMessage()); if(exceptionHandler(e)){ isDoLongRequest=false; //调用重连 ImLog.d(TAG, "shortEmptyRequest@@===>调用重连"); this.service.getDataSyncer().setValue(UserProfile.RECONNECT, "0"); } } finally{ close(); this.service.releaseWakeLock(); } return isDoLongRequest; } /** * 异常处理 判断是否重连 * @param e * @return */ private boolean exceptionHandler(Exception e){ boolean isReconnect=false; if ( e instanceof IMException) { isReconnect=true; }else if (!(e instanceof SocketTimeoutException)&&!(e instanceof NoHttpResponseException)) { NotifyError.notifyErrorNum.incrementAndGet(); if(NotifyError.notifyErrorNum.get()>this.ERRORNUM){ isReconnect=true; NotifyError.notifyErrorNum.set(0); } }else NotifyError.notifyErrorNum.set(0); e.printStackTrace(); return isReconnect; } /** * 空请求发送和接收数据处理 * @throws TException */ private boolean handleMessage() throws TException{ if(!this.isRunning) return false; ImLog.d(TAG, "handleMessage@@===>sessionID "+sessionID); SendEmptyRequestReq req = new SendEmptyRequestReq(); req.setSessionID(sessionID); req.setTicket(ticket); req.setNotifyID(NotifyID.notifyID.get()); ImLog.d(TAG, "handleMessage@@===>一次空请求周期开始 "); this.service.getDataSyncer().setValue(UserProfile.LASTREQUESTTIME, String.valueOf(SystemClock.elapsedRealtime())); client.SendEmptyRequest(req); NotifyError.notifyErrorNum.set(0); if(!this.isRunning) return false; APNotifyImpl iface = new APNotifyImpl(); APNotify.Processor<Iface> processor = new APNotify.Processor<Iface>(iface); boolean isStop = false; while (!isStop) { try { ImLog.d(TAG, "handleMessage@@===>进入接收数据处理"); while (processor.process(protocol, protocol) == true) { isStop = true; break; } ImLog.d(TAG, "handleMessage@@===>结束接收数据处理"); } catch (TException e) { ImLog.d(TAG, "handleMessage@@===>接收数据处理异常"); isStop = true; } } ImLog.d(TAG, "handleMessage@@===>一次空请求周期结束"); if(!iface.isSessionVaild){//后台报session 失效 this.service.setSessionID(0); this.service.setTicket(null); return false; } //重设闹铃 this.service.getDataSyncer().setValue(UserProfile.ALARM_TTIME, "0"); return true; } /** * 关闭连接 */ private void close() { synchronized(this){ if (thc != null) { thc.shutdown(); thc.close(); thc=null; } } if (client != null && client.getInputProtocol() != null) { client.getInputProtocol().getTransport().close(); client.getOutputProtocol().getTransport().close(); } } /** * 线程中断 */ public void interrupt() { this.isRunning=false; this.isOld=true; close(); super.interrupt(); } /** * 判断是否在运行状态 */ public boolean isRunning(){ return isRunning; }
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。