欧美网址在线观看-亚洲最新毛片-国产成人免费爽爽爽视频-亚洲一区在线影院-日韩欧美在线观看视频网站-男女激情四射-成人一区二区免费看-欧美亚洲综合在线-日韩一级视频在线播放-国产成人三级视频在线播放-亚洲中文字幕日产无码2020-99久久久国产精品免费无卡顿-av在线观看地址-果冻传媒mv免费播放在线观看-欧美在线观看视频免费-日韩天天操

聯(lián)系我們 - 廣告服務(wù) - 聯(lián)系電話:
您的當(dāng)前位置: > 關(guān)注 > > 正文

播報:在Android系統(tǒng)中為什么需要廣播機制?

來源:CSDN 時間:2023-01-09 07:47:23

在Android系統(tǒng)中,廣播(Broadcast)是在組件之間傳播數(shù)據(jù)(Intent)的一種機制;這些組件甚至是可以位于不同的進程中,這樣它就像Binder機制一樣,起到進程間通信的作用。

在Android系統(tǒng)中,為什么需要廣播機制呢?如果是兩個組件位于不同的進程當(dāng)中,那么可以用Binder機制來實現(xiàn),如果兩個組件是在同一個進程中,那么它們之間可以用來通信的方式就更多了,這樣看來,廣播機制似乎是多余的。

然而,廣播機制卻是不可替代的,它和Binder機制不一樣的地方在于,廣播的發(fā)送者和接收者事先是不需要知道對方的存在的,這樣帶來的好處便是,系統(tǒng)的各個組件可以松耦合地組織在一起,這樣系統(tǒng)就具有高度的可擴展性,容易與其它系統(tǒng)進行集成。


(相關(guān)資料圖)

使用廣播的兩個步驟: 1、廣播的接收者需要通過調(diào)用registerReceiver函數(shù)告訴系統(tǒng),它對什么樣的廣播有興趣,即指定IntentFilter,并且向系統(tǒng)注冊廣播接收器,即指定BroadcastReceiver:

IntentFilter counterActionFilter = new IntentFilter(CounterService.BROADCAST_COUNTER_ACTION);  registerReceiver(counterActionReceiver, counterActionFilter);  

這里,指定感興趣的廣播就是CounterService.BROADCAST_COUNTER_ACTION了,而指定的廣播接收器就是counterActonReceiver,它是一個BroadcastReceiver類型的實例。

2、廣播的發(fā)送者通過調(diào)用sendBroadcast函數(shù)來發(fā)送一個指定的廣播,并且可以指定廣播的相關(guān)參數(shù):

Intent intent = new Intent(BROADCAST_COUNTER_ACTION);  intent.putExtra(COUNTER_VALUE, counter);  sendBroadcast(intent)  

這里,指定的廣播為CounterService.BROADCAST_COUNTER_ACTION,并且附帶的帶參數(shù)當(dāng)前的計數(shù)器值counter。調(diào)用了sendBroadcast函數(shù)之后,所有注冊了CounterService.BROADCAST_COUNTER_ACTION廣播的接收者便可以收到這個廣播了。

在第1步中,廣播的接收者把廣播接收器注冊到ActivityManagerService中;在第2步中,廣播的發(fā)送者同樣是把廣播發(fā)送到ActivityManagerService中,由ActivityManagerService去查找注冊了這個廣播的接收者,然后把廣播分發(fā)給它們。

在第2步的分發(fā)的過程,其實就是把這個廣播轉(zhuǎn)換成一個消息,然后放入到接收器所在的線程消息隊列中去,最后就可以在消息循環(huán)中調(diào)用接收器的onReceive函數(shù)了。這里有一個要非常注意的地方是,由于ActivityManagerService把這個廣播放進接收器所在的線程消息隊列后,就返回了,它不關(guān)心這個消息什么時候會被處理,因此,對廣播的處理是異步的,即調(diào)用sendBroadcast時,這個函數(shù)不會等待這個廣播被處理完后才返回。

虛線上面Step 1到Step 4步是注冊廣播接收器的過程,其中Step 2通過LoadedApk.getReceiverDispatcher在LoadedApk內(nèi)部創(chuàng)建了一個IIntentReceiver接口,并且傳遞給ActivityManagerService;

虛線下面的Step 5到Step 11是發(fā)送廣播的過程,在Step 8中,ActivityManagerService利用上面得到的IIntentReceiver遠程接口,調(diào)用LoadedApk.performReceiver接口,LoadedApk.performReceiver接口通過ActivityThread.H接口的post函數(shù)將這個廣播消息放入到ActivityThread的消息隊列中去,最后這個消息在LoadedApk的Args.run函數(shù)中處理,LoadedApk.Args.run函數(shù)接著調(diào)用MainActivity.BroadcastReceiver的onReceive函數(shù)來最終處理這個廣播。

注冊廣播接收器(registerReceiver)

在Android的廣播機制中,ActivityManagerService扮演著廣播中心的角色,負(fù)責(zé)系統(tǒng)中所有廣播的注冊和發(fā)布操作,因此,Android應(yīng)用程序注冊廣播接收器的過程就把是廣播接收器注冊到ActivityManagerService的過程。Android應(yīng)用程序是通過調(diào)用ContextWrapper類的registerReceiver函數(shù)來把廣播接收器BroadcastReceiver注冊到ActivityManagerService中去的,而ContextWrapper類本身又借助ContextImpl類來注冊廣播接收器。

在Android應(yīng)用程序框架中,Activity和Service類都繼承了ContextWrapper類,因此,我們可以在Activity或者Service的子類中調(diào)用registerReceiver函數(shù)來注冊廣播接收器。

我們先來看一下MainActivity是如何調(diào)用registerReceiver函數(shù)來注冊廣播接收器的:

public class MainActivity extends Activity implements OnClickListener {......        @Override         public void onResume() {super.onResume();              IntentFilter counterActionFilter = new IntentFilter(CounterService.BROADCAST_COUNTER_ACTION);            registerReceiver(counterActionReceiver, counterActionFilter);        }         ......    }

Step 1. ContextWrapper.registerReceiver

public class ContextWrapper extends Context {Context mBase;      ......        @Override      public Intent registerReceiver(          BroadcastReceiver receiver, IntentFilter filter) {return mBase.registerReceiver(receiver, filter);      }        ......    }  

這里的成員變量mBase是一個ContextImpl實例。

Step 2. ContextImpl.registerReceiver

class ContextImpl extends Context {......        @Override      public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {return registerReceiver(receiver, filter, null, null);      }        @Override      public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,              String broadcastPermission, Handler scheduler) {return registerReceiverInternal(receiver, filter, broadcastPermission,              scheduler, getOuterContext());      }        private Intent registerReceiverInternal(BroadcastReceiver receiver,              IntentFilter filter, String broadcastPermission,              Handler scheduler, Context context) {IIntentReceiver rd = null;          if (receiver != null) {if (mPackageInfo != null && context != null) {if (scheduler == null) {scheduler = mMainThread.getHandler();                  }                  rd = mPackageInfo.getReceiverDispatcher(                      receiver, context, scheduler,                      mMainThread.getInstrumentation(), true);              } else {......              }          }          try {return ActivityManagerNative.getDefault().registerReceiver(                      mMainThread.getApplicationThread(),                      rd, filter, broadcastPermission);          } catch (RemoteException e) {return null;          }      }        ......    }  

通過兩個函數(shù)的中轉(zhuǎn),最終就進入到ContextImpl.registerReceiverInternal這個函數(shù)來了。這里的成員變量mPackageInfo是一個LoadedApk實例,它是用來負(fù)責(zé)處理廣播的接收的。

參數(shù)broadcastPermission和scheduler都為null,而參數(shù)context是上面的函數(shù)通過調(diào)用函數(shù)getOuterContext得到的,這里它就是指向MainActivity了,因為MainActivity是繼承于Context類的,因此,這里用Context類型來引用。

由于條件mPackageInfo != null和context != null都成立,而且條件scheduler == null也成立,于是就調(diào)用mMainThread.getHandler來獲得一個Handler了,這個Hanlder是后面用來分發(fā)ActivityManagerService發(fā)送過的廣播用的。這里的成員變量mMainThread是一個ActivityThread實例。

Step 3. ActivityThread.getHandler

public final class ActivityThread {......        final H mH = new H();        private final class H extends Handler {......            public void handleMessage(Message msg) {......                switch (msg.what) {......              }                ......          }            ......        }        ......        final Handler getHandler() {return mH;      }        ......    }  

有了這個Handler之后,就可以分發(fā)消息給應(yīng)用程序處理了。

再回到上一步的ContextImpl.registerReceiverInternal函數(shù)中,它通過mPackageInfo.getReceiverDispatcher函數(shù)獲得一個IIntentReceiver接口對象rd,這是一個Binder對象,接下來會把它傳給ActivityManagerService,ActivityManagerService在收到相應(yīng)的廣播時,就是通過這個Binder對象來通知MainActivity來接收的。

Step 4. LoadedApk.getReceiverDispatcher

final class LoadedApk {......        public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,              Context context, Handler handler,              Instrumentation instrumentation, boolean registered) {synchronized (mReceivers) {LoadedApk.ReceiverDispatcher rd = null;              HashMap map = null;              if (registered) {map = mReceivers.get(context);                  if (map != null) {rd = map.get(r);                  }              }              if (rd == null) {rd = new ReceiverDispatcher(r, context, handler,                      instrumentation, registered);                  if (registered) {if (map == null) {map = new HashMap();                          mReceivers.put(context, map);                      }                      map.put(r, rd);                  }              } else {rd.validate(context, handler);              }              return rd.getIIntentReceiver();          }      }        ......        static final class ReceiverDispatcher {final static class InnerReceiver extends IIntentReceiver.Stub {final WeakReference mDispatcher;              ......                InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {mDispatcher = new WeakReference(rd);                  ......              }                ......          }            ......            final IIntentReceiver.Stub mIIntentReceiver;          final Handler mActivityThread;            ......            ReceiverDispatcher(BroadcastReceiver receiver, Context context,                  Handler activityThread, Instrumentation instrumentation,                  boolean registered) {......                mIIntentReceiver = new InnerReceiver(this, !registered);              mActivityThread = activityThread;                            ......          }            ......            IIntentReceiver getIIntentReceiver() {return mIIntentReceiver;          }        }        ......    }  

在LoadedApk.getReceiverDispatcher函數(shù)中,首先看一下參數(shù)r是不是已經(jīng)有相應(yīng)的ReceiverDispatcher存在了,如果有,就直接返回了,否則就新建一個ReceiverDispatcher,并且以r為Key值保在一個HashMap中,而這個HashMap以Context,這里即為MainActivity為Key值保存在LoadedApk的成員變量mReceivers中,這樣,只要給定一個Activity和BroadcastReceiver,就可以查看LoadedApk里面是否已經(jīng)存在相應(yīng)的廣播接收發(fā)布器ReceiverDispatcher了。

在新建廣播接收發(fā)布器ReceiverDispatcher時,會在構(gòu)造函數(shù)里面創(chuàng)建一個InnerReceiver實例,這是一個Binder對象,實現(xiàn)了IIntentReceiver接口,可以通過ReceiverDispatcher.getIIntentReceiver函數(shù)來獲得,獲得后就會把它傳給ActivityManagerService,以便接收廣播。

