Android 6.0 permissions are no longer given to you at install time. If you need permissions, you need to get them in your code. For users, the “Access Permissions” will pop up so that users can see what permissions the application has, and then decide whether to grant them or not.
For example, the following example is a spammy program to obtain the permission for SMS
I just need to add a line in the code, the “2” in the parameter is arbitrarily written, is to enter an integer, representing the request code.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.requestPermissions(
new String[]{Manifest.permission.SEND_SMS},
2);
}Copy the code
This article does not say too much, say how this popbox is good. The first entry is the Activity class, which calls requestPermissions to get the permissions. You can see that he starts another Activity. You can imagine that the popbox is inside the Activity. Let’s look at what the Intent is and find the package name and Action of the Intent. /frameworks/ base/core/java/android/app/Activity.java
public final void requestPermissions(@NonNull String[] permissions, int requestCode) {
Intent intent = getPackageManager().buildRequestPermissionsIntent(permissions);
startActivityForResult(REQUEST_PERMISSIONS_WHO_PREFIX, intent, requestCode, null);
}Copy the code
Through ContextImpl. GetPackageManager () get ApplicationPackageManager, he is the parent of the PackageManager. /frameworks/base/core/java/android/app/ContextImpl.java
@Override
public PackageManager getPackageManager() {
if(mPackageManager ! =null) {
return mPackageManager;
}
IPackageManager pm = ActivityThread.getPackageManager();
if(pm ! =null) {
// Doesn't matter if we make more than one instance.
return (mPackageManager = new ApplicationPackageManager(this, pm));
}
return null;
}Copy the code
ApplicationPackageManager access to the intent of the action is android. The content. PM. Action. REQUEST_PERMISSIONS, package name to look at, Through getPermissionControllerPackageName (). /frameworks/base/core/java/android/app/ApplicationPackageManager.java
public static final String ACTION_REQUEST_PERMISSIONS =
"android.content.pm.action.REQUEST_PERMISSIONS";
public static final String EXTRA_REQUEST_PERMISSIONS_NAMES =
"android.content.pm.extra.REQUEST_PERMISSIONS_NAMES";
public Intent buildRequestPermissionsIntent(@NonNull String[] permissions) {
if (ArrayUtils.isEmpty(permissions)) {
throw new NullPointerException("permission cannot be null or empty");
}
Intent intent = new Intent(ACTION_REQUEST_PERMISSIONS);
intent.putExtra(EXTRA_REQUEST_PERMISSIONS_NAMES, permissions);
intent.setPackage(getPermissionControllerPackageName());
return intent;
}Copy the code
GetPermissionControllerPackageName () will further call mPM. GetPermissionControllerPackageName (), the mPM is the service PackageManagerService remote agent system.
@Override
public String getPermissionControllerPackageName(a) {
synchronized (mLock) {
if (mPermissionsControllerPackageName == null) {
try {
mPermissionsControllerPackageName = mPM.getPermissionControllerPackageName();
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e); }}returnmPermissionsControllerPackageName; }}Copy the code
The PackageManagerService getRequiredInstallerLPr is used to obtain the package name, which is used to install apk.
/frameworks/base/services/core/java/ com/android/server/ pm/PackageManagerService.java
private String getRequiredInstallerLPr() {
Intent installerIntent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
installerIntent.addCategory(Intent.CATEGORY_DEFAULT);
installerIntent.setDataAndType(Uri.fromFile(new File("foo.apk")), PACKAGE_MIME_TYPE);
final List<ResolveInfo> installers = queryIntentActivities(installerIntent,
PACKAGE_MIME_TYPE, 0.0);
String requiredInstaller = null;
final int N = installers.size();
for (int i = 0; i < N; i++) {
final ResolveInfo info = installers.get(i);
final String packageName = info.activityInfo.packageName;
if(! info.activityInfo.applicationInfo.isSystemApp()) {continue;
}
if(requiredInstaller ! =null) {
throw new RuntimeException("There must be one required installer");
}
requiredInstaller = packageName;
}
if (requiredInstaller == null) {
throw new RuntimeException("There must be one required installer");
}
return requiredInstaller;
}Copy the code
So, finally the combination of the intent of the package name is com. The android. Packageinstaller, the action is android. The content. PM. Action. REQUEST_PERMISSIONS.
This Action starts the application installer’s GrantPermissionsActivity for authorization
So, this box is popped up from GrantPermissionsActivity. Analysis done!