网上能找到很多关于本文主题的代码——Android启动一个只知道包名的APP,那我为什么还要在此啰嗦一下呢?
你可能参考网上各种方式都打不开APP,还不是很清楚原因,那么我这里就只是做一个提醒吧,害怕你忘了或者没注意到过。
我们知道,在TV上开发的APP和在移动端的有一些差别。
- 一个应用运行在TV设备中,必须在它的manifest中定义一个启动activity,用intent filter包含CATEGORY_LEANBACK_LAUNCHER。
- 这个filter表明你的应用是在TV上可用,并且为Google Play上发布TV应用所必须。
- 定义这个intent也意味着点击主屏幕的应用图标时,就是打开的这个activity。
所以,你要启动一个只知道包名的APP,在TV上和移动端还是有些差别的,敲重点了。
1、我们先抛弃如下方式:
Intent intent = context.getPackageManager().getLaunchIntentForPackage(packageName);
context.startActivity(intent);
因为它可能会返回为空,高版本Android使用它会有缺陷的。
2、我们常用方式,即移动端的正确解锁方式:
PackageManager packageManager = context.getPackageManager();
Intent resolveIntent = new Intent(Intent.ACTION_MAIN, null);
resolveIntent.addCategory(Intent.CATEGORY_LAUNCHER);
resolveIntent.setPackage(packageName);
List<ResolveInfo> apps = packageManager.queryIntentActivities(
resolveIntent, 0);
ResolveInfo ri = apps.iterator().next();
if (ri != null) {
String className = ri.activityInfo.name;
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
ComponentName cn = new ComponentName(packageName, className);
intent.setComponent(cn);
context.startActivity(intent);
}
3、TV端方式需要做个兼容(这也是很多同学打不开APP的原因)重点中的重点:
{
String activityName = getActivityNameFromPackage(context, packageName);
if (activityName == null) {
return;
}
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
ComponentName cn = new ComponentName(packageName, activityName);
intent.setComponent(cn);
context.startActivity(intent);
}
private static String getActivityNameFromPackage(Context context, String packageName) {
try {
PackageManager pm = context.getPackageManager();
PackageInfo pi = pm.getPackageInfo(packageName, 0);
Intent resolveIntent = new Intent(Intent.ACTION_MAIN, null);
resolveIntent.setPackage(pi.packageName);
resolveIntent.addCategory(Intent.CATEGORY_LEANBACK_LAUNCHER);
List<ResolveInfo> apps = pm.queryIntentActivities(resolveIntent, 0);
if (apps != null) {
Log.d(TAG, "getActivityNameFromPackage: LEANBACK_LAUNCHER: launcherIntent size == " + apps.size());
}
if (apps == null || apps.isEmpty()) {
resolveIntent.removeCategory(Intent.CATEGORY_LEANBACK_LAUNCHER);
resolveIntent.addCategory(Intent.CATEGORY_LAUNCHER);
apps = pm.queryIntentActivities(resolveIntent, 0);
Log.d(TAG, "getActivityNameFromPackage: LAUNCHER: launcherIntent size == " + apps.size());
}
if (apps != null && apps.size() > 0) {
ResolveInfo info = apps.iterator().next();
if (info != null) {
return info.activityInfo.name;
}
} else {
Log.d(TAG, "getActivityNameFromPackage: apps is null");
}
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
最后,我们知道,对CATEGORY_LEANBACK_LAUNCHER 和 CATEGORY_LAUNCHER的正确理解是解决此问题的根本之道。
版权声明:本文为Agg_bin原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。