android延迟,Android延迟广播

Android广播阻塞、延迟问题

  最近项目中,多次碰到app研发人员反馈广播从发送到接收器接收,间隔时间太长,要求系统进行优化,特别是开机阶段。对此,专门阅读了一下广播从发送到接收这个流程的源码,以彻底搞明白怎样让自己发送的广播尽快到达接收器。

专注于为中小企业提供成都做网站、网站建设服务,电脑端+手机端+微信端的三站合一,更高效的管理,为中小企业南木林免费做网站提供优质的服务。我们立足成都,凝聚了一批互联网行业人才,有力地推动了成百上千企业的稳健成长,帮助中小企业通过网站建设实现规模扩充和转变。

涉及到的源码类不多,主要就是ActivityManagerService.java 和 BroadcastQueue.java。发送广播进程调用发送接口,通过IPC到达AMS,AMS根据Intent是否配置Intent.FLAG_RECEIVER_FOREGROUND,选择当前广播加入前台广播队列还是后台广播队列。根据当前广播是否有序,将广播加入广播队列的串行列表还是并行列表。广播队列和广播队列中的广播列表是影响广播接收时间的主要因素。

BroadcastQueue广播队列,负责将广播发送给广播接收器。AMS中有两个成员变量, 

BroadcastQueue mFgBroadcastQueue;//前台广播队列

BroadcastQueue mBgBroadcastQueue;//后台广播队列

前台广播队列和后台广播队列的区别有两处:1 超时时间,前台10s,后台60s. 2 是否延迟广播等待前一个广播进程完成。这两个区别已经说明前台广播对广播接收器要求更高,响应时间更短,如果广播要排队,时间上前台广播更短。同时系统默认使用后台广播队列,所以前台广播队列处理的广播要少,避免了可能的大量广播排队情况。

广播队列中的列表

//存放无序并发送给动态广播接收器的广播任务

final ArrayListBroadcastRecord mParallelBroadcasts = new ArrayListBroadcastRecord();

//存放无序发送给静态广播接收器的广播任务或者存放有序广播任务

final ArrayListBroadcastRecord mOrderedBroadcasts = new ArrayListBroadcastRecord();

mParallelBroadcasts 此列表中存放的是无序广播动态广播接收器任务,广播队列会在处理任务时通过嵌套循环,把每个广播通过ipc发送到关注它的所有进程。所有无序广播+动态广播接收器,广播不需要排队。这种情况是最快能让广播到达目标进程的方式。

mOrderedBroadcasts存放的广播任务特点:广播有序,或者广播接收器是静态注册的。此种类型的广播全部要在mOrderedBroadcasts中排队,广播之间按时间先后,同一个广播不同广播接收器按优先级。mOrderedBroadcasts存放的广播必须等一个广播任务处理完毕才能处理下一个,中间可能包含进程的启动等。

由此可见,广播最快的情况是前台广播、无序广播、动态注册广播接收器。最糟糕的情况是:后台广播、有序或静态注册广播接收器、广播接收器优先级低。如果一个应用只是简单的靠注册一个静态广播接收器拉起进程,对应的正是最糟糕的情况。如果又发生在开机阶段,自然延迟严重。

如果必须注册静态广播接收器,缩短时间的办法为:配置Intent.FLAG_RECEIVER_FOREGROUND,加入前台广播队列,设置广播优先级

源码:

广播发送:Context .sendBroadcast -ActivityManagerNative.broadcastIntent-ActivityManagerService.broadcastIntent-ActivityManagerService.broadcastIntentLocked.到此阶段,跟发送广播的进程通信结束。此阶段AMS完成的工作主要是根据Intent查找该广播对应的动态广播接收器、静态广播接收器、以此发送该广播使用的广播队列。