在ReceiverDispatcher類的構(gòu)造函數(shù)中,還會把傳進來的Handle類型的參數(shù)activityThread保存下來,以便后面在分發(fā)廣播的時候使用。

現(xiàn)在,再回到ContextImpl.registerReceiverInternal函數(shù),在獲得了IIntentReceiver類型的Binder對象后,就開始要把它注冊到ActivityManagerService中去了。

Step 5. ActivityManagerProxy.registerReceiver

class ActivityManagerProxy implements IActivityManager  {......        public Intent registerReceiver(IApplicationThread caller,              IIntentReceiver receiver,              IntentFilter filter, String perm) throws RemoteException      {Parcel data = Parcel.obtain();          Parcel reply = Parcel.obtain();          data.writeInterfaceToken(IActivityManager.descriptor);          data.writeStrongBinder(caller != null ? caller.asBinder() : null);          data.writeStrongBinder(receiver != null ? receiver.asBinder() : null);          filter.writeToParcel(data, 0);          data.writeString(perm);          mRemote.transact(REGISTER_RECEIVER_TRANSACTION, data, reply, 0);          reply.readException();          Intent intent = null;          int haveIntent = reply.readInt();          if (haveIntent != 0) {intent = Intent.CREATOR.createFromParcel(reply);          }          reply.recycle();          data.recycle();          return intent;      }        ......    }  

這個函數(shù)通過Binder驅(qū)動程序就進入到ActivityManagerService中的registerReceiver函數(shù)中去了。

Step 6. ActivityManagerService.registerReceiver

public final class ActivityManagerService extends ActivityManagerNative          implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {......        public Intent registerReceiver(IApplicationThread caller,              IIntentReceiver receiver, IntentFilter filter, String permission) {synchronized(this) {ProcessRecord callerApp = null;              if (caller != null) {callerApp = getRecordForAppLocked(caller);                  if (callerApp == null) {......                  }              }                List allSticky = null;                // Look for any matching sticky broadcasts...              Iterator actions = filter.actionsIterator();              if (actions != null) {while (actions.hasNext()) {String action = (String)actions.next();                      allSticky = getStickiesLocked(action, filter, allSticky);                  }              } else {......              }                // The first sticky in the list is returned directly back to              // the client.              Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;                ......                if (receiver == null) {return sticky;              }                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 {......                  }                  mRegisteredReceivers.put(receiver.asBinder(), rl);              }                BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);              rl.add(bf);              ......              mReceiverResolver.addFilter(bf);                // Enqueue broadcasts for all existing stickies that match              // this filter.              if (allSticky != null) {......              }                return sticky;          }      }        ......    }  

函數(shù)首先是獲得調(diào)用registerReceiver函數(shù)的應(yīng)用程序進程記錄塊:

ProcessRecord callerApp = null;     if (caller != null) {callerApp = getRecordForAppLocked(caller);  if (callerApp == null) {......         }     }  

這里得到的便是應(yīng)用程序Broadcast的進程記錄塊了,MainActivity就是在里面啟動起來的。

List allSticky = null;       // Look for any matching sticky broadcasts...     Iterator actions = filter.actionsIterator();     if (actions != null) {while (actions.hasNext()) {String action = (String)actions.next();      allSticky = getStickiesLocked(action, filter, allSticky);  }     } else {......     }       // The first sticky in the list is returned directly back to     // the client.     Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null; 

這里傳進來的filter只有一個action,就是前面描述的CounterService.BROADCAST_COUNTER_ACTION了,這里先通過getStickiesLocked函數(shù)查找一下有沒有對應(yīng)的sticky intent列表存在。什么是Sticky Intent呢?我們在最后一次調(diào)用sendStickyBroadcast函數(shù)來發(fā)送某個Action類型的廣播時,系統(tǒng)會把代表這個廣播的Intent保存下來,這樣,后來調(diào)用registerReceiver來注冊相同Action類型的廣播接收器,就會得到這個最后發(fā)出的廣播。這就是為什么叫做Sticky Intent了,這個最后發(fā)出的廣播雖然被處理完了,但是仍然被粘住在ActivityManagerService中,以便下一個注冊相應(yīng)Action類型的廣播接收器還能繼承處理。

這里,假設(shè)我們不使用sendStickyBroadcast來發(fā)送CounterService.BROADCAST_COUNTER_ACTION類型的廣播,于是,這里得到的allSticky和sticky都為null了。

繼續(xù)往下看,這里傳進來的receiver不為null,于是,繼續(xù)往下執(zhí)行:

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 {......  }  mRegisteredReceivers.put(receiver.asBinder(), rl);     }  

這里其實就是把廣播接收器receiver保存一個ReceiverList列表中,這個列表的宿主進程是rl.app,這里就是MainActivity所在的進程了,在ActivityManagerService中,用一個進程記錄塊來表示這個應(yīng)用程序進程,它里面有一個列表receivers,專門用來保存這個進程注冊的廣播接收器。接著,又把這個ReceiverList列表以receiver為Key值保存在ActivityManagerService的成員變量mRegisteredReceivers中,這些都是為了方便在收到廣播時,快速找到對應(yīng)的廣播接收器的。

再往下看:

BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);  rl.add(bf);  ......  mReceiverResolver.addFilter(bf); 

上面只是把廣播接收器receiver保存起來了,但是還沒有把它和filter關(guān)聯(lián)起來,這里就創(chuàng)建一個BroadcastFilter來把廣播接收器列表rl和filter關(guān)聯(lián)起來,然后保存在ActivityManagerService中的成員變量mReceiverResolver中去。

發(fā)送廣播(sendBroadcast)的過程分析

前面我們分析了Android應(yīng)用程序注冊廣播接收器的過程,這個過程只完成了萬里長征的第一步,接下來它還要等待ActivityManagerService將廣播分發(fā)過來。

廣播的發(fā)送過程比廣播接收器的注冊過程要復(fù)雜得多了,不過這個過程仍然是以ActivityManagerService為中心。廣播的發(fā)送者將廣播發(fā)送到ActivityManagerService,ActivityManagerService接收到這個廣播以后,就會在自己的注冊中心查看有哪些廣播接收器訂閱了該廣播,然后把這個廣播逐一發(fā)送到這些廣播接收器中,但是ActivityManagerService并不等待廣播接收器處理這些廣播就返回了,因此,廣播的發(fā)送和處理是異步的。

在分析廣播的發(fā)送過程前,我們先來看一下廣播發(fā)送過程的序列圖,然后按照這個序圖中的步驟來一步一步分析整個過程。

Step 1. ContextWrapper.sendBroadcast

public class ContextWrapper extends Context {Context mBase;        ......        @Override      public void sendBroadcast(Intent intent) {mBase.sendBroadcast(intent);      }        ......    }  

Step 2. ContextImpl.sendBroadcast

class ContextImpl extends Context {......        @Override      public void sendBroadcast(Intent intent) {String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());          try {ActivityManagerNative.getDefault().broadcastIntent(                  mMainThread.getApplicationThread(), intent, resolvedType, null,                  Activity.RESULT_OK, null, null, null, false, false);          } catch (RemoteException e) {}      }        ......    }  

