、
这篇文章针对的是系统权限的app,因为
Intent.ACTION_AIRPLANE_MODE_CHANGED 在AndroidManifest.xml文件中属于<protected-broadcat/>,需要权限需要高权限才能操作,
//Intent.class
public class Intent implements Parcelable, Cloneable {
...public static final String ACTION_AIRPLANE_MODE_CHANGED = "android.intent.action.AIRPLANE_MODE";
...
}// framework/base/core/res/AndroidManifest.xml
<protected-broadcast android:name="android.intent.action.AIRPLANE_MODE" />
应为Android 发送广播最终要走 ActivityManagerService 的broadcastIntentLocked 方法,我贴一段发送广播的代码,在里面有一段代码是判断当前 app的 uid权限的,如果权限不够则直接跑出异常
@GuardedBy("this")final int broadcastIntentLocked(ProcessRecord callerApp,String callerPackage, Intent intent, String resolvedType,IIntentReceiver resultTo, int resultCode, String resultData,Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions,boolean ordered, boolean sticky, int callingPid, int callingUid, int userId) {...final boolean isCallerSystem;switch (UserHandle.getAppId(callingUid)) {case ROOT_UID:case SYSTEM_UID:case PHONE_UID:case BLUETOOTH_UID:case NFC_UID:case SE_UID:isCallerSystem = true;break;default:isCallerSystem = (callerApp != null) && callerApp.persistent;break;}// First line security check before anything else: stop non-system apps from// sending protected broadcasts.if (!isCallerSystem) {if (isProtectedBroadcast) {String msg = "Permission Denial: not allowed to send broadcast "+ action + " from pid="+ callingPid + ", uid=" + callingUid;Slog.w(TAG, msg);throw new SecurityException(msg);} else if (AppWidgetManager.ACTION_APPWIDGET_CONFIGURE.equals(action)|| AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)) {// Special case for compatibility: we don't want apps to send this,// but historically it has not been protected and apps may be using it// to poke their own app widget. So, instead of making it protected,// just limit it to the caller.if (callerPackage == null) {String msg = "Permission Denial: not allowed to send broadcast "+ action + " from unknown caller.";Slog.w(TAG, msg);throw new SecurityException(msg);} else if (intent.getComponent() != null) {// They are good enough to send to an explicit component... verify// it is being sent to the calling app.if (!intent.getComponent().getPackageName().equals(callerPackage)) {String msg = "Permission Denial: not allowed to send broadcast "+ action + " to "+ intent.getComponent().getPackageName() + " from "+ callerPackage;Slog.w(TAG, msg);throw new SecurityException(msg);}} else {// Limit broadcast to their own package.intent.setPackage(callerPackage);}}}... return ActivityManager.BROADCAST_SUCCESS;}
/*** 飞行模式开关* @param setAirPlane*/public static void toggleAirplaneMode(Context context,boolean setAirPlane) {Log.d(TAG, "toggleAirplaneMode: "+setAirPlane);String value = setAirPlane?"1":"0";Log.d(TAG, "toggleAirplaneMode: "+value);Settings.Global.putString( context.getContentResolver(),Settings.Global.AIRPLANE_MODE_ON,value );Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);context.sendBroadcast(intent);}