想了解android–PackageManager.getInstalledPackages()返回空列表的新动态吗?本文将为您提供详细的信息,我们还将为您解答关于androidgettext返回类型
想了解android – PackageManager.getInstalledPackages()返回空列表的新动态吗?本文将为您提供详细的信息,我们还将为您解答关于android gettext返回类型的相关问题,此外,我们还将为您介绍关于Android APK应用安装原理解析之AndroidManifest使用PackageParser.parserPackage原理分析、Android Framework 分析 ---3PackageManager 分析、Android O PackageInstaller 解析、Android PackageManager 查询、安装、读取 meta 等用法的新知识。
本文目录一览:- android – PackageManager.getInstalledPackages()返回空列表(android gettext返回类型)
- Android APK应用安装原理解析之AndroidManifest使用PackageParser.parserPackage原理分析
- Android Framework 分析 ---3PackageManager 分析
- Android O PackageInstaller 解析
- Android PackageManager 查询、安装、读取 meta 等用法
android – PackageManager.getInstalledPackages()返回空列表(android gettext返回类型)
使用PackageManager.getInstalledPackages()方法时,我遇到了一个非常奇怪的情况.我第一次启动活动时,会获得所有已安装软件包的有效列表.但是第二次启动我的活动时,我得到一个空列表……可能是什么导致了这个?
我使用此代码获取列表:
列出pkgList = getPackageManager().getInstalledPackages(PackageManager.GET_ACTIVITIES);
我正在构建1.6 SDK,兼容1.5
提前感谢任何建议/帮助…我对原因感到困惑,不能想到我做错了什么.
解决方法:
由于某种原因,可能需要在主应用程序线程上调用PackageManager.我没有尝试过使用AsyncTask.
更新2018-03-26:PackageManager通常可以在后台线程上调用,特别是getInstalledPackages().
Android APK应用安装原理解析之AndroidManifest使用PackageParser.parserPackage原理分析
本文实例讲述了Android APK应用安装之AndroidManifest使用PackageParser.parserPackage原理。分享给大家供大家参考,具体如下:
Android 安装一个APK的时候首先会解析APK,这里要做很多事情,其中一个事情就是解析Manifest.xml文件,并将所有APK的Manifest封装到各种对象中并保存在内存当中
解析Manifest的类是非常重要的,该类就是frameworks\base\core\java\android\content\pm\PackageParser
PackageManagerService会调用PackageParser.parserPackage方法来解析APK清单,下面开始分析PackageParser的实现:
PackageParser是使用的XMLPullParser工具来对XML进行解析的,然后分别通过android.content.pm下各种xxxInfo类来进行封装:
public Package parsePackage(File sourceFile,String destCodePath,displayMetrics metrics,int flags) { //最后要跑出的解析错误信息 mParseError = PackageManager.INSTALL_SUCCEEDED; //获得要解析的文件的路径 marchiveSourcePath = sourceFile.getPath(); //如果要解析的不是文件类型就跳过并且返回该方法 if (!sourceFile.isFile()) { Log.w(TAG,"Skipping dir: " + marchiveSourcePath); //更新错误信息 mParseError = PackageManager.INSTALL_PARSE_Failed_NOT_APK; return null; } //如果文件不是以.apk结尾并且flag没有确定一定是APK,那么也返回 if (!isPackageFilename(sourceFile.getName()) && (flags&PARSE_MUST_BE_APK) != 0) { if ((flags&PARSE_IS_SYstem) == 0) { // We expect to have non-.apk files in the system dir,// so don't warn about them. Log.w(TAG,"Skipping non-package file: " + marchiveSourcePath); } //更新错误信息 mParseError = PackageManager.INSTALL_PARSE_Failed_NOT_APK; return null; } if ((flags&PARSE_CHATTY) != 0 && Config.LOGD) Log.d( TAG,"Scanning package: " + marchiveSourcePath); XmlResourceParser parser = null; AssetManager assmgr = null; boolean assetError = true; try { assmgr = new AssetManager(); //将一个文件添加到AssetManager中并返回一个唯一标识 int cookie = assmgr.addAssetPath(marchiveSourcePath); if(cookie != 0) { //通过标识去AssetManager中找到标识对应资源中的Manifest清单文件,并返回一个XML的解析器 parser = assmgr.openXmlResourceParser(cookie,"AndroidManifest.xml"); //走到这里证明一切顺利 assetError = false; } else { Log.w(TAG,"Failed adding asset path:"+marchiveSourcePath); } } catch (Exception e) { Log.w(TAG,"Unable to read AndroidManifest.xml of " + marchiveSourcePath,e); } if(assetError) { if (assmgr != null) assmgr.close(); mParseError = PackageManager.INSTALL_PARSE_Failed_BAD_MANIFEST; return null; } String[] errorText = new String[1]; Package pkg = null; Exception errorException = null; try { // XXXX todo: need to figure out correct configuration. Resources res = new Resources(assmgr,metrics,null); //这个是真正在解析的package的方法,是private method pkg = parsePackage(res,parser,flags,errorText); } catch (Exception e) { errorException = e; mParseError = PackageManager.INSTALL_PARSE_Failed_UNEXPECTED_EXCEPTION; } if (pkg == null) { if (errorException != null) { Log.w(TAG,marchiveSourcePath,errorException); } else { Log.w(TAG,marchiveSourcePath + " (at " + parser.getPositionDescription() + "): " + errorText[0]); } parser.close(); assmgr.close(); if (mParseError == PackageManager.INSTALL_SUCCEEDED) { mParseError = PackageManager.INSTALL_PARSE_Failed_MANIFEST_MALFORMED; } return null; }
parserPackage调用了重载的另外一个parserPackage
private Package parsePackage( Resources res,XmlResourceParser parser,int flags,String[] outError) throws XmlPullParserException,IOException { AttributeSet attrs = parser; //每次调用这个方法时候清空这些变量 mParseInstrumentationArgs = null; mParseActivityArgs = null; mParseServiceArgs = null; mParseProviderArgs = null; //这里调用这个方法获得包名 String pkgName = parsePackageName(parser,attrs,outError); if (pkgName == null) { mParseError = PackageManager.INSTALL_PARSE_Failed_BAD_PACKAGE_NAME; return null; } int type; final Package pkg = new Package(pkgName); boolean foundApp = false; //从资源里获得AndroidManifest的数组 TypedArray sa = res.obtainAttributes(attrs,com.android.internal.R.styleable.AndroidManifest); //继续挖掘出版本号 pkg.mVersionCode = sa.getInteger( com.android.internal.R.styleable.AndroidManifest_versionCode,0); //获取版本名 pkg.mVersionName = sa.getNonConfigurationString( com.android.internal.R.styleable.AndroidManifest_versionName,0); if (pkg.mVersionName != null) { pkg.mVersionName = pkg.mVersionName.intern(); } //获得sharedUserId String str = sa.getNonConfigurationString( com.android.internal.R.styleable.AndroidManifest_sharedUserId,0); if (str != null && str.length() > 0) { //验证包名是否符合规则 String nameError = validateName(str,true); if (nameError != null && !"android".equals(pkgName)) { outError[0] = "<manifest> specifies bad sharedUserId name \"" + str + "\": " + nameError; mParseError = PackageManager.INSTALL_PARSE_Failed_BAD_SHARED_USER_ID; return null; } pkg.mSharedUserId = str.intern(); pkg.mSharedUserLabel = sa.getResourceId( com.android.internal.R.styleable.AndroidManifest_sharedUserLabel,0); } sa.recycle(); //安装的位置 pkg.installLocation = sa.getInteger( com.android.internal.R.styleable.AndroidManifest_installLocation,PARSE_DEFAULT_INSTALL_LOCATION); // Resource boolean are -1,so 1 means we don't kNow the value. int supportsSmallScreens = 1; int supportsnormalScreens = 1; int supportsLargeScreens = 1; int resizeable = 1; int anyDensity = 1; int outerDepth = parser.getDepth(); //关键时刻到了,真正的开始解析了 while ((type=parser.next()) != parser.END_DOCUMENT && (type != parser.END_TAG || parser.getDepth() > outerDepth)) { if (type == parser.END_TAG || type == parser.TEXT) { continue; } String tagName = parser.getName(); if (tagName.equals("application")) { if (foundApp) { if (RIGID_PARSER) { outError[0] = "<manifest> has more than one <application>"; mParseError = PackageManager.INSTALL_PARSE_Failed_MANIFEST_MALFORMED; return null; } else { Log.w(TAG,"<manifest> has more than one <application>"); XmlUtils.skipCurrentTag(parser); continue; } } foundApp = true; if (!parseApplication(pkg,res,outError)) { return null; } } else if (tagName.equals("permission-group")) { if (parsePermissionGroup(pkg,outError) == null) { return null; } } else if (tagName.equals("permission")) { if (parsePermission(pkg,outError) == null) { return null; } } else if (tagName.equals("permission-tree")) { if (parsePermissionTree(pkg,outError) == null) { return null; } } else if (tagName.equals("uses-permission")) { sa = res.obtainAttributes(attrs,com.android.internal.R.styleable.AndroidManifestUsesPermission); // Note: don't allow this value to be a reference to a resource // that may change. String name = sa.getNonResourceString( com.android.internal.R.styleable.AndroidManifestUsesPermission_name); sa.recycle(); ................................................... ................................................... ...................................................篇幅有限
这里分别把每种不同的element用不同的小方法去解析,他们的调用顺序是:
这些小方法里其实还是有很多小技巧的,有兴趣的话可以细细品位
更多关于Android相关内容感兴趣的读者可查看本站专题:《Android开发入门与进阶教程》、《Android调试技巧与常见问题解决方法汇总》、《Android基本组件用法总结》、《Android视图View技巧总结》、《Android布局layout技巧总结》及《Android控件用法总结》
希望本文所述对大家Android程序设计有所帮助。
Android Framework 分析 ---3PackageManager 分析
在 windowphone,ios 和 android 中到目前为止,还是 android 的市场份额最大。个人认为除了 google 开源外,广大开发者早就了 android 的霸主地位。各位兄弟姐妹开发出各种各样的 apk,才组成 android 的广阔天下。本篇主要分析一下 android 系统是针对处理这些 apk 的,主要涉及到 pm 这块的代码。分析这种底层服务,最好从 android 的开启启动流程中开始分析。因为这样才能更清楚的了解服务的启动流程。
1. 在 SystemServer.java 中启动 PM
android 开机启动后加载的第一个 java 的程序就是 SystemServer, 在包含 android 系统的最主要的一些底层服务。在 4.4kk 之前都是建一个 Thread 线程来启动。4.4KK 的启动机制就变了,具体后续的文章会讲解。
Installer installer = null;
Slog.i(TAG, "Waiting for installd to be ready.");
installer = new Installer();
installer.ping();
pm = PackageManagerService.main(context, installer,
factoryTest != SystemServer.FACTORY_TEST_OFF,
onlyCore);
boolean firstBoot = false;
try {
firstBoot = pm.isFirstBoot();
} catch (RemoteException e) {
}
public static final IPackageManager main(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
PackageManagerService m = new PackageManagerService(context, installer,
factoryTest, onlyCore);
ServiceManager.addService("package", m);
return m;
}
在 systemServer 中初始化了 Installer,并将它传入 PackageManagerService.main () 中。在 main 函数中将 pm 添加到 ServiceManager 中,供开发者调用。
2.PackageManagerService 启动安装分析
启动 PackageManagerService 后,主要完成以下几个步骤
2.1. 初始化 PackageSetting,设置 sharedUserID
mSettings = new Settings(context);
mSettings.addSharedUserLPw("android.uid.system",
Process.SYSTEM_UID, ApplicationInfo.FLAG_SYSTEM);
mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID, ApplicationInfo.FLAG_SYSTEM);
2.2. 获取屏幕参数:
WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
Display d = wm.getDefaultDisplay();
d.getMetrics(mMetrics);
2.3. 使用 HandlerThread 开启 packagemanager 工作线程和初始化 app 目录
mHandlerThread.start();
mHandler = new PackageHandler(mHandlerThread.getLooper());
File dataDir = Environment.getDataDirectory();
mAppDataDir = new File(dataDir, "data");
mAppInstallDir = new File(dataDir, "app");
mAppLibInstallDir = new File(dataDir, "app-lib");
mAsecInternalPath = new File(dataDir, "app-asec").getPath();
mUserAppDataDir = new File(dataDir, "user");
mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
2.4. 加载 Framework 的主要 jar 和 BOOTCLASSPATH
mFrameworkDir = new File(Environment.getRootDirectory(), "framework");
mDalvikCacheDir = new File(dataDir, "dalvik-cache");
boolean didDexOpt = false;
/**
* Out of paranoia, ensure that everything in the boot class
* path has been dexed.
*/
String bootClassPath = System.getProperty("java.boot.class.path");
2.5. 安装 system/app,vendor/app 和 data/app 目录下 apk
// Collect all system packages.
mSystemAppDir = new File(Environment.getRootDirectory(), "app");
mSystemInstallObserver = new AppDirObserver(
mSystemAppDir.getPath(), OBSERVER_EVENTS, true);
mSystemInstallObserver.startWatching();
scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
// Collect all vendor packages.
mVendorAppDir = new File("/vendor/app");
mVendorInstallObserver = new AppDirObserver(
mVendorAppDir.getPath(), OBSERVER_EVENTS, true);
mVendorInstallObserver.startWatching();
scanDirLI(mVendorAppDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
......
mAppInstallObserver = new AppDirObserver(
mAppInstallDir.getPath(), OBSERVER_EVENTS, false);
mAppInstallObserver.startWatching();
scanDirLI(mAppInstallDir, 0, scanMode, 0);
其中具体如果安装代码在 scanDirLI()函数,最终调用 scanPackageLI()进行安装。在安装过程中会搜集 ApplicationInfo 和 ActivityInfo 信息,比较签名,匹配本地 so 的目录。
具体细节参看 PackageManagerService.java 中的
private PackageParser.Package scanPackageLI(PackageParser.Package pkg,int parseFlags, int scanMode, long currentTime, UserHandle user) {
函数。
3. 在 Activity 使用 PackageManger 的分析
我们在应用经常通过
PackageManager pm = this.getPackageManager () 来获取 pm。这部分主要从它的来源来深入分析。
由于我们在 Activity 中使用 this 来获取 pm,很容易想到到 context 类里去寻找实现。
/** Return PackageManager instance to find global package information. */
public abstract PackageManager getPackageManager();
但是 context 是虚函数,因此要找到它的实现,由于 context 的实现采用 设计模式里面的 " 桥接模式 '' 因此很容易想到从 contextImpl.java 中寻找实现。
果然找到。
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;
}
从代码上看获取 IPackageManager,还是需要从 ActivityThread 中获取。我在 Activity 里面获取吗出现在 ActivityThread 也不意外。
那我们就看看他是怎么实现的
public static IPackageManager getPackageManager() {
if (sPackageManager != null) {
//Slog.v("PackageManager", "returning cur default = " + sPackageManager);
return sPackageManager;
}
IBinder b = ServiceManager.getService("package");
//Slog.v("PackageManager", "default service binder = " + b);
sPackageManager = IPackageManager.Stub.asInterface(b);
//Slog.v("PackageManager", "default service = " + sPackageManager);
return sPackageManager;
}
原来是通过 ServiceManager.getService ("package"). 从上你们的代码知道,这句其实就是获取 PackageManagerService 并赋给 IBinder ,成为一个 binder 对象。
通过 asInterface()函数,通过 binder 对象获取接口类 IPackageManager 的实例。并返回回去。
if (pm != null) {
// Doesn''t matter if we make more than one instance.
return (mPackageManager = new ApplicationPackageManager(this, pm));
}
在接着同 ApplicationPackageManager 创建 PackageManager 对象。到此我们在 Activity 中就可以使用 pm 这个对象操作系统中的各种包。
4.Android 系统中 PackageManager 的关键类和 UML 的类图。
在 pm 中主要涉及的类和路径如下:
frameworks\base\services\java\com\android\server\pm\PackageManagerService.java 和 其他文件
frameworks\base\core\java\android\content\pm\IPackageManager.aidl
frameworks\base\core\java\android\app\ActivityThread.java ,context.java ,contextimpl.java
frameworks\base\core\java\android\content\pm\PackageManager.java
版权声明:本文为博主原创文章,未经博主允许不得转载。
Android O PackageInstaller 解析
Android O 8.0
1.src\com\android\packageinstaller\permission\mode\PermissionGroups.java
@Override
public List<PermissionGroup> loadInBackground() {
ArraySet<String> launcherPkgs = Utils.getLauncherPackages(getContext());
PermissionApps.PmCache pmCache = new PermissionApps.PmCache(
getContext().getPackageManager());
List<PermissionGroup> groups = new ArrayList<>();
Set<String> seenPermissions = new ArraySet<>();
PackageManager packageManager = getContext().getPackageManager();
List<PermissionGroupInfo> groupInfos = packageManager.getAllPermissionGroups(0);
for (PermissionGroupInfo groupInfo : groupInfos) {
// Mare sure we respond to cancellation.
if (isLoadInBackgroundCanceled()) {
return Collections.emptyList();
}
// 得到权限组里的所有权限
// Get the permissions in this group.
final List<PermissionInfo> groupPermissions;
try {
groupPermissions = packageManager.queryPermissionsByGroup(groupInfo.name, 0);
} catch (PackageManager.NameNotFoundException e) {
continue;
}
boolean hasRuntimePermissions = false;
// 查看某个权限组是否含有运行时权限
// Cache seen permissions and see if group has runtime permissions.
for (PermissionInfo groupPermission : groupPermissions) {
seenPermissions.add(groupPermission.name);
if ((groupPermission.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE)
== PermissionInfo.PROTECTION_DANGEROUS
&& (groupPermission.flags & PermissionInfo.FLAG_INSTALLED) != 0
&& (groupPermission.flags & PermissionInfo.FLAG_REMOVED) == 0) {
hasRuntimePermissions = true;
}
}
// 权限组里没有运行时权限,我们不感兴趣,继续循环查询
// No runtime permissions - not interesting for us.
if (!hasRuntimePermissions) {
continue;
}
// 如果权限组里含有运行时权限,则继续往下执行
// 获取权限组的label
CharSequence label = loadItemInfoLabel(groupInfo);
Drawable icon = loadItemInfoIcon(groupInfo);
// 根据权限组 新建 PermissionApps 对象
PermissionApps permApps = new PermissionApps(getContext(), groupInfo.name, null,
pmCache);
permApps.refreshSync();
// 创建 PermissionGroup 对象
// Create the group and add to the list.
PermissionGroup group = new PermissionGroup(groupInfo.name,
groupInfo.packageName, label, icon, permApps.getTotalCount(launcherPkgs),
permApps.getGrantedCount(launcherPkgs));
groups.add(group);
}
// 获取所有的安装包权限
// Make sure we add groups for lone runtime permissions.
List<PackageInfo> installedPackages = getContext().getPackageManager()
.getInstalledPackages(PackageManager.GET_PERMISSIONS);
// We will filter out permissions that no package requests.
Set<String> requestedPermissions = new ArraySet<>();
for (PackageInfo installedPackage : installedPackages) {
if (installedPackage.requestedPermissions == null) {
continue;
}
// 将安装包请求的权限加入到 列表中
for (String requestedPermission : installedPackage.requestedPermissions) {
requestedPermissions.add(requestedPermission);
}
}
for (PackageInfo installedPackage : installedPackages) {
if (installedPackage.permissions == null) {
continue;
}
// 自定义的权限
for (PermissionInfo permissionInfo : installedPackage.permissions) {
// If we have handled this permission, no more work to do.
if (!seenPermissions.add(permissionInfo.name)) {
continue;
}
// 关心的是 运行时权限
// We care only about installed runtime permissions.
if ((permissionInfo.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE)
!= PermissionInfo.PROTECTION_DANGEROUS
|| (permissionInfo.flags & PermissionInfo.FLAG_INSTALLED) == 0) {
continue;
}
// 没有app使用那个自定义的权限
// If no app uses this permission,
if (!requestedPermissions.contains(permissionInfo.name)) {
continue;
}
CharSequence label = loadItemInfoLabel(permissionInfo);
Drawable icon = loadItemInfoIcon(permissionInfo);
PermissionApps permApps = new PermissionApps(getContext(), permissionInfo.name,
null, pmCache);
permApps.refreshSync();
// Create the group and add to the list.
PermissionGroup group = new PermissionGroup(permissionInfo.name,
permissionInfo.packageName, label, icon,
permApps.getTotalCount(launcherPkgs),
permApps.getGrantedCount(launcherPkgs));
groups.add(group);
}
}
Collections.sort(groups);
return groups;
}
2.PermissionApps.java
/**
* Refresh the state and do not return until it finishes. Should not be called while an {@link
* #refresh async referesh} is in progress.
*/
public void refreshSync() {
mSkipUi = true;
createMap(loadPermissionApps());
}
3.
src\com\android\packageinstaller\permission\utils\EventLogger.java
/**
* For each permission there are four events. The events are in the order of
* #ALL_DANGEROUS_PERMISSIONS. The four events per permission are (in that order): "requested",
* "granted", "denied", and "revoked".
*/
public class EventLogger {
private static final String LOG_TAG = EventLogger.class.getSimpleName();
/** All dangerous permission names in the same order as the events in MetricsEvent */
private static final List<String> ALL_DANGEROUS_PERMISSIONS = Arrays.asList(
Manifest.permission.READ_CALENDAR,
Manifest.permission.WRITE_CALENDAR,
Manifest.permission.CAMERA,
Manifest.permission.READ_CONTACTS,
Manifest.permission.WRITE_CONTACTS,
Manifest.permission.GET_ACCOUNTS,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.RECORD_AUDIO,
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.CALL_PHONE,
Manifest.permission.READ_CALL_LOG,
Manifest.permission.WRITE_CALL_LOG,
Manifest.permission.ADD_VOICEMAIL,
Manifest.permission.USE_SIP,
Manifest.permission.PROCESS_OUTGOING_CALLS,
Manifest.permission.READ_CELL_BROADCASTS,
Manifest.permission.BODY_SENSORS,
Manifest.permission.SEND_SMS,
Manifest.permission.RECEIVE_SMS,
Manifest.permission.READ_SMS,
Manifest.permission.RECEIVE_WAP_PUSH,
Manifest.permission.RECEIVE_MMS,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_PHONE_NUMBERS,
Manifest.permission.ANSWER_PHONE_CALLS,
Manifest.permission.ACCEPT_HANDOVER);
private static final List<String> ALL_APPOP_PERMISSIONS = Arrays.asList(
Manifest.permission.ACCESS_NOTIFICATIONS,
Manifest.permission.SYSTEM_ALERT_WINDOW,
Manifest.permission.WRITE_SETTINGS,
Manifest.permission.REQUEST_INSTALL_PACKAGES);
......
}
4.
src\com\android\packageinstaller\permission\utils\Utils.java
public static final String OS_PKG = "android";
public static final String[] MODERN_PERMISSION_GROUPS = { // 目前平台支持的权限组
Manifest.permission_group.CALENDAR,
Manifest.permission_group.CAMERA,
Manifest.permission_group.CONTACTS,
Manifest.permission_group.LOCATION,
Manifest.permission_group.SENSORS,
Manifest.permission_group.SMS,
Manifest.permission_group.PHONE,
Manifest.permission_group.MICROPHONE,
Manifest.permission_group.STORAGE
};
private static final Intent LAUNCHER_INTENT = new Intent(Intent.ACTION_MAIN, null)
.addCategory(Intent.CATEGORY_LAUNCHER);
5.
public class DeviceUtils {
public static boolean isTelevision(Context context) { // 电视
int uiMode = context.getResources().getConfiguration().uiMode;
return (uiMode & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_TELEVISION;
}
public static boolean isWear(final Context context) {// 穿戴设备
return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH);
}
public static boolean isAuto(Context context) {// 汽车、自动设备
return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
}
}
Android PackageManager 查询、安装、读取 meta 等用法
一、查询手机上的所有 app
首先建立一个 Model
class ApplicationInfo {
CharSequence title;
Intent intent;
Drawable icon;
boolean filtered;
//启动app初始化设置方式一
final void setActivity(ComponentName className, int launchFlags) {
intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setComponent(className);
intent.setFlags(launchFlags);
}
//直接获得启动器,启动初始化方式二
final void setActivity(Context cxt,String packageName, int launchFlags) {
intent = cxt.getPackageManager().getLaunchIntentForPackage(packageName);
intent.setFlags(launchFlags);
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof ApplicationInfo)) {
return false;
}
ApplicationInfo that = (ApplicationInfo) o;
return title.equals(that.title) &&
intent.getComponent().getClassName().equals(
that.intent.getComponent().getClassName());
}
@Override
public int hashCode() {
int result;
result = (title != null ? title.hashCode() : 0);
final String name = intent.getComponent().getClassName();
result = 31 * result + (name != null ? name.hashCode() : 0);
return result;
}
}
第一种方式:
找到的代码只能查询到系统的 app,不能查询到全部 app,代码如下:
private void loadAppVerion1() {
PackageManager manager = getPackageManager();
Intent mainIntent = new Intent(Intent.ACTION_MAIN, null); //可能出现误差,因为Action任何Activity都可以相同
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
final List<ResolveInfo> apps = manager.queryIntentActivities(mainIntent, 0);
Collections.sort(apps, new ResolveInfo.DisplayNameComparator(manager));
if (apps != null) {
final int count = apps.size();
if (mApplications == null) {
mApplications = new ArrayList<ApplicationInfo>(count);
}
mApplications.clear();
for (int i = 0; i < count; i++) {
ApplicationInfo application = new ApplicationInfo();
ResolveInfo info = apps.get(i);
application.title = info.loadLabel(manager);
application.setActivity(new ComponentName(
info.activityInfo.applicationInfo.packageName,
info.activityInfo.name),
Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
application.icon = info.activityInfo.loadIcon(manager);
mApplications.add(application);
}
}
}
第二种方式可获得所有的 app(推荐):
private void loadAppVerion2()
{
PackageManager packageManager = this.getPackageManager();
List<PackageInfo> packageInfoList = packageManager.getInstalledPackages(PackageManager.GET_ACTIVITIES);
if(packageInfoList!=null)
{
if (mApplications == null)
{
mApplications = new ArrayList<ApplicationInfo>();
}
mApplications.clear();
for (PackageInfo packageInfo : packageInfoList)
{
ApplicationInfo application = new ApplicationInfo();
if(android.os.Build.VERSION.SDK_INT>=9)
{
application.icon = packageInfo.applicationInfo.loadLogo(packageManager);
}else{
application.icon = packageInfo.applicationInfo.loadIcon(packageManager);
}
application.title = packageInfo.applicationInfo.loadLabel(packageManager);
String packageName = packageInfo.packageName;
application.setActivity(this, packageName,Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
mApplications.add(application);
}
}
}
二、下面是关于 app 的安装
// 安装APK程序代码
private void openArcInStall(File file) {//传入app的下载路径构造的File文件即可
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setAction(android.content.Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file),"application/vnd.android.package-archive");
startActivity(intent);
}
1. 查找可以分享文本的 app
/**
* 查询手机内所有支持分享的应用
* @param context
* @return
*/
public static List<ResolveInfo> getShareApps(Context context){
List<ResolveInfo> mApps = new ArrayList<ResolveInfo>();
Intent intent=new Intent(Intent.ACTION_SEND,null);
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setType("text/plain");
PackageManager pManager = context.getPackageManager();
mApps = pManager.queryIntentActivities(intent,PackageManager.COMPONENT_ENABLED_STATE_DEFAULT);
return mApps;
}
2. 查询最近打开过的应用(任务栈)
private void searchRecents()
{
final PackageManager manager = getPackageManager();
final ActivityManager tasksManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
final List<ActivityManager.RecentTaskInfo> recentTasks = tasksManager.getRecentTasks(4, 0);
final int count = recentTasks.size();
final ArrayList<ApplicationInfo> recents = new ArrayList<ApplicationInfo>();
}
三、读取 Meta 信息
1> application
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<meta-data
android:name="application_meta_data"
android:value="application_meta_data_value" /> <!--可以关联资源ID, 支持多种数据类型 -->
ApplicationInfo info = null;
try {
info = getPackageManager()
.getApplicationInfo(getPackageName(), PackageManager.GET_META_DATA);
} catch (NameNotFoundException e) {
e.printStackTrace();
}
Log.v(TAG, "application meta data value:" + info.metaData.getString("application_meta_data"));
2> Activity
<activity
android:name="fyc.app.testandroid.MainActivity" >
<meta-data
android:name="activity_meta_data"
android:value="activity_meta_data_value" />
</activity>
ActivityInfo info = null;
try {
info = getPackageManager()
.getActivityInfo(getComponentName(), PackageManager.GET_META_DATA);
} catch (NameNotFoundException e) {
e.printStackTrace();
}
Log.v(TAG, "activity meta data value:" + info.metaData.getString("activity_meta_data"));
3> Service
<service android:name="fyc.app.testandroid.MyService" >
<meta-data
android:name="service_meta_data"
android:value="service_meta_data_value" />
</service>
ServiceInfo info = null;
try {
info = getPackageManager()
.getServiceInfo(new ComponentName(this, MyService.class), PackageManager.GET_META_DATA);
} catch (NameNotFoundException e) {
e.printStackTrace();
}
Log.v(TAG, "service meta data value:" + info.metaData.getString("service_meta_data"));
4> BroadcastReceiver
<receiver android:name="fyc.app.testandroid.MyReceiver" >
<meta-data
android:name="receiver_meta_data"
android:value="receiver_meta_data_value" />
</receiver>
ActivityInfo info = null;
try {
info = getPackageManager()
.getReceiverInfo(new ComponentName(this, MyReceiver.class), PackageManager.GET_META_DATA);
} catch (NameNotFoundException e) {
e.printStackTrace();
}
Log.v(TAG, "receiver meta data value:" + info.metaData.getString("receiver_meta_data"));
关于android – PackageManager.getInstalledPackages()返回空列表和android gettext返回类型的问题我们已经讲解完毕,感谢您的阅读,如果还想了解更多关于Android APK应用安装原理解析之AndroidManifest使用PackageParser.parserPackage原理分析、Android Framework 分析 ---3PackageManager 分析、Android O PackageInstaller 解析、Android PackageManager 查询、安装、读取 meta 等用法等相关内容,可以在本站寻找。
本文标签: