大体的设计思路是,写一个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分享给大家。
茶杯头甜蜜终章dlc 官方手机版v1.0.0.3
下载火柴人传说暗影格斗内置菜单 最新版v3.0.1
下载荒野乱斗测试服 安卓版v61.10.3
下载荒野乱斗彩虹服 安卓版v61.10.3
下载寒霜启示录 安卓版v1.25.10
寒霜启示录是一款生存模拟游戏,不少玩家可能对于末日都有着自己
末日城堡免广告版 安卓最新版v0.7.1
末日城堡免广告版是一款非常好玩的模拟经营类游戏,内部可以不看
甜蜜人生模拟器 最新版v1.4.5
甜蜜人生模拟器是一款非常好玩的模拟恋爱手游,玩家在这里能够对
武器锻造师内置功能菜单 v10.4
武器锻造师内置菜单版是游戏的破解版本,在该版本中为玩家提供了
开放空间overfield 安卓版v1.0.5
开放空间Overfield是一款箱庭养成经营手游,让你在广阔