android 用闹钟定时做http请求推送解决方案

  1. 设计思路
    如果在开发当中需要做push接入,而产品又要求不允许用第三方sdk(百度push,友盟push),而且又没有网络编程的经验,这个时候怎么办?这里就给大家分享下用http请求解决这个问题。
    大体的设计思路是,写一个service(为了保证长时间运行不被kill,就将其定义到另外的进程当中去),在这个service里面启动闹钟,每隔一段时间(这个时间可以自己定义)去请求服务器,如果有新的push消息,就通知给用户。
  2. 具体实现
    貌似很简单定义一个闹钟不断轮循请求服务器一句话,却在实际开发中要考虑很多问题,下面简单给大家列出来。
    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(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去拉取新的消息
没有写网络请求的部分,大家明白意思就行

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对象添加到这个集合里面去

ArrayList<IPushIntentAction> mPushActions;

也就是所有的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分享给大家。

/**
* --------------
* 欢迎转载 | 转载请注明
* --------------
* 如果对你有帮助,请点击|顶|
* --------------
* 请保持谦逊 | 你会走的更远
* --------------
* @author css
* @github https://github.com/songsongbrother
* @blog http://blog.csdn.net/xiangxi101
*/

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值