android用鬧鐘定時(shí)做http請求推送的解決方案
設(shè)計(jì)思路
如果在開發(fā)當(dāng)中需要做push接入,而產(chǎn)品又要求不允許用第三方sdk(百度push,友盟push),而且又沒有網(wǎng)絡(luò)編程的經(jīng)驗(yàn),這個(gè)時(shí)候怎么辦?這里就給大家分享下用http請求解決這個(gè)問題。
大體的設(shè)計(jì)思路是,寫一個(gè)service(為了保證長時(shí)間運(yùn)行不被kill,就將其定義到另外的進(jìn)程當(dāng)中去),在這個(gè)service里面啟動(dòng)鬧鐘,每隔一段時(shí)間(這個(gè)時(shí)間可以自己定義)去請求服務(wù)器,如果有新的push消息,就通知給用戶。
具體實(shí)現(xiàn)
貌似很簡單定義一個(gè)鬧鐘不斷輪循請求服務(wù)器一句話,卻在實(shí)際開發(fā)中要考慮很多問題,下面簡單給大家列出來。
1)鬧鐘時(shí)間校準(zhǔn)
2)每天push只能在固定的或者某個(gè)定義的時(shí)間內(nèi)推送
3)push類型的擴(kuò)展,新添加一種類型的push
什么都不說,類圖直接貼上

