大体的设计思路是,写一个service(为了保证长时间运行不被kill,就将其定义到另外的进程当中去),在这个service里面启动闹钟,每隔一段时间(这个时间可以自己定义)去请求服务器,如果有新的push消息,就通知给用户。
具体实现
貌似很简单定义一个闹钟不断轮循请求服务器一句话,却在实际开发中要考虑很多问题,下面简单给大家列出来。
1)闹钟时间校准
2)每天push只能在固定的或者某个定义的时间内推送
3)push类型的扩展,新添加一种类型的push
什么都不说,类图直接贴上
大概分为三级结构
第一级:MoboPushAlarmManager,主要工作是管理闹钟,初始化闹钟,对闹钟时间进行校准,取消闹钟。
第二级:MobogeniePushServiceNew,主要工作是对闹钟设置的pendingintent的动作(startservice)进行处理。
第三级:MoboPushNotifyHelper,主要工作是实例化notification对象,发送出通知,并且取消通知。MoboMessageSelector,主要工作是从n多个push中根据时间选择出可用的push。MoboPushRequest,主要是请求服务器,从服务器列表中获取push队列。
其余的PushActionCreator,MoboPushMessage等等都属于第三级或者第一第二级的工具类了。
开始来贴代码了(具体的源码还没抽出来,过段时间再贴上)
MoboPushAlarmManager来初始化闹钟,当闹钟响了就会发送一个intent给MobogeniePushServiceNew
public void initPullAlarm(Context context, boolean boot) { Bundle bundle = new Bundle(); bundle.putInt(START_SERVICE_TYPE, TYPE_REQUEST); PendingIntent pendingIntent = getPendingIntent(context, bundle, REQ_PULL); //循环时间 long repeat_time = HOUR_MILLIS * 2; Log.i(TAG, "repeat_time is " + repeat_time); // 计算下一次执行时间 long triggerAtMillis = boot ? 10000 : 0; Log.i(TAG, "initPullAlarm,and next pull time is after: " + triggerAtMillis); // 这个行为会覆盖之前的Alarm,主要根据PendingIntent来辨别不同的闹钟 getAlarmManager(context).setRepeating(AlarmManager.RTC, System.currentTimeMillis() + triggerAtMillis, repeat_time, pendingIntent); }
MobogeniePushServiceNew接收到闹钟之后,就会解析intent,并且进行相应的操作(请求网络,发送通知)
@Override public void onStart(Intent intent, int startId) { super.onStart(intent, startId); LogUtil.p("pushservice onStart"); if (intent == null) { LogUtil.d("mobopush", "intent == null)"); return; } // 解析打开service的意图 parsePushServiceIntent(intent); } private void parsePushServiceIntent(Intent intent) { Log.i(TAG, "parsePushServiceIntent"); if (intent == null) { return; } Bundle bundle = intent.getExtras(); if (bundle == null) { // 不明渠道调起service,默认处理为准备获取新消息,重设闹钟 PushAlarmManager.getInstance().initPullAlarm(this, false); return; } int type = bundle.getInt(PushAlarmManager.START_SERVICE_TYPE); if (type == PushAlarmManager.TYPE_STARTSERVICE) { //判断闹钟是否过期,如果过期则重设 } else if (type == PushAlarmManager.TYPE_REQUEST) { // 预设的网络请求 mREQ_RESULT = REQ_RESULT.ING; MoboPushRequest.getInstance().pullPushMessages(this, this, MoboPushRequest.REQUEST_NORMAL); } } //请求网络回调的数据处理 @Override public void onMessageLoaded(int actionCode, int requestCode, MessageResponse response) { //将网络请求回来的结果利用MessageSelector选择器,选择出有用的消息 getMessageSelector().assignMessageFromNet(MobogeniePushServiceNew.this, new MessageGetListener() { @Override public void showMessages(Listmsgs) { if (msgs.size() > 0) { for (MoboPushMessage msg : msgs) { notifyMessageAndDelete(msg, false); } } } @Override public void prepareMessages(List msgs) { if (msgs == null || msgs.size() == 0) { return; } MoboPushMessageDBUtils.insertBatch(MobogeniePushServiceNew.this, msgs); initShowMessageAlarm(msgs); } }, response.messages); }
MoboPushRequest去拉取新的消息
没有写网络请求的部分,大家明白意思就行
public void pullPushMessages(Context context, final IMessageGetListener l, final int requestCode) { boolean pushFlag = true; if (!pushFlag) { return; } final Context appcontext = context.getApplicationContext(); //这里进行http请求,得到json数据 String json = ""; if (!TextUtils.isEmpty(json)) { JSONObject jsonObj = null; String str = null; try { jsonObj = new JSONObject(json); if (jsonObj.optInt("code") == 100) { int interval = jsonObj.optInt("interval"); MessageResponse response = new MessageResponse(); response.interval = interval * 1000; JSONArray jsonArray = jsonObj.optJSONArray("list"); if (jsonArray == null || jsonArray.length() == 0) { } int aLength = jsonArray.length(); response.initMessageArray(aLength); response.resCode = 100; for (int i = 0; i < aLength; i++) { JSONObject jsonInArray = jsonArray.getJSONObject(i); str = jsonInArray.toString(); MoboPushMessage pushMessage = new MoboPushMessage(); pushMessage.parseJson(str); response.messages[i] = pushMessage; if (pushMessage != null ) { } } } else { } } catch (JSONException e) { } } Object object=null; int actionCode=0; if (l == null) { return; } if (actionCode==0 && object != null && object instanceof MessageResponse) { MessageResponse response = (MessageResponse) object; l.onMessageLoaded(actionCode, requestCode, response); } else { l.onMessageLoaded(actionCode, requestCode, null); } }
剩下的就是处理具体的push消息了
private void notifyMessageAndDelete(MoboPushMessage message, boolean delete) { if (message == null) { return; } //传入message对象发送通知 getMoboPushNotifyHelper().showNotification(message); }
我们只有message对象怎样利用这个message对象去发送不同类型的push呢,为了很好的扩展,直接上代码
public void showNotification(MoboPushMessage message) { final Intent targetIntent = obtainNotificationClick(message, false); setNotification(message, targetIntent); } public void setNotification(final MoboPushMessage message, final Intent intent) { //根据MoboPushMessage和Intent来show通知 }
重点就在这句话了,怎样根据message检测出需要的push呢
final Intent targetIntent = obtainNotificationClick(message, false);
我们可以看见getTargetIntent(mContext, message)这个方法主要作用
public Intent obtainNotificationClick(MoboPushMessage message, boolean flag) { if (message == null) { return null; } PushActionCreator actionCreator = new PushActionCreator(); return actionCreator.getTargetIntent(mContext, message); }
核心在这里
public Intent getTargetIntent(Context c,MoboPushMessage pushMessage){ if(pushMessage==null) { return null; } int type = pushMessage.type; Intent resultIntent = null; for(IPushIntentAction action:mPushActions){ if(action.isTypeForAction(type)){ try{ resultIntent = action.createTargetIntent(c,pushMessage); }catch(Exception e){ } break; } } return resultIntent; }
将不同类型的push对象添加到这个集合里面去
ArrayListmPushActions;
也就是所有的push数据都要实现这个公共的接口
public interface IPushIntentAction { public Intent createTargetIntent(Context context,MoboPushMessage message); public int getActionKey(); public boolean isTypeForAction(int type); public String getNextPage(); }
其中createTargetIntent这个根据不同的类型new出各自的intent,isTypeForAction比对类型
举个例子大家就知道了。
public class PushActionDefault implements IPushIntentAction { @Override public Intent createTargetIntent(Context c, MoboPushMessage message) { Intent intent = new Intent(); intent.setAction("android.intent.action.MAIN"); intent.addCategory("android.intent.category.LAUNCHER"); return intent; } @Override public int getActionKey() { return MoboPushMessage.TYPE_OPEN_APP; } @Override public String getNextPage() { return null; } @Override public boolean isTypeForAction(int type) { return false; } }
基本上把一条线给贯穿了,其中
1)闹钟时间校准
解决方法可以自由的写在初始化闹钟里面,如果发现时间有错误,可以再初始化一下闹钟,这样就可以覆盖以前的闹钟
2)每天push只能在固定的或者某个定义的时间内推送
我们在MoboMessageSelector选择器里面专门对时间进行了筛选
3)push类型的扩展,新添加一种类型的push
我们要添加新的类型的push的时候,只需要实现IPushIntentAction 这个接口,然后在将对象添加到ArrayList mPushActions这个集合里面,供选择就OK了
最近比较忙,之后一定把整理好的demo分享给大家。
热血大作战 安卓最新版v2.1.166
下载凡尔赛法环免广告版 最新版v1.69.1
下载天煞异种 安卓版v1.0.21
下载十三月 (Undecember)最新官方中文版v3.26.0200
下载星露谷物语sve 安卓版v1.5.6.52
星露谷物语sve手机版是游戏的超大拓展Mod内容,全称Sta
动物园大亨 手机版v2.0
动物园大亨是一款模拟动物园经营的休闲放置游戏,采用了卡通画风
蜜蜂园林钞票不减反增版 v0.1.68
蜜蜂园林无限道具版是游戏的破解版本,在该版本中为玩家提供了足
幻想熔炉失落帝国的世界 安卓版v2.16.2
幻想熔炉失落帝国的世界是一款魔法卡通风格的城市模拟经营类游戏
我的女友是声优免广告 安卓版v1
我的女友是声优免广告是一款非常好玩的模拟经营类手游,玩家在游