這里的resolvedType表示這個Intent的MIME類型,我們沒有設(shè)置這個Intent的MIME類型,因此,這里的resolvedType為null。接下來就調(diào)用ActivityManagerService的遠程接口ActivityManagerProxy把這個廣播發(fā)送給ActivityManagerService了。

Step 3. ActivityManagerProxy.broadcastIntent

class ActivityManagerProxy implements IActivityManager  {......        public int broadcastIntent(IApplicationThread caller,          Intent intent, String resolvedType,  IIntentReceiver resultTo,          int resultCode, String resultData, Bundle map,          String requiredPermission, boolean serialized,          boolean sticky) throws RemoteException      {Parcel data = Parcel.obtain();          Parcel reply = Parcel.obtain();          data.writeInterfaceToken(IActivityManager.descriptor);          data.writeStrongBinder(caller != null ? caller.asBinder() : null);          intent.writeToParcel(data, 0);          data.writeString(resolvedType);          data.writeStrongBinder(resultTo != null ? resultTo.asBinder() : null);          data.writeInt(resultCode);          data.writeString(resultData);          data.writeBundle(map);          data.writeString(requiredPermission);          data.writeInt(serialized ? 1 : 0);          data.writeInt(sticky ? 1 : 0);          mRemote.transact(BROADCAST_INTENT_TRANSACTION, data, reply, 0);          reply.readException();          int res = reply.readInt();          reply.recycle();          data.recycle();          return res;      }        ......    }  

Step 4. ActivityManagerService.broadcastIntent

public final class ActivityManagerService extends ActivityManagerNative          implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {......        public final int broadcastIntent(IApplicationThread caller,              Intent intent, String resolvedType, IIntentReceiver resultTo,              int resultCode, String resultData, Bundle map,              String requiredPermission, boolean serialized, boolean sticky) {synchronized(this) {intent = verifyBroadcastLocked(intent);                final ProcessRecord callerApp = getRecordForAppLocked(caller);              final int callingPid = Binder.getCallingPid();              final int callingUid = Binder.getCallingUid();              final long origId = Binder.clearCallingIdentity();              int res = broadcastIntentLocked(callerApp,                  callerApp != null ? callerApp.info.packageName : null,                  intent, resolvedType, resultTo,                  resultCode, resultData, map, requiredPermission, serialized,                  sticky, callingPid, callingUid);              Binder.restoreCallingIdentity(origId);              return res;          }      }        ......  }  

這里調(diào)用broadcastIntentLocked函數(shù)來進一步處理。

Step 5. ActivityManagerService.broadcastIntentLocked