private final int broadcastIntentLocked(

......//权限检查

......//特殊系统广播进行必要处理

if (sticky) {//粘性广播处理

......

//查找静态注册的接收器

receivers = collectReceiverComponents(intent, resolvedType, users);

if (intent.getComponent() == null) {

// 查找动态广播接收器

        registeredReceivers = mReceiverResolver.queryIntent(intent,

                resolvedType, false, userId);

    }

//动态广播接收器

    int NR = registeredReceivers != null ? registeredReceivers.size() : 0;

    if (!ordered NR 0) { 

//确定队列

        final BroadcastQueue queue = broadcastQueueForIntent(intent);

//创建广播任务BroadcastRecord

        BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,

                callerPackage, callingPid, callingUid, resolvedType, requiredPermission,

                appOp, registeredReceivers, resultTo, resultCode, resultData, map,

                ordered, sticky, false, userId);

......

//广播任务加入并行列表中

            queue.enqueueParallelBroadcastLocked(r);

//启动异步发送广播任务

            queue.scheduleBroadcastsLocked();

registeredReceivers = null;

        NR = 0;

......

while (it NT ir NR) {

......

//根据优先级排序

      if (curt == null) {

                curt = (ResolveInfo)receivers.get(it);

            }

            if (curr == null) {

                curr = registeredReceivers.get(ir);

            }

            if (curr.getPriority() = curt.priority) {

                // Insert this broadcast record into the final list.

                receivers.add(it, curr);

//获取广播队列

        BroadcastQueue queue = broadcastQueueForIntent(intent);

//创建广播任务

        BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,

                callerPackage, callingPid, callingUid, resolvedType,

                requiredPermission, appOp, receivers, resultTo, resultCode,

                resultData, map, ordered, sticky, false, userId);

//加入到广播队列串行列表中

            queue.enqueueOrderedBroadcastLocked(r);

//启动异步发送任务

            queue.scheduleBroadcastsLocked();

广播队列处理广播:

final void processNextBroadcast(boolean fromMsg) {

......

//并行列表,遍历广播任务

        while (mParallelBroadcasts.size() 0) {

final int N = r.receivers.size();

//遍历接收器

            for (int i=0; iN; i++) {

//IPC调用发送给目标进程

deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);

}

}

//有串行广播任务正在执行

if (mPendingBroadcast != null) {

         //接收广播的目标进程正常

            if (!isDead) {

                // It's still alive, so keep waiting 继续等待目前进程反馈

                return;

            }

}

         //取出第一个广播

            r = mOrderedBroadcasts.get(0);//判断是否超时,

                if ((numReceivers 0)  

                        (now r.dispatchTime + (2*mTimeoutPeriod*numReceivers))) {

                     //广播超时

                      broadcastTimeoutLocked(false);//超时处理,终止当前广播,启动下一个任务。

                      }

if (r.receivers == null || r.nextReceiver = numReceivers

                    || r.resultAbort || forceReceive) {

             //所有广播任务执行完毕

}

int recIdx = r.nextReceiver++;//下一个广播接收器

r.dispatchTime = r.receiverTime;//设置派发时间

setBroadcastTimeoutLocked(timeoutTime);//启动超时计时

if (nextReceiver instanceof BroadcastFilter){//动态广播接收器

deliverToRegisteredReceiverLocked(r, filter, r.ordered);//发送

return;

}

.//静态广播

        ResolveInfo info =

            (ResolveInfo)nextReceiver;

......

//检查进程是否已启动

        ProcessRecord app = mService.getProcessRecordLocked(targetProcess,

                info.activityInfo.applicationInfo.uid, false);

        if (app != null app.thread != null) { /进程启动

           processCurBroadcastLocked(r, app);//发送静态广播

           return;

        }

 if ((r.curApp=mService.startProcessLocked(targetProcess,//启动进程

                info.activityInfo.applicationInfo, true,

                r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,

                "broadcast", r.curComponent,

                (r.intent.getFlags()Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false, false))

                        == null) {

                  //进程启动失败

              }

         //标志正在发送的串行广播

        mPendingBroadcast = r;

        mPendingBroadcastRecvIndex = recIdx;//正在发送的广播任务对应的接收器索引

}

android 开发中如何实现让程序执行一条语句后延时一段时间后再执行下面的语句?

延时操作,可以用下列方案:

方案1:线程阻断

try {

Thread.currentThread().sleep(2000);//阻断2秒

} catch (InterruptedException e) {

e.printStackTrace();

}

方案2:使用Handler的postDelayed延迟操作。

mHandler .postDelayed(mRunnable, 3000); // 在Handler中执行子线程并延迟3s。

private Runnable mRunnable = new Runnable() {

@Override

public void run() {

mHandler.sendEmptyMessage(1);

}

};

Handler mHandler = new Handler() {

@Override

public void handleMessage(Message msg) {

super.handleMessage(msg);

//3s后执行代码

}

}。

如何解决android消息通知推送延迟的问题?

这是安卓的缺陷。苹果因为系统封闭,所有推送由苹果自己负责统一推送,所以程序不需要后台,所有软件都能及时推送。而安卓也有谷歌统一推送,但是由于一些因素国内支持的很少,所以安卓很多软件如果要及时推送就必须锁定在后台,少数几个还好,如果需要推送的多了都锁定后台对性能续航都会有比较大影响。

所以目前大多采用第三方消息推送平台,例如极光,个推等


当前名称:android延迟,Android延迟广播
网站网址:http://scyanting.com/article/dsipphc.html