APK安装流程系列文章整体内容如下:
本片文章主要内容如下:
1、PackageManager介绍
2、PackageManager类概述
3、PackageManager与APK安装
4、PackageManager的功能
5、PackageManager常用方法
6、PackageManager中关于"安装"的几个方法
俗话说的好,得中原者,得天下,那么想要了解Android的安装了流程就不得不提及一个重要的类"PackageManager"我们就先来了解这两个类
一、PackageManager介绍
Android系统为我们提供了很多服务的管理类,比如ActivityManager、PowrManager,那么和安装APK有关就是PackageManager了,它负责管理应用程序包,通过它就可以获取应用程序信息。
二、PackageManager类概述
这个类已经5000多行,我们就不详细介绍了,我们来看下这个类
/**
* Class for retrieving various kinds of information related to the application
* packages that are currently installed on the device.
*
* You can find this class through {@link Context#getPackageManager}.
*/
public abstract class PackageManager {
...
}
通过上面代码我们知道这个类是抽象类,那我们来看下注释
PackageManager这个类是检测当前已经安装在当前设备上的应用程序包的信息。你可以调用Context类的getPackageManager()方法来获取PackageManager方法。
三、PackageManager与APK安装
PackageManager是一个实际上管理应用程序安装、卸载和升级的API。当我们安装APK文件时,PackageManager会解析APK包文件和显示确认信息。当我们点击OK按钮后,PackageManager会调用一个叫"InstallPackage"的方法,这个方法有4个参数,也就是uri、installFlags、observer、installPackagename。PackageManager会启动一个叫"package"的servcie服务,现在所有模糊的东西会发生在这个service中。
APK安装流程.png
四、PackageManager的功能
1、安装、卸载应用
2、查询permission相关信息
3、查询Application相关信息(application、activity、receiver、service、provider及相应属性等)
4、查询已安装应用
5、增加、删除permission
6、清除用户数据、缓存、代码等
五、PackageManager常用方法
1、public abstract PackageInfo getPackageInfo(String packageName, int flags)方法:
通过包名获取该包名对应的应用程序的PackageInfo对象
/**
* Retrieve overall information about an application package that is
* installed on the system.
*
* Throws {@link NameNotFoundException} if a package with the given name can
* not be found on the system.
*
* @param packageName The full name (i.e. com.google.apps.contacts) of the
* desired package.
* @param flags Additional option flags. Use any combination of
* {@link #GET_ACTIVITIES}, {@link #GET_GIDS},
* {@link #GET_CONFIGURATIONS}, {@link #GET_INSTRUMENTATION},
* {@link #GET_PERMISSIONS}, {@link #GET_PROVIDERS},
* {@link #GET_RECEIVERS}, {@link #GET_SERVICES},
* {@link #GET_SIGNATURES}, {@link #GET_UNINSTALLED_PACKAGES} to
* modify the data returned.
* @return Returns a PackageInfo object containing information about the
* package. If flag GET_UNINSTALLED_PACKAGES is set and if the
* package is not found in the list of installed applications, the
* package information is retrieved from the list of uninstalled
* applications (which includes installed applications as well as
* applications with data directory i.e. applications which had been
* deleted with {@code DONT_DELETE_DATA} flag set).
* @see #GET_ACTIVITIES
* @see #GET_GIDS
* @see #GET_CONFIGURATIONS
* @see #GET_INSTRUMENTATION
* @see #GET_PERMISSIONS
* @see #GET_PROVIDERS
* @see #GET_RECEIVERS
* @see #GET_SERVICES
* @see #GET_SIGNATURES
* @see #GET_UNINSTALLED_PACKAGES
*/
public abstract PackageInfo getPackageInfo(String packageName, int flags)
throws NameNotFoundException;
先翻译一下注释:
检索出有关系统上安装应用程序包的总体信息
关于PackageInfo这各类请参考APK安装流程详解1——有关"安装ing"的实体类概述
。它表示检索有关系统上安装的应用程序包的总体信息。
2、public abstract String[] currentToCanonicalPackageNames(String[] names)方法:
/**
* Map from the current package names in use on the device to whatever
* the current canonical name of that package is.
* @param names Array of current names to be mapped.
* @return Returns an array of the same size as the original, containing
* the canonical name for each package.
*/
public abstract String[] currentToCanonicalPackageNames(String[] names);
简单翻译注释如下:
从设备上使用当前包名映射到该软件包名的当前规范名称。
入参params names 表示要映射的当前名称的数组
出参return 表示与原始数组大小相同的数组,其中包含每个包的规范名称
如果修改包名会用到,没有修改过包名一般不会用到
3、public abstract String[] canonicalToCurrentPackageNames(String[] names)方法:
主要是相对于上面的方法
/**
* Map from a packages canonical name to the current name in use on the device.
* @param names Array of new names to be mapped.
* @return Returns an array of the same size as the original, containing
* the current name for each package.
*/
public abstract String[] canonicalToCurrentPackageNames(String[] names);
简单翻译注释如下:
将软件包规范名称映射到设备上正在使用的当前名称。
入参params names 表示要映射的新名称数组
出参return 表示返回与原始数组大小相同的数组,其中包含每个包的当前名称。
其中canonicalToCurrentPackageNames()和currentToCanonicalPackageNames()方法是相反的两个方法
4、public abstract Intent getLaunchIntentForPackage(String packageName)方法:
获取一个应用程序的Lauch的Intent
/**
* Returns a "good" intent to launch a front-door activity in a package.
* This is used, for example, to implement an "open" button when browsing
* through packages. The current implementation looks first for a main
* activity in the category {@link Intent#CATEGORY_INFO}, and next for a
* main activity in the category {@link Intent#CATEGORY_LAUNCHER}. Returns
* null
if neither are found.
*
* @param packageName The name of the package to inspect.
*
* @return A fully-qualified {@link Intent} that can be used to launch the
* main activity in the package. Returns null
if the package
* does not contain such an activity, or if packageName is not
* recognized.
*/
public abstract Intent getLaunchIntentForPackage(String packageName);
返回一个"包"中的"入口"Activity的Intent,例如,这是类似于在浏览包的"打开"按钮。这个当前的安装启动第一步在category(CATEGORY_INFO)中寻找main Activity,然后在category(CATEGORY_LAUNCHER)寻找main Activity。如果找不到就返回null。
入参是包名
5、public abstract Intent getLeanbackLaunchIntentForPackage(String packageName)方法:
获取一个TV应用的Leanback的Intent
/**
* Return a "good" intent to launch a front-door Leanback activity in a
* package, for use for example to implement an "open" button when browsing
* through packages. The current implementation will look for a main
* activity in the category {@link * return null if no main leanback activities are found.
*
* Throws {@link NameNotFoundException} if a package with the given name
* cannot be found on the system.
*
* @param packageName The name of the package to inspect.
* @return Returns either a fully-qualified Intent that can be used to launch
* the main Leanback activity in the package, or null if the package
* does not contain such an activity.
*/
public abstract Intent getLeanbackLaunchIntentForPackage(String packageName);
Leanback activity一般在TV上使用的比较多,上面这个方法返回的Intent的一般在AndroidManifest如下:
android:name="com.example.android.TvActivity"
android:label="@string/app_name"
android:theme="@style/Theme.Leanback">
其实就是返回的是com.example.android.TvActivity的打开Intent
翻译注释如下:
返回一个"合适的"Intent,这个Intent是打开LeanbackActivity的入口Intent。例如,类似于在浏览包的"打开"按钮。这个将找匹配CATEGORY_LEANBACK_LAUNCHER的Activity。如果没有找到则返回null。
6、public abstract int[] getPackageGids(String packageName)方法:
获取相应包的Group ids
/**
* Return an array of all of the POSIX secondary group IDs that have been
* assigned to the given package.
*
* Note that the same package may have different GIDs under different
* {@link UserHandle} on the same device.
*
* @param packageName The full name (i.e. com.google.apps.contacts) of the
* desired package.
* @return Returns an int array of the assigned GIDs, or null if there are
* none.
* @throws NameNotFoundException if a package with the given name cannot be
* found on the system.
*/
public abstract int[] getPackageGids(String packageName)
throws NameNotFoundException;
翻译注释如下:
返回已分配给包的所有的POSIX辅助组ID的数组
请注意,相同的包可能会有不同的GID, 因为可能存在在同一个设备开启了不同的"用户模式“下
入参params packageName 是全包名
出参 表示 返回应用程序对应的GID的int 数组,如果没有应用程序,则返回null。
7、public abstract int[] getPackageUid(String packageName)方法:
获取相应包的UID
代码在PackageManager.java2113行
/**
* Return the UID associated with the given package name.
*
* Note that the same package will have different UIDs under different
* {@link UserHandle} on the same device.
*
* @param packageName The full name (i.e. com.google.apps.contacts) of the
* desired package.
* @return Returns an integer UID who owns the given package name.
* @throws NameNotFoundException if a package with the given name can not be
* found on the system.
*/
public abstract int getPackageUid(String packageName, @PackageInfoFlags int flags)
throws NameNotFoundException;
翻译注释如下:
返回与给定包名的对应的UID
请注意,相同的包可能会有不同的UID, 因为可能存在在同一个设备开启了不同的"用户模式“下
入参params packageName 是全包名
出参 表示 返回给定包名的int 型的UID
8、 public abstract PermissionInfo getPermissionInfo(String name, int flags)方法:
根