- $ adb shell dumpsys activity | grep "mResumedActivity" --color=auto
- mResumedActivity: ActivityRecord{32c5bd u0 com.android.settings/.applications.InstalledAppDetails t28}
代码
主要的action:
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_APPLICATION_DETAILS_SETTINGS = "android.settings.APPLICATION_DETAILS_SETTINGS";
- Intent intent = new Intent();
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- if (Build.VERSION.SDK_INT >= 9) {
- intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
- intent.setData(Uri.fromParts("package", "指定应用包名, null));
- } else if (Build.VERSION.SDK_INT <= 8) {
- intent.setAction(Intent.ACTION_VIEW);
- intent.setClassName("com.android.settings", "com.android.settings.InstalledAppDetails");
- intent.putExtra("com.android.settings.ApplicationPkgName", "指定应用的包名");
- }
- startActivity(intent);
配置文件
-
- <activity android:name=".applications.InstalledAppDetailsTop"
- android:label="@string/application_info_label"
- android:exported="true" />
-
-
- <activity-alias android:name=".applications.InstalledAppDetails"
- android:label="@string/application_info_label"
- android:exported="true"
- android:targetActivity=".applications.InstalledAppDetailsTop">
- <intent-filter android:priority="1">
- <action android:name="android.settings.APPLICATION_DETAILS_SETTINGS" />
- <action android:name="android.intent.action.AUTO_REVOKE_PERMISSIONS" />
- <category android:name="android.intent.category.DEFAULT" />
- <data android:scheme="package" />
- intent-filter>
- activity-alias>
- packageUtils.installApp = function (path) {
- if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) {//sd 卡已挂载
- var targetFile = new java.io.File(path);
- if (targetFile.exists()) {
- var intent = new android.content.Intent(android.content.Intent.ACTION_VIEW);
- intent.addCategory(android.content.Intent.CATEGORY_DEFAULT);
- intent.addFlags(android.content.Intent.FLAG_ACTIVITY_NEW_TASK);
- intent.addFlags(android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION)
- intent.addFlags(android.content.Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION)
- intent.setDataAndType(getFileUri(context, targetFile), "application/vnd.android.package-archive");
- context.startActivity(intent);
- } else {
- console.log("文件不存在");
- }
- }
- }
主要核心在 application/vnd.android.package-archive 这是打开.apk文件的标识
这里设置有两种方式
- public @NonNull Intent setData(@Nullable Uri data) {
- mData = data;
- mType = null;
- return this;
- }
-
- public @NonNull Intent setDataAndType(@Nullable Uri data, @Nullable String type) {
- mData = data;
- mType = type;
- return this;
- }
-
至于data 和 Uri 可以 参考 android.net.Uri parse(String uriString) | android.content.parseUriInternal(String uri, @UriFlags int flags)
关于这个 mType 就是 android手机中经常看到用xx播放,用xxx浏览器,分享到xxx等.这种菜单
- {".3gp", "video/3gpp"},
- {".apk", "application/vnd.android.package-archive"},
- {".asf", "video/x-ms-asf"},
- {".avi", "video/x-msvideo"},
- {".bin", "application/octet-stream"},
- {".bmp", "image/bmp"},
- {".c", "text/plain"},
- {".class", "application/octet-stream"},
- {".conf", "text/plain"},
- {".cpp", "text/plain"},
- {".doc", "application/msword"},
- {".exe", "application/octet-stream"},
- {".gif", "image/gif"},
- {".gtar", "application/x-gtar"},
- {".gz", "application/x-gzip"},
- {".h", "text/plain"},
- {".htm", "text/html"},
- {".html", "text/html"},
- {".jar", "application/java-archive"},
- {".java", "text/plain"},
- {".jpeg", "image/jpeg"},
- {".jpg", "image/jpeg"},
- {".js", "application/x-javascript"},
- {".log", "text/plain"},
- {".m3u", "audio/x-mpegurl"},
- {".m4a", "audio/mp4a-latm"},
- {".m4b", "audio/mp4a-latm"},
- {".m4p", "audio/mp4a-latm"},
- {".m4u", "video/vnd.mpegurl"},
- {".m4v", "video/x-m4v"},
- {".mov", "video/quicktime"},
- {".mp2", "audio/x-mpeg"},
- {".mp3", "audio/x-mpeg"},
- {".mp4", "video/mp4"},
- {".mpc", "application/vnd.mpohun.certificate"},
- {".mpe", "video/mpeg"},
- {".mpeg", "video/mpeg"},
- {".mpg", "video/mpeg"},
- {".mpg4", "video/mp4"},
- {".mpga", "audio/mpeg"},
- {".msg", "application/vnd.ms-outlook"},
- {".ogg", "audio/ogg"},
- {".pdf", "application/pdf"},
- {".png", "image/png"},
- {".pps", "application/vnd.ms-powerpoint"},
- {".ppt", "application/vnd.ms-powerpoint"},
- {".prop", "text/plain"},
- {".rar", "application/x-rar-compressed"},
- {".rc", "text/plain"},
- {".rmvb", "audio/x-pn-realaudio"},
- {".rtf", "application/rtf"},
- {".sh", "text/plain"},
- {".tar", "application/x-tar"},
- {".tgz", "application/x-compressed"},
- {".txt", "text/plain"},
- {".wav", "audio/x-wav"},
- {".wma", "audio/x-ms-wma"},
- {".wmv", "audio/x-ms-wmv"},
- {".wps", "application/vnd.ms-works"},
- {".xml", "text/xml"},
- {".xml", "text/plain"},
- {".z", "application/x-compress"},
- {".zip", "application/zip"},
- {"", "*/*"}
可以看出打开.apk文件 application/vnd.android.package-archive 是这个这个值就是赋给 data android 标签的 mimeType属性
frameworks/base/packages/PackageInstaller/AndroidManifest.xml
可以看出这里注册的Activity 有data属性
- <activity android:name=".InstallStart"
- android:theme="@android:style/Theme.Translucent.NoTitleBar"
- android:exported="true"
- android:excludeFromRecents="true">
- <intent-filter android:priority="1">
- <action android:name="android.intent.action.VIEW" />
- <action android:name="android.intent.action.INSTALL_PACKAGE" />
- <category android:name="android.intent.category.DEFAULT" />
- <data android:scheme="content" />
- <data android:mimeType="application/vnd.android.package-archive" />
- intent-filter>
- <intent-filter android:priority="1">
- <action android:name="android.intent.action.INSTALL_PACKAGE" />
- <category android:name="android.intent.category.DEFAULT" />
- <data android:scheme="package" />
- <data android:scheme="content" />
- intent-filter>
- <intent-filter android:priority="1">
- <action android:name="android.content.pm.action.CONFIRM_INSTALL" />
- <category android:name="android.intent.category.DEFAULT" />
- intent-filter>
- activity>
到了这里我们知道了当初 context.startActivity(intent) 的拉起来的就是 com.android.packageinstaller.InstallStart
frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java
static final String SCHEME_PACKAGE = "package";
static final String SCHEME_CONTENT = "content";
- Intent nextActivity = new Intent(intent);
- nextActivity.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT| Intent.FLAG_GRANT_READ_URI_PERMISSION);
-
- // The the installation source as the nextActivity thinks this activity is the source, hence
- // set the originating UID and sourceInfo explicitly
- nextActivity.putExtra(PackageInstallerActivity.EXTRA_CALLING_PACKAGE, callingPackage);
- nextActivity.putExtra(PackageInstallerActivity.EXTRA_CALLING_ATTRIBUTION_TAG,callingAttributionTag);
- nextActivity.putExtra(PackageInstallerActivity.EXTRA_ORIGINAL_SOURCE_INFO, sourceInfo);
- nextActivity.putExtra(Intent.EXTRA_ORIGINATING_UID, originatingUid);
-
- if (isSessionInstall) {
- nextActivity.setClass(this, PackageInstallerActivity.class);
- } else {
- Uri packageUri = intent.getData();
-
- if (packageUri != null && packageUri.getScheme().equals(ContentResolver.SCHEME_CONTENT)) {
- // [IMPORTANT] This path is deprecated, but should still work. Only necessary
- // features should be added.
-
- // Copy file to prevent it from being changed underneath this process
- nextActivity.setClass(this, InstallStaging.class);
- } else if (packageUri != null && packageUri.getScheme().equals(PackageInstallerActivity.SCHEME_PACKAGE)) {
- nextActivity.setClass(this, PackageInstallerActivity.class);
- } else {
- Intent result = new Intent();
- result.putExtra(Intent.EXTRA_INSTALL_RESULT,PackageManager.INSTALL_FAILED_INVALID_URI);
- setResult(RESULT_FIRST_USER, result);
-
- nextActivity = null;
- }
- }
-
- if (nextActivity != null) {
- startActivity(nextActivity);
- }
- finish();
可以看出 packageUri.getScheme().equals(ContentResolver.SCHEME_CONTENT) 为 true;所以这里 startActivity(nextActivity); 打开的就是 PackageInstallerActivity