当前位置:首页 » 安卓系统 » android动态广播

android动态广播

发布时间: 2023-02-12 17:05:17

‘壹’ Android开发中怎么把广播中处理后的信息传递给Activity

1.发送广播
Intent intent = new Intent(BroadcastAction);
Bundle bundle = new Bundle();
bundle.putString("***", SUCCESS);
bundle.putString("FullPathName", mFullPathName);
intent.putExtras(bundle);
sendBroadcast(intent);
2.在Activity中创建一个内部类MyBroadcastReceiver扩展BroadcastReceiver,并在其中实现onReceive方法。
3.在Activity中声明一个MyBroadcastReceiver类型的成员变量,并注册:
private MyBroadcastReceiver myBroadcastReceiver;
...
myBroadcastReceiver = new MyBroadcastReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(BroadcastAction);
registerReceiver(receiver, filter);
4.使用完后要记得释放
unregisterReceiver(receiver);

注:1和2中的 BroadcastAction要是同一个Action

‘贰’ Android 动态广播 和 静态广播的区别

同一优先级的广播接收器,动态的要比静态注册的早。 动态注册:即由代码注册的广播接收器静态注册:即在 AndroidManifest.xml 中注册的广播接收器 优先级: 当广播为有序发送的时候,要按这个排序并顺序发送。 sendBroadcast 发送的是无序广播。sendOrderedBroadcast 发送的是有序广播。 好了,现在寻找问题原因,在找原因前肯定有这样的想法,一个有序队列,既然允许有相同的优先级存在,那么在同优先级内要不然有排序子因素,要不基就是按照某种操作可能影响顺序。后者可能性很大。 打开源码,顺着 动态注册广播接受器 找,最后是 ActivityManagerService.java 这个文件找到了 registerReceiver 的实现。同地也看到,存储的广播接收器列表是 HashMap mRegisteredReceivers 这个变理。 里面有一段代码为: ReceiverList rl = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder()); if (rl == null) { rl = new ReceiverList(this, callerApp, Binder.getCallingPid(), Binder.getCallingUid(), receiver); if (rl.app != null) { rl.app.receivers.add(rl); } else { try { receiver.asBinder().linkToDeath(rl, 0); } catch (RemoteException e) { return sticky; } rl.linkedToDeath = true; } mRegisteredReceivers.put(receiver.asBinder(), rl); } 在里面查找有没有这个 Receiver , 如果没有 put 进去。 看到这里貌似没有对广播的顺序做处理。是不是有别的地方做排序呢,找找成员变理,发现一个可疑的变量:final ArrayList mOrderedBroadcasts没错,感觉就应该是它了。 找找对它的操作,只有一处 mOrderedBroadcasts.set ,把代码摘录一下: BroadcastRecord r = new BroadcastRecord(intent, callerApp, callerPackage, callingPid, callingUid, requiredPermission, sticky, false); mOrderedBroadcasts.set(i, r);在这里放入了一个 BroadcastRecord 对像,而这个对像中主要的东西其实是 receivers向上跟踪 int NT = receivers != null ? receivers.size() : 0; int it = 0; ResolveInfo curt = null; BroadcastFilter curr = null; 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); ir++; curr = null; it++; NT++; } else { // Skip to the next ResolveInfo in the final list. it++; curt = null; } } 发现了一段 对 receivers 排序的代码,并且判断也是 priority 的值,用的是 >= 方式 感觉的找到了地方,但是对 Activity Manager Service 这个模块却更加的不懂了,以后有机会一定要分析一下这块是怎样设计的,才能确定本文的问题所在。暂时记录,以后分析!

‘叁’ 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 ArrayList<BroadcastRecord> mParallelBroadcasts = new ArrayList<BroadcastRecord>();

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

final ArrayList<BroadcastRecord> mOrderedBroadcasts = new ArrayList<BroadcastRecord>();

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.(r);

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

                queue.scheleBroadcastsLocked();

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.scheleBroadcastsLocked();

广播队列处理广播:

final void processNextBroadcast(boolean fromMsg) {

......

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

            while (mParallelBroadcasts.size() > 0) {

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

//遍历接收器

                for (int i=0; i<N; i++) {

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

(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){//动态广播接收器

(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动态注册锁屏、解锁、开屏系统广播

先自定义一个广播类

然后在Application中进行动态注册

因为是动态注册所以无需在AndroidManifest.xml中进行注册

‘伍’ 22 AndroidBroadcast广播机制

广播(Broadcast)机制用于进程/线程间通信,广播分为广播发送和广播接收两个过程,其中广播接收者BroadcastReceiver便是Android四大组件之一。

BroadcastReceiver分为两类:

从广播发送方式可分为三类:

广播在系统中以BroadcastRecord对象来记录, 该对象有几个时间相关的成员变量.

广播注册,对于应用开发来说,往往是在Activity/Service中调用 registerReceiver() 方法,而Activity或Service都间接继承于Context抽象类,真正干活是交给ContextImpl类。另外调用getOuterContext()可获取最外层的调用者Activity或Service。

[ContextImpl.java]

其中broadcastPermission拥有广播的权限控制,scheler用于指定接收到广播时onRecive执行线程,当scheler=null则默认代表在主线程中执行,这也是最常见的用法

[ContextImpl.java]

ActivityManagerNative.getDefault()返回的是ActivityManagerProxy对象,简称AMP.
该方法中参数有mMainThread.getApplicationThread()返回的是ApplicationThread,这是Binder的Bn端,用于system_server进程与该进程的通信。

[-> LoadedApk.java]

不妨令 以BroadcastReceiver(广播接收者)为key,LoadedApk.ReceiverDispatcher(分发者)为value的ArrayMap 记为 A 。此处 mReceivers 是一个以 Context 为key,以 A 为value的ArrayMap。对于ReceiverDispatcher(广播分发者),当不存在时则创建一个。

此处mActivityThread便是前面传递过来的当前主线程的Handler.

ReceiverDispatcher(广播分发者)有一个内部类 InnerReceiver ,该类继承于 IIntentReceiver.Stub 。显然,这是一个Binder服务端,广播分发者通过rd.getIIntentReceiver()可获取该Binder服务端对象 InnerReceiver ,用于Binder IPC通信。

[-> ActivityManagerNative.java]

这里有两个Binder服务端对象 caller 和 receiver ,都代表执行注册广播动作所在的进程. AMP通过Binder驱动将这些信息发送给system_server进程中的AMS对象,接下来进入AMS.registerReceiver。

[-> ActivityManagerService.java]

其中 mRegisteredReceivers 记录着所有已注册的广播,以receiver IBinder为key, ReceiverList为value为HashMap。

在BroadcastQueue中有两个广播队列mParallelBroadcasts,mOrderedBroadcasts,数据类型都为ArrayList<broadcastrecord style="box-sizing: border-box;">:</broadcastrecord>

mLruProcesses数据类型为 ArrayList<ProcessRecord> ,而ProcessRecord对象有一个IApplicationThread字段,根据该字段查找出满足条件的ProcessRecord对象。

该方法用于匹配发起的Intent数据是否匹配成功,匹配项共有4项action, type, data, category,任何一项匹配不成功都会失败。

broadcastQueueForIntent(Intent intent)通过判断intent.getFlags()是否包含FLAG_RECEIVER_FOREGROUND 来决定是前台或后台广播,进而返回相应的广播队列mFgBroadcastQueue或者mBgBroadcastQueue。

注册广播:

另外,当注册的是Sticky广播:

广播注册完, 另一个操作便是在广播发送过程.

发送广播是在Activity或Service中调用 sendBroadcast() 方法,而Activity或Service都间接继承于Context抽象类,真正干活是交给ContextImpl类。

[ContextImpl.java]

[-> ActivityManagerNative.java]

[-> ActivityManagerService.java]

broadcastIntent()方法有两个布尔参数serialized和sticky来共同决定是普通广播,有序广播,还是Sticky广播,参数如下:

broadcastIntentLocked方法比较长,这里划分为8个部分来分别说明。

这个过程最重要的工作是:

BroadcastReceiver还有其他flag,位于Intent.java常量:

主要功能:

这个过主要处于系统相关的10类广播,这里不就展开讲解了.

这个过程主要是将sticky广播增加到list,并放入mStickyBroadcasts里面。

其他说明:

AMS.collectReceiverComponents

广播队列中有一个成员变量 mParallelBroadcasts ,类型为ArrayList<broadcastrecord style="box-sizing: border-box;">,记录着所有的并行广播。</broadcastrecord>

动态注册的registeredReceivers,全部合并都receivers,再统一按串行方式处理。

广播队列中有一个成员变量 mOrderedBroadcasts ,类型为ArrayList<broadcastrecord style="box-sizing: border-box;">,记录着所有的有序广播。</broadcastrecord>

发送广播过程:

处理方式:

可见不管哪种广播方式,都是通过broadcastQueueForIntent()来根据intent的flag来判断前台队列或者后台队列,然后再调用对应广播队列的scheleBroadcastsLocked方法来处理广播;

在发送广播过程中会执行 scheleBroadcastsLocked 方法来处理相关的广播

[-> BroadcastQueue.java]

在BroadcastQueue对象创建时,mHandler=new BroadcastHandler(handler.getLooper());那么此处交由mHandler的handleMessage来处理:

由此可见BroadcastHandler采用的是”ActivityManager”线程的Looper

[-> BroadcastQueue.java]

此处mService为AMS,整个流程还是比较长的,全程持有AMS锁,所以广播效率低的情况下,直接会严重影响这个手机的性能与流畅度,这里应该考虑细化同步锁的粒度。

‘陆’ android 注册的静态广播和动态广播的区别

1.动态注册广播不是常驻型广播,也就是说广播跟随activity的生命周期。注意: 在activity结束前,移除广播接收器。
静态注册是常驻型,也就是说当应用程序关闭后,如果有信息广播来,程序也会被系统调用自动运行。
它的生命周期为从回调onReceive()方法开始到该方法返回结果后结束。
2.当广播为有序广播时:
1 优先级高的先接收
2 同优先级的广播接收器,动态优先于静态
3 同优先级的同类广播接收器,静态:先扫描的优先于后扫描的,动态:先注册的优先于后注册的。

‘柒’ Android BroadcastReceiver详解

BroadcastReceiver(广播接收器)是Android四大组件之一,顾名思义,通过广播的方式进行消息传递,其本质是一个全局的监听器,可以监听到各种广播,可以用来实现不同组件之间的通信。广播最大的特点就是发送方并不关心接收方是否接到数据,也不关心接收方是如何处理数据的,通过这样的形式来达到接、收双方的完全解耦合。

又称无序广播,这种广播完全是异步的,所有与广播Intent匹配的BroadcastReceiver,都可以收到这条广播,并且不分先后顺序,视为同时收到,通过Context.sendBroadcast()方法发送。这种广播的效率比较高,但缺点是接收器不能将处理结果传递给下一个接收器,并且无法在中途终止广播。

这是一种同步执行的广播,通过Context.sendOrderedBroadcast()方法发送,这种广播发出后,通过receiver的intent-filter中的android:priority属性来设置优先级,优先级从-1000~1000,数越大,优先级越高,使用setResult()方法把结果传递给下一个接收者,通过getResult()方法获取上一个接收者传递过来的结果,并可以通过abortBroadcast()方法丢弃该广播,使该广播不再传递给下一个接收者。

粘性广播通过Context.sendStickBroadcast()方法来发送,用此方法发送的广播会一直滞留,当有匹配此广播的接收器被注册后,该广播接收器就会收到此广播。使用此广播时,需要获得BROADCAST_STICKY权限。(在 android 5.0/api 21后不再推荐使用)

Android系统中内置了多个系统广播,只要涉及到手机的基本操作,基本上都会发出相应的系统广播。如:开启启动,网络状态改变,拍照,屏幕关闭与开启,点亮不足等等。每个系统广播都具有特定的intent-filter,其中主要包括具体的action,系统广播发出后,将被相应的BroadcastReceiver接收。系统广播在系统内部当特定事件发生时,有系统自动发出。

以上广播都属于全局广播,发出去的广播,只要有匹配的接收者,就可以收到广播。这样一来会造成一些问题,一是消耗性能,二是容易引起安全性的问题,为了能够简单的解决这方面的问题,Android引入了一套广播本地广播机制,使用该机制发出的广播只能够在本应用内部进行传递,并且广播接收器也只能接收来自本应用发出的广播。

使用方法
1.注册本地广播接收器

2.发送本地广播

3.注销本地广播接收器

本文用到的BroadcastReceiver

Android 8.0(API级别26)取消大部分静态注册广播,建议使用动态广播
https://developer.android.google.cn/about/versions/oreo/android-8.0

‘捌’ Android动态广播(Android8.0)

   (a).动态注册             在UI中注册的广播,例如:

  (b).静态注册             

   需要在manifest中进行注册(在安卓8.0后系统废除了大部分静态广播,最好使用动态注册)。

 (a).系统广播             

   系统中已经定义的广播,此类广播只能由系统发出,并且需要在intent-filter中加上系统已经写的action。             

  (b).自定义广播         

    顾名思义,是用户自己定义的广播。

 (a)我们首先需要一个广播接收类                                     

(b)其次注册动态广播

(c)最后需要通过send方法发送一个广播供广播接收者接受

另外还有有序广播和无序广播,这篇博客写的比较详细,供大家参考: Android的有序广播和无序广播(解决安卓8.0版本之后有序广播的接收问题) - ming3 - 博客园 (cnblogs.com)

‘玖’ 说说Android的广播(1)

对于Activity的启动流程,我们已经有了几个版本的分析了。这里我们分析一个更容易一些的,四大组件中最简单的Broadcast Receiver。

关于Broadcast,有几点需要了解。首先是广播的类型,然后是广播的发送方法,最后是广播是如何被接收的。这三者相辅相承的,比如普通广播和有序广播只有在详细了解了广播的接收过程了之后,才能真正明白它的含义。

普通的广播是不在意顺序的,最简单的理解是同时可以收到这个广播。如果应用是动态注册这个广播的,且广播发送时这个进程还活着,那么当然可以并发的把广播尽快地传送出去是最好的。
但是,如果是通过AndroidManifest.xml静态注册的情况,也就是说这个广播首先要把一个进程启动起来,这时并发启动很多进程就是个问题了。Android目前的做法是,对这种静态的广播接收者,自动按有序广播的方式来串行处理。但是这对应用是透明的,应用不能假设系统已经把静态的无序广播当成有序广播来处理。

这个时候讲粘性广播有福了,因为从Android 5.0(API 21)开始,因为安全性的问题,官方已经正式废弃了粘性广播。

Context类提供两个方法可以用于发送普通广播:

差别是第二个设置权限。

发给特定的用户:

有序广播因为要处理消息的处理结果,所以要复杂一些。

如果只是想让广播可以按优先级来收取,并不在意处理的结果,可以用下面的版本:

同样,在多用户环境下,也可以选择给哪个用户发广播:

不管是普通的还是有序的广播都对应有粘性的版本:

以上的API都是定义于Context类中: https://developer.android.com/reference/android/content/Context.html

首先我们先看看发送端是如何发送的。
我们首先先放一个大图,让大家先有一个直观的印象,不管普通广播、有序广播、粘性广播如何组合,最终都汇集到一个大方法中。

我们先看应用发送普通广播的一个简单的例子:

非常简单,调用ContentWrapper的sendBroadcast方法就可以了。
然后我们顺藤摸瓜就好了。
Activity中的sendBroadcast,实际上调用的是:

我们来看frameworks/base/core/java/android/content/ContextWrapper.java中对sendBroadcast的定义:

ContextWrapper只是一个包装,真正的实现在ContextImpl中

我们来看/frameworks/base/core/java/android/app/ContextImpl.java中真正实现sendBroadcast的功能:

它会通过IPC去调用AMS的broadcastIntent。由于我们这个普通的广播的方法参数最少,所以好多都是传null。

加锁,定参数,然后调用真正的逻辑的实现。

我们先把broadcastIntentLocked的真正逻辑放一下,先看看有序广播是如何发送的。

ContextWrapper.sendOrderedBroadcast

Context是abstract方法,调用的是ContextWrapper的实现:

跟普通广播一样,还是会调用到ContextImpl.sendOrderedBroadcast

有序广播调用broadcastIntent的区别在于serialized参数,普通广播为false,有序广播为true.

原型为:

前面讲过带有回调的版本,我们看看它是如何实现的:

当然还是调用ContextImpl.sendOrderedBroadcast

这次变成只是一个封装了,它会调用一个更多参数的版本:

这次是一个全参数调用broadcastIntent的版本了,除了sticky就齐了

我们也不绕圈子了,直接看ContextImpl.sendStickyBroadcast.

‘拾’ Android 中如何在server 中动态注册广播。

在Service中的onStartCommand中动态注册广播。
如下代码:
@Override
public int onStartCommand(Intent intent, int flags, int startId) {

IntentFilter filter = new IntentFilter(Intent.ACTION_TIME_TICK); //注册IntentFilter
filter.setPriority(Integer.MAX_VALUE); //设置级别
receiver = new AppReceiver();//本地服务
registerReceiver(receiver, filter);//注册广播

return START_STICKY;
}

广播代码:
package com.sevencolorbox.sdk.service;

import java.util.List;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public class AppReceiver extends BroadcastReceiver{

private boolean isServiceRunning = false;
private String serviceName = "com.sevencolorbox.sdk.service.SevenColorService";
@Override
public void onReceive(Context context, Intent intent) {

if (intent.getAction().equals(Intent.ACTION_TIME_TICK)){

ActivityManager am = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningServiceInfo> infos = am.getRunningServices(Integer.MAX_VALUE);

for (RunningServiceInfo info : infos) {

if (info.service.getClassName().equals(serviceName)) {

isServiceRunning = true;
}
}
if (!isServiceRunning) {

Log.i("ss", "本地服务未开启");
Intent tIntent = new Intent(context,SevenColorService.class);
context.startService(tIntent);
}
}
}
}

热点内容
如何玩cf端游越南服务器 发布:2025-05-17 08:38:54 浏览:183
噪声的危害和控制设计脚本 发布:2025-05-17 08:22:29 浏览:473
esr算法 发布:2025-05-17 08:16:09 浏览:194
安卓手机怎么用拟我表情 发布:2025-05-17 08:10:13 浏览:918
给U盘安装kalilinux 发布:2025-05-17 08:07:26 浏览:249
sql提示存储过程 发布:2025-05-17 07:35:58 浏览:743
qq里的互动访问 发布:2025-05-17 07:26:53 浏览:665
口语易账号密码发送到哪里 发布:2025-05-17 07:26:52 浏览:62
核桃编程幼儿 发布:2025-05-17 07:26:50 浏览:787
2台服务器集群搭建 发布:2025-05-17 07:18:57 浏览:185