大概分為三級(jí)結(jié)構(gòu)
第一級(jí):MoboPushAlarmManager,主要工作是管理鬧鐘,初始化鬧鐘,對鬧鐘時(shí)間進(jìn)行校準(zhǔn),取消鬧鐘。
第二級(jí):MobogeniePushServiceNew,主要工作是對鬧鐘設(shè)置的pendingintent的動(dòng)作(startservice)進(jìn)行處理。
第三級(jí):MoboPushNotifyHelper,主要工作是實(shí)例化notification對象,發(fā)送出通知,并且取消通知。MoboMessageSelector,主要工作是從n多個(gè)push中根據(jù)時(shí)間選擇出可用的push。MoboPushRequest,主要是請求服務(wù)器,從服務(wù)器列表中獲取push隊(duì)列。
其余的PushActionCreator,MoboPushMessage等等都屬于第三級(jí)或者第一第二級(jí)的工具類了。
開始來貼代碼了(具體的源碼還沒抽出來,過段時(shí)間再貼上)
MoboPushAlarmManager來初始化鬧鐘,當(dāng)鬧鐘響了就會(huì)發(fā)送一個(gè)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);
//循環(huán)時(shí)間
long repeat_time = HOUR_MILLIS * 2;
Log.i(TAG, "repeat_time is " + repeat_time);
// 計(jì)算下一次執(zhí)行時(shí)間
long triggerAtMillis = boot ? 10000 : 0;
Log.i(TAG, "initPullAlarm,and next pull time is after: " + triggerAtMillis);
// 這個(gè)行為會(huì)覆蓋之前的Alarm,主要根據(jù)PendingIntent來辨別不同的鬧鐘
getAlarmManager(context).setRepeating(AlarmManager.RTC, System.currentTimeMillis() + triggerAtMillis, repeat_time, pendingIntent);
}
MobogeniePushServiceNew接收到鬧鐘之后,就會(huì)解析intent,并且進(jìn)行相應(yīng)的操作(請求網(wǎng)絡(luò),發(fā)送通知)
@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) {
// 不明渠道調(diào)起service,默認(rèn)處理為準(zhǔn)備獲取新消息,重設(shè)鬧鐘
PushAlarmManager.getInstance().initPullAlarm(this, false);
return;
}
int type = bundle.getInt(PushAlarmManager.START_SERVICE_TYPE);
if (type == PushAlarmManager.TYPE_STARTSERVICE) {
//判斷鬧鐘是否過期,如果過期則重設(shè)
} else if (type == PushAlarmManager.TYPE_REQUEST) {
// 預(yù)設(shè)的網(wǎng)絡(luò)請求
mREQ_RESULT = REQ_RESULT.ING;
MoboPushRequest.getInstance().pullPushMessages(this, this, MoboPushRequest.REQUEST_NORMAL);
}
}
//請求網(wǎng)絡(luò)回調(diào)的數(shù)據(jù)處理
@Override
public void onMessageLoaded(int actionCode, int requestCode, MessageResponse response) {
//將網(wǎng)絡(luò)請求回來的結(jié)果利用MessageSelector選擇器,選擇出有用的消息 getMessageSelector().assignMessageFromNet(MobogeniePushServiceNew.this, new MessageGetListener() {
@Override
public void showMessages(List<MoboPushMessage> msgs) {
if (msgs.size() > 0) {
for (MoboPushMessage msg : msgs) {
notifyMessageAndDelete(msg, false);
}
}
}
@Override
public void prepareMessages(List<MoboPushMessage> msgs) {
if (msgs == null || msgs.size() == 0) {
return;
}
MoboPushMessageDBUtils.insertBatch(MobogeniePushServiceNew.this, msgs);
initShowMessageAlarm(msgs);
}
}, response.messages);
}
MoboPushRequest去拉取新的消息
沒有寫網(wǎng)絡(luò)請求的部分,大家明白意思就行
public void pullPushMessages(Context context, final IMessageGetListener l, final int requestCode) {
boolean pushFlag = true;
if (!pushFlag) {
return;
}
final Context appcontext = context.getApplicationContext();
//這里進(jìn)行http請求,得到j(luò)son數(shù)據(jù)
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對象發(fā)送通知 getMoboPushNotifyHelper().showNotification(message);
}
我們只有message對象怎樣利用這個(gè)message對象去發(fā)送不同類型的push呢,為了很好的擴(kuò)展,直接上代碼
public void showNotification(MoboPushMessage message) {
final Intent targetIntent = obtainNotificationClick(message, false);
setNotification(message, targetIntent);
}
public void setNotification(final MoboPushMessage message, final Intent intent) {
//根據(jù)MoboPushMessage和Intent來show通知
}
重點(diǎn)就在這句話了,怎樣根據(jù)message檢測出需要的push呢
final Intent targetIntent = obtainNotificationClick(message, false);
我們可以看見getTargetIntent(mContext, message)這個(gè)方法主要作用
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對象添加到這個(gè)集合里面去
ArrayList<IPushIntentAction> mPushActions;
也就是所有的push數(shù)據(jù)都要實(shí)現(xiàn)這個(gè)公共的接口
public interface IPushIntentAction {
public Intent createTargetIntent(Context context,MoboPushMessage message);
public int getActionKey();
public boolean isTypeForAction(int type);
public String getNextPage();
}
其中createTargetIntent這個(gè)根據(jù)不同的類型new出各自的intent,isTypeForAction比對類型
舉個(gè)例子大家就知道了。
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)鬧鐘時(shí)間校準(zhǔn)
解決方法可以自由的寫在初始化鬧鐘里面,如果發(fā)現(xiàn)時(shí)間有錯(cuò)誤,可以再初始化一下鬧鐘,這樣就可以覆蓋以前的鬧鐘
2)每天push只能在固定的或者某個(gè)定義的時(shí)間內(nèi)推送
我們在MoboMessageSelector選擇器里面專門對時(shí)間進(jìn)行了篩選
3)push類型的擴(kuò)展,新添加一種類型的push
我們要添加新的類型的push的時(shí)候,只需要實(shí)現(xiàn)IPushIntentAction 這個(gè)接口,然后在將對象添加到ArrayList mPushActions這個(gè)集合里面,供選擇就OK了
最近比較忙,之后一定把整理好的demo分享給大家。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- android實(shí)現(xiàn)定時(shí)拍照并發(fā)送微博功能
- android實(shí)現(xiàn)定時(shí)拍照功能
- Android使用自定義view在指定時(shí)間內(nèi)勻速畫一條直線的實(shí)例代碼
- Android使用Handler實(shí)現(xiàn)定時(shí)器與倒計(jì)時(shí)器功能
- Android定時(shí)器和倒計(jì)時(shí)實(shí)現(xiàn)淘寶秒殺功能
- Android CountDownTimer實(shí)現(xiàn)定時(shí)器和倒計(jì)時(shí)效果
- android service實(shí)現(xiàn)循環(huán)定時(shí)提醒功能
- Android鬧鐘機(jī)制實(shí)現(xiàn)定時(shí)任務(wù)功能
- Android編程實(shí)現(xiàn)popupwindow定時(shí)消失的方法
- Android中AlarmManager+Notification實(shí)現(xiàn)定時(shí)通知提醒功能
- 詳解Android實(shí)現(xiàn)定時(shí)器的幾種方法
- Android定時(shí)開機(jī)的流程詳解
相關(guān)文章
Android 兩個(gè)ViewPager的聯(lián)動(dòng)效果的實(shí)現(xiàn)
這篇文章主要介紹了Android 兩個(gè)ViewPager的聯(lián)動(dòng)效果的實(shí)現(xiàn),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-08-08
Android中SwipeBack實(shí)現(xiàn)右滑返回效果
這篇文章主要介紹了Android中SwipeBack實(shí)現(xiàn)右滑返回效果的相關(guān)資料,需要的朋友可以參考下2016-02-02
Flutter實(shí)現(xiàn)密碼強(qiáng)度校驗(yàn)結(jié)果的示例詳解
我們經(jīng)常在一些網(wǎng)站上看到這樣的密碼強(qiáng)度指示,使用三段線,分別用不同的顏色來表示弱密碼、中等強(qiáng)度密碼和強(qiáng)密碼,本篇我們就用?Flutter?來實(shí)現(xiàn)這樣一個(gè)密碼強(qiáng)度校驗(yàn)示例,希望對大家有所幫助2023-08-08
RecyclerView設(shè)置間距和添加分割線的方法
在使用RecyclerView布局,經(jīng)常需要調(diào)整間距和添加分割線以達(dá)到更美觀效果,這篇文章主要介紹了RecyclerView設(shè)置間距和添加分割線的方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-09-09
Android Studio實(shí)現(xiàn)QQ的注冊登錄和好友列表跳轉(zhuǎn)
最近做了一個(gè)項(xiàng)目,這篇文章主要介紹了Android Studio界面跳轉(zhuǎn),本次項(xiàng)目主要包含了注冊、登錄和好友列表三個(gè)界面以及之間相互跳轉(zhuǎn),感興趣的可以了解一下2021-05-05

