sendBroadcastAsUser——Calling a method in the system process
Posted skiwnchhw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了sendBroadcastAsUser——Calling a method in the system process相关的知识,希望对你有一定的参考价值。
改换这几种调用方式
public void startActivityAsUser(Intent intent, UserHandle user);
public void sendBroadcastAsUser(Intent intent, UserHandle user);
public ComponentName startServiceAsUser(Intent service, UserHandle user);
public boolean stopServiceAsUser(Intent service, UserHandle user);
UserHandle.ALL
UserHandle.CURRENT
UserHandle.CURRENT_OR_SELF
UserHandle.OWNER
延伸阅读
先看下面代码
private void broadcastCallStateChanged(int state, String incomingNumber) {
//... ...省略
//TelephonyManager.ACTION_PHONE_STATE_CHANGED 即"android.intent.action.PHONE_STATE"
Intent intent = new Intent(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
//PhoneConstants.STATE_KEY 即字符串"state"
intent.putExtra(PhoneConstants.STATE_KEY, DefaultPhoneNotifier.convertCallState(state).toString());
//如果incomingNumber不为空则添加到intent的Extra中,对应的key为"incoming_number"
if (!TextUtils.isEmpty(incomingNumber)) {
intent.putExtra(TelephonyManager.EXTRA_INCOMING_NUMBER, incomingNumber);
}
//MTK Dual SIM support,对应key为"simId"
if (FeatureOption.MTK_GEMINI_SUPPORT) {
intent.putExtra(PhoneConstants.GEMINI_SIM_ID_KEY, mySimId);
}
//发送广播,接收者为所有人,接收者需要有READ_PHONE_STATE权限
mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
android.Manifest.permission.READ_PHONE_STATE);
}
在Android 4.0之前,并非使用sendBroadcastAsUser,而是使用sendBroadcast(intent, android.Manifest.permission.READ_PHONE_STATE)发起广播通知,两者相比,前者多了一个UserHandle.ALL的参数,该参数系Google在Android中添加用于区分用户组的标志。
在Android 4.2 之后Android引入多用户支持,目前Android平台多用户仅支持平板设备。虽然在Android 4.2 中我们已经可以看到Android多用户支持的影子,但直到Android 4.4 google还是没有正式推出。因为Android 平板和手机共用一套代码,因此这里简单的提一下Android 4.4中多用户所支持的用户组。
Android 4.4 用户分为:UserHandle.ALL、UserHandle.CURRENT、UserHandle.CURRENT_OR_SELF、UserHandle.OWNER四种类型,每种类型的handle不同。详细描述如下:
- /** A user handle to indicate all users on the device */
- //设备上所有用户均可接收到广播
- // handle = -1
- UserHandle.ALL
- /** A user handle to indicate the current user of the device */
- //设备上当前用户可接收到广播
- // handle = -2
- UserHandle.CURRENT
- /** A user handle to indicate that we would like to send to the current
- * user, but if this is calling from a user process then we will send it
- * to the caller‘s user instead of failing wiht a security exception */
- //handle = -3
- //设备上当前用户或者该应用所属用户可接收到广播
- UserHandle.CURRENT_OR_SELF
- /** A user handle to indicate the primary/owner user of the device */
- // handle = 0
- //设备所有者可接收到广播
- UserHandle.OWNER
这里的广播范围可以排序为:UserHandle.ALL > UserHandle.OWNER > UserHandle.CURRENT_OR_SELF > UserHandle.CURRENT。注意UserHandle.ALL包含了所有用户,而OWNER仅仅是设备持有者(注意guest用户)。
阅读更多:
http://blog.csdn.net/yihongyuelan/article/details/32324335
Android
4.4 Kitkat Phone工作流程浅析(九)__状态通知流程分析
概要
当手机Modem状态改变后会将状态变化信息通知到上层,通过《Android 4.4 Kitkat Phone工作流程浅析(八)__Phone状态分析》和《Android 4.4 Kitkat Phone工作流程浅析(六)__InCallActivity显示更新流程》的分析,我们知道了Phone状态的类型,以及这些状态的上报流程,而本文主要分析Phone状态改变之后是如何通知到三方应用的。
Phone状态对于三方应用来讲主要包括:TelephonyManager.CALL_STATE_IDLE、TelephonyManager.CALL_STATE_RINGING、TelephonyManager.CALL_STATE_OFFHOOK三种。对于三方应用,通常使用两种方法来获知Phone状态的改变即:
①监听Phone状态改变广播;
②使用PhoneStateListener监听Phone状态。PhoneStateListener不仅能监听Phone状态改变,同时还能监听数据连接状态、Phone服务状态等状态改变信息;
两种方法所对应的相关代码如下:
- //1.注册广播监听Phone状态改变
- //1.1 动态注册广播
- public class MainActivity extends Activity {
- private PhoneStateChangedReceiver mPhoneStateChangedReceiver;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- //Dynamic register the broadcast
- IntentFilter filter = new IntentFilter();
- //"android.intent.action.PHONE_STATE"
- filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
- //"android.intent.action.NEW_OUTGOING_CALL"
- filter.addAction(Intent.ACTION_NEW_OUTGOING_CALL);
- mPhoneStateChangedReceiver = new PhoneStateChangedReceiver();
- registerReceiver(mPhoneStateChangedReceiver, filter);
- }
- @Override
- protected void onDestroy() {
- //unregister the broadcast when activity destroyed
- unregisterReceiver(mPhoneStateChangedReceiver);
- super.onDestroy();
- }
- //内部类广播
- public static class PhoneStateChangedReceiver extends BroadcastReceiver {
- @Override
- public void onReceive(Context context, Intent intent) {
- //Action is "android.intent.action.PHONE_STATE"
- //or "android.intent.action.NEW_OUTGOING_CALL"
- String action = intent.getAction();
- Log.i("Seven","action is "+action);
- if (Intent.ACTION_NEW_OUTGOING_CALL.equals(action)) {
- //"android.intent.extra.PHONE_NUMBER"
- String outgoingNum = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
- Log.i("Seven", "It‘s outgoing call. Number is:"+outgoingNum);
- return;
- }
- //State is RINGING/OFFHOOK/IDLE
- String state = intent.getStringExtra("state");
- //Only state is Ringing can get the incoming_number
- String incomingNum = intent.getStringExtra("incoming_number");
- //MTK add for dual SIM support
- String simId = intent.getStringExtra("simId");
- Log.i("Seven", "state is "+state);
- Log.i("Seven", "incomingNum is "+incomingNum);
- Log.i("Seven", "simId is "+simId);
- }
- }
- }
- //1.2 静态注册广播
- //与动态注册的区别主要是需要在AndroidManifest.xml中添加<receiver>标签
- <receiver
- android:name="com.seven.androidphonestatelistenerdemo.MainActivity$PhoneStateChangedReceiver" >
- <intent-filter>
- <action android:name="android.intent.action.PHONE_STATE" />
- <action android:name="android.intent.action.NEW_OUTGOING_CALL" />
- </intent-filter>
- </receiver>
- //注意:无论是静态还是动态注册均需要添加相应的权限
- <uses-permission android:name="android.permission.READ_PHONE_STATE" />
- <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
- 2.使用PhoneStateListener监听Phone状态改变
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- //TELEPHONY_SERVICE equals "phone"
- TelephonyManager mTelephonyManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
- mTelephonyManager.listen(new PhoneStateListener(){
- @Override
- public void onCallStateChanged(int state, String incomingNumber) {
- switch (state) {
- case TelephonyManager.CALL_STATE_IDLE:
- Log.i("Seven","Call state is IDLE");
- break;
- case TelephonyManager.CALL_STATE_RINGING:
- Log.i("Seven","Call state is RINGING");
- break;
- case TelephonyManager.CALL_STATE_OFFHOOK:
- Log.i("Seven","Call state is OFFHOOK");
- break;
- default:
- break;
- }
- super.onCallStateChanged(state, incomingNumber);
- }
- }, PhoneStateListener.LISTEN_CALL_STATE);
- }
以上两种方法均可实现监听Phone状态的改变,通过广播的方式可以监听"去电状态"和"Phone状态"改变,而如果通过PhoneStateListener则只能监听Phone状态改变。这里我们先以MT流程为例,从代码的执行流程上分析Phone状态改变后是如何通知到三方应用的,后文也会顺带分析去电广播的发起流程。
通过前面文章的分析,我们知道Phone状态的改变是Modem发起的,之后通过framework、TeleService并最终通过InCallUI表现到界面上,整个流程如图1:
通过图1可以知道,所有的状态都是从Modem发起并经过Telephony Framework处理之后再向上传递的,也是正是在Telephony Framework中,系统将Phone相关状态告知给了三方应用。
状态通知发起流程
当Phone状态改变之后,RILJ将相关信息反馈到GsmCallTracker的handleCallProgressInfo()方法中 (AOSP是handlePollCalls) 进行相关的处理。在该方法中会进行Phone状态的转换,在上一篇文章《Android 4.4 Kitkat Phone工作流程浅析(八)__Phone状态分析》中我们有详细分析,这里不再详细解释。
在handleCallProgressInfo()的updatePhoneState()方法中进行Call.State(Internal)和PhoneConstants.State转换时,有如下代码:
以上是关于sendBroadcastAsUser——Calling a method in the system process的主要内容,如果未能解决你的问题,请参考以下文章