public final class ActivityManagerService extends ActivityManagerNative          implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {......        private final int broadcastIntentLocked(ProcessRecord callerApp,              String callerPackage, Intent intent, String resolvedType,              IIntentReceiver resultTo, int resultCode, String resultData,              Bundle map, String requiredPermission,              boolean ordered, boolean sticky, int callingPid, int callingUid) {intent = new Intent(intent);            ......            // Figure out who all will receive this broadcast.          List receivers = null;          List registeredReceivers = null;          try {if (intent.getComponent() != null) {......              } else {......                  registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);              }          } catch (RemoteException ex) {......          }            final boolean replacePending =              (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;            int NR = registeredReceivers != null ? registeredReceivers.size() : 0;          if (!ordered && NR > 0) {// If we are not serializing this broadcast, then send the              // registered receivers separately so they don"t wait for the              // components to be launched.              BroadcastRecord r = new BroadcastRecord(intent, callerApp,                  callerPackage, callingPid, callingUid, requiredPermission,                  registeredReceivers, resultTo, resultCode, resultData, map,                  ordered, sticky, false);              ......              boolean replaced = false;              if (replacePending) {for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {......                          mParallelBroadcasts.set(i, r);                          replaced = true;                          break;                      }                  }              }                if (!replaced) {mParallelBroadcasts.add(r);                    scheduleBroadcastsLocked();              }                registeredReceivers = null;              NR = 0;          }            ......        }        ......  }  

這個函數(shù)首先是根據(jù)intent找出相應(yīng)的廣播接收器:

// Figure out who all will receive this broadcast.     List receivers = null;     List registeredReceivers = null;     try {if (intent.getComponent() != null) {......  } else {......      registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);  }     } catch (RemoteException ex) {......     }  

回憶一下前面過程分析中的Step 6(ActivityManagerService.registerReceiver)中,我們將一個filter類型為BROADCAST_COUNTER_ACTION類型的BroadcastFilter實例保存在了ActivityManagerService的成員變量mReceiverResolver中,這個BroadcastFilter實例包含了我們所注冊的廣播接收器,這里就通過mReceiverResolver.queryIntent函數(shù)將這個BroadcastFilter實例取回來。由于注冊一個廣播類型的接收器可能有多個,所以這里把所有符合條件的的BroadcastFilter實例放在一個List中,然后返回來。在我們這個場景中,這個List就只有一個BroadcastFilter實例了,就是MainActivity注冊的那個廣播接收器。

繼續(xù)往下看:

final boolean replacePending =  (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;  

這里是查看一下這個intent的Intent.FLAG_RECEIVER_REPLACE_PENDING位有沒有設(shè)置,如果設(shè)置了的話,ActivityManagerService就會在當(dāng)前的系統(tǒng)中查看有沒有相同的intent還未被處理,如果有的話,就有當(dāng)前這個新的intent來替換舊的intent。這里,我們沒有設(shè)置intent的Intent.FLAG_RECEIVER_REPLACE_PENDING位,因此,這里的replacePending變量為false。

再接著往下看:

int NR = registeredReceivers != null ? registeredReceivers.size() : 0;    if (!ordered && NR > 0) {// If we are not serializing this broadcast, then send the  // registered receivers separately so they don"t wait for the  // components to be launched.  BroadcastRecord r = new BroadcastRecord(intent, callerApp,      callerPackage, callingPid, callingUid, requiredPermission,      registeredReceivers, resultTo, resultCode, resultData, map,      ordered, sticky, false);  ......  boolean replaced = false;  if (replacePending) {for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {......              mParallelBroadcasts.set(i, r);              replaced = true;              break;          }      }  }    if (!replaced) {mParallelBroadcasts.add(r);        scheduleBroadcastsLocked();  }    registeredReceivers = null;  NR = 0;     }  

前面我們說到,這里得到的列表registeredReceivers的大小為1,且傳進來的參數(shù)ordered為false,表示要將這個廣播發(fā)送給所有注冊了BROADCAST_COUNTER_ACTION類型廣播的接收器,因此,會執(zhí)行下面的if語句。這個if語句首先創(chuàng)建一個廣播記錄塊BroadcastRecord,里面記錄了這個廣播是由誰發(fā)出的以及要發(fā)給誰等相關(guān)信息。由于前面得到的replacePending變量為false,因此,不會執(zhí)行接下來的if語句,即不會檢查系統(tǒng)中是否有相同類型的未處理的廣播。

這樣,這里得到的replaced變量的值也為false,于是,就會把這個廣播記錄塊r放在ActivityManagerService的成員變量mParcelBroadcasts中,等待進一步處理;進一步處理的操作由函數(shù)scheduleBroadcastsLocked進行。

Step 6. ActivityManagerService.scheduleBroadcastsLocked

public final class ActivityManagerService extends ActivityManagerNative          implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {......        private final void scheduleBroadcastsLocked() {......            if (mBroadcastsScheduled) {return;          }            mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);          mBroadcastsScheduled = true;      }        ......  }  

這里的mBroadcastsScheduled表示ActivityManagerService當(dāng)前是不是正在處理其它廣播,如果是的話,這里就先不處理直接返回了,保證所有廣播串行處理。

注意這里處理廣播的方式,它是通過消息循環(huán)來處理,每當(dāng)ActivityManagerService接收到一個廣播時,它就把這個廣播放進自己的消息隊列去就完事了,根本不管這個廣播后續(xù)是處理的,因此,這里我們可以看出廣播的發(fā)送和處理是異步的。

這里的成員變量mHandler是一個在ActivityManagerService內(nèi)部定義的Handler類變量,通過它的sendEmptyMessage函數(shù)把一個類型為BROADCAST_INTENT_MSG的空消息放進ActivityManagerService的消息隊列中去。這里的空消息是指這個消息除了有類型信息之外,沒有任何其它額外的信息,因為前面已經(jīng)把要處理的廣播信息都保存在mParcelBroadcasts中了,等處理這個消息時,從mParcelBroadcasts就可以讀回相關(guān)的廣播信息了,因此,這里不需要把廣播信息再放在消息內(nèi)容中。

Step 7. Handler.sendEmptyMessage

這個自定義的Handler類實現(xiàn)在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中,它是ActivityManagerService的內(nèi)部類,調(diào)用了它的sendEmptyMessage函數(shù)來把一個消息放到消息隊列后,一會就會調(diào)用它的handleMessage函數(shù)來真正處理這個消息:

public final class ActivityManagerService extends ActivityManagerNative          implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {......        final Handler mHandler = new Handler() {public void handleMessage(Message msg) {switch (msg.what) {......              case BROADCAST_INTENT_MSG: {......                  processNextBroadcast(true);              } break;              ......              }          }      }        ......  }   

這里又調(diào)用了ActivityManagerService的processNextBroadcast函數(shù)來處理下一個未處理的廣播。

Step 8. ActivityManagerService.processNextBroadcast

public final class ActivityManagerService extends ActivityManagerNative          implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {......        private final void processNextBroadcast(boolean fromMsg) {synchronized(this) {BroadcastRecord r;                ......                if (fromMsg) {mBroadcastsScheduled = false;              }                // First, deliver any non-serialized broadcasts right away.              while (mParallelBroadcasts.size() > 0) {r = mParallelBroadcasts.remove(0);                  ......                  final int N = r.receivers.size();                  ......                  for (int i=0; iObject target = r.receivers.get(i);                      ......                        deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);                  }                  addBroadcastToHistoryLocked(r);                  ......              }                ......            }      }        ......  }  

這里傳進來的參數(shù)fromMsg為true,于是把mBroadcastScheduled重新設(shè)為false,這樣,下一個廣播就能進入到消息隊列中進行處理了。前面我們在Step 5中,把一個廣播記錄塊BroadcastRecord放在了mParallelBroadcasts中,因此,這里就把它取出來進行處理了。廣播記錄塊BroadcastRecord的receivers列表中包含了要接收這個廣播的目標(biāo)列表,即前面我們注冊的廣播接收器,用BroadcastFilter來表示,這里while循環(huán)中的for循環(huán)就是把這個廣播發(fā)送給每一個訂閱了該廣播的接收器了,通過deliverToRegisteredReceiverLocked函數(shù)執(zhí)行。

Step 9. ActivityManagerService.deliverToRegisteredReceiverLocked

public final class ActivityManagerService extends ActivityManagerNative          implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {......        private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,              BroadcastFilter filter, boolean ordered) {boolean skip = false;          if (filter.requiredPermission != null) {......          }          if (r.requiredPermission != null) {......          }            if (!skip) {// If this is not being sent as an ordered broadcast, then we              // don"t want to touch the fields that keep track of the current              // state of ordered broadcasts.              if (ordered) {......              }                try {......                  performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,                      new Intent(r.intent), r.resultCode,                      r.resultData, r.resultExtras, r.ordered, r.initialSticky);                  ......              } catch (RemoteException e) {......              }          }        }        ......  }  

函數(shù)首先是檢查一下廣播發(fā)送和接收的權(quán)限,在我們分析的這個場景中,沒有設(shè)置權(quán)限,因此,這個權(quán)限檢查就跳過了,這里得到的skip為false,于是進入下面的if語句中。由于上面?zhèn)鲿r來的ordered參數(shù)為false,因此,直接就調(diào)用performReceiveLocked函數(shù)來進一步執(zhí)行廣播發(fā)送的操作了。

Step 10. ActivityManagerService.performReceiveLocked

public final class ActivityManagerService extends ActivityManagerNative          implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {......        static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,              Intent intent, int resultCode, String data, Bundle extras,              boolean ordered, boolean sticky) throws RemoteException {// Send the intent to the receiver asynchronously using one-way binder calls.          if (app != null && app.thread != null) {// If we have an app thread, do the call through that so it is              // correctly ordered with other one-way calls.              app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,                      data, extras, ordered, sticky);          } else {......          }      }        ......  }  

注意,這里傳進來的參數(shù)app是注冊廣播接收器的Activity所在的進程記錄塊,在我們分析的這個場景中,由于是MainActivity調(diào)用registerReceiver函數(shù)來注冊這個廣播接收器的,因此,參數(shù)app所代表的ProcessRecord就是MainActivity所在的進程記錄塊了;

而參數(shù)receiver也是注冊廣播接收器時傳給ActivityManagerService的一個Binder對象,它的類型是IIntentReceiver。

MainActivity在注冊廣播接收器時,已經(jīng)把自己的ProcessRecord記錄下來了,所以這里的參數(shù)app和app.thread均不為null,于是,ActivityManagerService就調(diào)用app.thread.scheduleRegisteredReceiver函數(shù)來把這個廣播分發(fā)給MainActivity了。這里的app.thread是一個Binder遠程對象,它的類型是ApplicationThreadProxy。

Step 11. ApplicationThreadProxy.scheduleRegisteredReceiver

class ApplicationThreadProxy implements IApplicationThread {......        public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,              int resultCode, String dataStr, Bundle extras, boolean ordered, boolean sticky)              throws RemoteException {Parcel data = Parcel.obtain();          data.writeInterfaceToken(IApplicationThread.descriptor);          data.writeStrongBinder(receiver.asBinder());          intent.writeToParcel(data, 0);          data.writeInt(resultCode);          data.writeString(dataStr);          data.writeBundle(extras);          data.writeInt(ordered ? 1 : 0);          data.writeInt(sticky ? 1 : 0);          mRemote.transact(SCHEDULE_REGISTERED_RECEIVER_TRANSACTION, data, null,              IBinder.FLAG_ONEWAY);          data.recycle();      }        ......  }  

這里通過Binder驅(qū)動程序就進入到ApplicationThread.scheduleRegisteredReceiver函數(shù)去了。

Step 12. ApplicaitonThread.scheduleRegisteredReceiver

public final class ActivityThread {......        private final class ApplicationThread extends ApplicationThreadNative {......            // This function exists to make sure all receiver dispatching is          // correctly ordered, since these are one-way calls and the binder driver          // applies transaction ordering per object for such calls.          public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,                  int resultCode, String dataStr, Bundle extras, boolean ordered,                  boolean sticky) throws RemoteException {receiver.performReceive(intent, resultCode, dataStr, extras, ordered, sticky);          }            ......      }        ......    }  

這里的receiver是在前面過程分析中的Step 4中創(chuàng)建的,它的具體類型是LoadedApk.ReceiverDispatcher.InnerReceiver,即定義在LoadedApk類的內(nèi)部類ReceiverDispatcher里面的一個內(nèi)部類InnerReceiver,這里調(diào)用它的performReceive函數(shù)。

Step 13. InnerReceiver.performReceive

final class LoadedApk {......         static final class ReceiverDispatcher {final static class InnerReceiver extends IIntentReceiver.Stub {......                public void performReceive(Intent intent, int resultCode,                      String data, Bundle extras, boolean ordered, boolean sticky) {LoadedApk.ReceiverDispatcher rd = mDispatcher.get();                  ......                  if (rd != null) {rd.performReceive(intent, resultCode, data, extras,                              ordered, sticky);                  } else {......                  }              }          }            ......      }        ......  }  

這里,它只是簡單地調(diào)用ReceiverDispatcher的performReceive函數(shù)來進一步處理,這里的ReceiverDispatcher類是LoadedApk類里面的一個內(nèi)部類。

Step 14. ReceiverDispatcher.performReceive

final class LoadedApk {......         static final class ReceiverDispatcher {......            public void performReceive(Intent intent, int resultCode,                  String data, Bundle extras, boolean ordered, boolean sticky) {......                Args args = new Args();              args.mCurIntent = intent;              args.mCurCode = resultCode;              args.mCurData = data;              args.mCurMap = extras;              args.mCurOrdered = ordered;              args.mCurSticky = sticky;              if (!mActivityThread.post(args)) {......              }           }            ......      }        ......  }  

這里mActivityThread成員變量的類型為Handler,它是前面MainActivity注冊廣播接收器時,從ActivityThread取得的。

這里ReceiverDispatcher借助這個Handler,把這個廣播以消息的形式放到MainActivity所在的這個ActivityThread的消息隊列中去,因此,ReceiverDispatcher不等這個廣播被MainActivity處理就返回了,這里也體現(xiàn)了廣播的發(fā)送和處理是異步進行的。

注意這里處理消息的方式是通過Handler.post函數(shù)進行的,post函數(shù)的參數(shù)是Runnable類型的,這個消息最終會調(diào)用這個這個參數(shù)的run成員函數(shù)來處理。這里的Args類是LoadedApk類的內(nèi)部類ReceiverDispatcher的一個內(nèi)部類,它繼承于Runnable類,因此,可以作為mActivityThread.post的參數(shù)傳進去,代表這個廣播的intent也保存在這個Args實例中。

Step 15. Hanlder.post

這個函數(shù)定義在frameworks/base/core/java/android/os/Handler.java文件中,它的作用就是把消息放在消息隊列中,然后就返回了,這個消息最終會在傳進來的Runnable類型的參數(shù)的run成員函數(shù)中進行處理。

Step 16. Args.run

final class LoadedApk {......         static final class ReceiverDispatcher {......            final class Args implements Runnable {......                public void run() {BroadcastReceiver receiver = mReceiver;                    ......                    Intent intent = mCurIntent;                                    ......                    try {ClassLoader cl =  mReceiver.getClass().getClassLoader();                      intent.setExtrasClassLoader(cl);                      if (mCurMap != null) {mCurMap.setClassLoader(cl);                      }                      receiver.setOrderedHint(true);                      receiver.setResult(mCurCode, mCurData, mCurMap);                      receiver.clearAbortBroadcast();                      receiver.setOrderedHint(mCurOrdered);                      receiver.setInitialStickyHint(mCurSticky);                      receiver.onReceive(mContext, intent);                  } catch (Exception e) {......                  }                    ......              }                ......          }            ......      }        ......  }  

這里的mReceiver是ReceiverDispatcher類的成員變量,它的類型是BroadcastReceiver,這里它就是MainActivity注冊廣播接收器時創(chuàng)建的BroadcastReceiver實例了。

有了這個ReceiverDispatcher實例之后,就可以調(diào)用它的onReceive函數(shù)把這個廣播分發(fā)給它處理了。

Step 17. BroadcastReceiver.onReceive

public class MainActivity extends Activity implements OnClickListener {......          private BroadcastReceiver counterActionReceiver = new BroadcastReceiver(){public void onReceive(Context context, Intent intent) {int counter = intent.getIntExtra(CounterService.COUNTER_VALUE, 0);                String text = String.valueOf(counter);                counterText.setText(text);                  Log.i(LOG_TAG, "Receive counter event");            }          }        ......      }  

這樣,MainActivity里面的定義的BroadcastReceiver實例counterActionReceiver就收到這個廣播并進行處理了。

至此,Android應(yīng)用程序發(fā)送廣播的過程就分析完成了。

最后,我們總結(jié)一下這個Android應(yīng)用程序發(fā)送廣播的過程:

Step 1 - Step 7,計數(shù)器服務(wù)CounterService通過sendBroadcast把一個廣播通過Binder進程間通信機制發(fā)送給ActivityManagerService,ActivityManagerService根據(jù)這個廣播的Action類型找到相應(yīng)的廣播接收器,然后把這個廣播放進自己的消息隊列中去,就完成第一階段對這個廣播的異步分發(fā)了;Step 8 - Step 15,ActivityManagerService在消息循環(huán)中處理這個廣播,并通過Binder進程間通信機制把這個廣播分發(fā)給注冊的廣播接收分發(fā)器ReceiverDispatcher,ReceiverDispatcher把這個廣播放進MainActivity所在的線程的消息隊列中去,就完成第二階段對這個廣播的異步分發(fā)了;Step 16 - Step 17, ReceiverDispatcher的內(nèi)部類Args在MainActivity所在的線程消息循環(huán)中處理這個廣播,最終是將這個廣播分發(fā)給所注冊的BroadcastReceiver實例的onReceive函數(shù)進行處理。
責(zé)任編輯:

標(biāo)簽:

相關(guān)推薦:

精彩放送:

新聞聚焦
Top 欧美网址在线观看-亚洲最新毛片-国产成人免费爽爽爽视频-亚洲一区在线影院-日韩欧美在线观看视频网站-男女激情四射-成人一区二区免费看-欧美亚洲综合在线-日韩一级视频在线播放-国产成人三级视频在线播放-亚洲中文字幕日产无码2020-99久久久国产精品免费无卡顿-av在线观看地址-果冻传媒mv免费播放在线观看-欧美在线观看视频免费-日韩天天操

        日韩精品免费一区| 每日在线观看av| 国产无套内射久久久国产| 91丝袜超薄交口足| 天天操天天爱天天爽| 波多野结衣乳巨码无在线| 欧美一级中文字幕| 糖心vlog在线免费观看| 不用播放器的免费av| 一区二区三区免费播放| 日韩a在线播放| 免费看一级大黄情大片| 奇米影视亚洲色图| 97超碰人人澡| 成人黄色av片| 日韩精品―中文字幕| a在线视频观看| 99999精品视频| 男人透女人免费视频| 日韩欧美xxxx| 欧美 激情 在线| 蜜臀视频一区二区三区| 欧美一级黄色影院| av五月天在线| 奇米影视四色在线| 色噜噜狠狠一区二区三区狼国成人| 性欧美videossex精品| 午夜免费看视频| www.日本久久| 大陆极品少妇内射aaaaaa| 99久久99久久精品| 国产91xxx| 日本熟妇人妻中出| 中文字幕视频三区| 成人手机在线播放| 毛片在线视频播放| 久久久久久久中文| 国产免费黄色一级片| 日韩视频免费播放| 97xxxxx| 成人亚洲精品777777大片| 五月婷婷之婷婷| 无码毛片aaa在线| 免费国产a级片| av免费网站观看| 欧美 日韩 国产 在线观看| 国产一级片91| 国产熟女高潮视频| 天天操天天干天天做| h无码动漫在线观看| 少妇性饥渴无码a区免费| 天天摸天天舔天天操| 日本a级片在线观看| 男女午夜激情视频| 亚洲综合伊人久久| 拔插拔插海外华人免费| 嫩草影院国产精品| 高清无码视频直接看| 91av俱乐部| 欧美乱做爰xxxⅹ久久久| 免费看欧美黑人毛片| 午夜精品久久久内射近拍高清| 国产主播自拍av| 久久久久xxxx| 大陆av在线播放| 可以在线看黄的网站| 国产精品av免费| 黄色网络在线观看| 欧美 国产 精品| 国产尤物av一区二区三区| 中文字幕一区二区三区四| 欧美性受xxxx黑人猛交88| 一级黄色免费在线观看| 欧美久久在线观看| 五月天婷婷亚洲| 99精品在线免费视频| 91看片破解版| 999精品视频在线| 欧美在线一区视频| 中国 免费 av| 草草草在线视频| 成人3d动漫一区二区三区| 男人天堂网站在线| 1314成人网| 污色网站在线观看| 无码aⅴ精品一区二区三区浪潮 | 国产淫片av片久久久久久| 国产卡一卡二在线| www.午夜av| 日本美女视频一区| 91蝌蚪视频在线观看| 97av视频在线观看| 日韩免费毛片视频| 免费黄色福利视频| 亚洲美免无码中文字幕在线| 国内自拍中文字幕| 国产一区二区三区在线免费| 中文字幕第22页| 免费看啪啪网站| 91大神免费观看| 99精品视频网站| 九九热视频免费| 日本一级淫片演员| 中国一级黄色录像| 五月天男人天堂| 看一级黄色录像| 免费看日本黄色| 色欲色香天天天综合网www| 青草网在线观看| av免费观看大全| 97xxxxx| 蜜臀视频一区二区三区| 国产原创精品在线| 毛毛毛毛毛毛毛片123| 五月六月丁香婷婷| 亚洲爆乳无码精品aaa片蜜桃| 51xx午夜影福利| 自拍日韩亚洲一区在线| 六月丁香婷婷激情| 日韩一级免费片| 日本不卡一区二区三区四区| 免费久久久久久| 你懂的av在线| 91人人澡人人爽人人精品| 精品久久久99| 妺妺窝人体色www看人体| 亚洲中文字幕无码专区| 日本爱爱免费视频| 法国空姐在线观看免费| www.日本少妇| 91插插插插插插插插| 日本三日本三级少妇三级66| 欧日韩免费视频| 欧美精品久久久久久久久25p| 色撸撸在线观看| 69堂免费视频| 三年中文高清在线观看第6集| av一区二区三区免费观看| 日本久久精品一区二区| 成年人三级视频| 成年人免费大片| 337p亚洲精品色噜噜狠狠p| 老司机午夜av| 国产在线视频在线| 一级黄色特级片| 免费 成 人 黄 色| 不用播放器的免费av| 每日在线更新av| 麻豆视频传媒入口| 精品少妇无遮挡毛片| 国产高清www| 麻豆md0077饥渴少妇| 韩国日本美国免费毛片| 搞av.com| 午夜久久久久久久久久久| 国产aaaaa毛片| 日韩国产一级片| 欧美爱爱视频网站| 日韩av片网站| 黑鬼大战白妞高潮喷白浆| 亚洲熟妇无码av在线播放| 中文字幕第一页在线视频| 国产麻花豆剧传媒精品mv在线| av电影一区二区三区| 天天看片天天操| 成人免费在线观看视频网站| 欧美成人一区二区在线观看| 大地资源网在线观看免费官网| 五月天婷婷亚洲| 69久久久久久| 黄色a级片免费| www国产黄色| 日日鲁鲁鲁夜夜爽爽狠狠视频97| 亚洲爆乳无码精品aaa片蜜桃| www.com久久久| 思思久久精品视频| 日韩av卡一卡二| 一区二区三区视频网| 波多结衣在线观看| 亚洲欧美激情网| 三年中国国语在线播放免费| 中国丰满人妻videoshd| 9色porny| 激情五月宗合网| 久章草在线视频| 久久午夜夜伦鲁鲁一区二区| 无码人妻丰满熟妇区毛片| 欧美aⅴ在线观看| 日本www高清视频| 国产小视频精品| 亚洲天堂伊人网| 熟妇熟女乱妇乱女网站| 久久综合亚洲精品| 欧美日韩福利在线| 精品视频在线观看一区| 欧美深夜福利视频| 国产激情在线观看视频| 不卡影院一区二区| 五月天视频在线观看| 一级全黄肉体裸体全过程|