如何通过Activity名称获取包名?能否无包名启动已保存的Activity?
嘿,这个问题我刚好有经验,来给你捋清楚~
解决方案:获取包名 & 直接启动Activity
一、从保存的Activity类名获取对应包名
你之前只保存了result.activityInfo.name(这是Activity的完整类名,格式通常是com.example.app.MainActivity),想要拿到它的包名有两种方式:
1. 补救方案:遍历已安装应用匹配类名
如果当初没存包名,可以通过PackageManager遍历所有带启动Activity的应用,匹配你保存的类名来找到对应包名:
// 从SharedPreferences取出保存的Activity类名 SharedPreferences sp = getSharedPreferences("YourPrefsName", MODE_PRIVATE); String savedActivityName = sp.getString("saved_activity", null); if (savedActivityName == null) return; PackageManager pm = getPackageManager(); // 查询所有符合LAUNCHER类别应用的启动Activity List<ResolveInfo> launchableActivities = pm.queryIntentActivities( new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_LAUNCHER), 0 ); String targetPackageName = null; for (ResolveInfo info : launchableActivities) { if (savedActivityName.equals(info.activityInfo.name)) { targetPackageName = info.activityInfo.packageName; break; } } // 找到包名后启动Activity if (targetPackageName != null) { Intent intent = new Intent(); intent.setComponent(new ComponentName(targetPackageName, savedActivityName)); startActivity(intent); }
2. 更高效的方案:当初保存时同时存包名
其实最省心的方式是当初获取ResolveInfo的时候,同时把包名也存到SharedPreferences,这样后面直接取出来用就行,不用额外遍历:
// 保存时的代码 ResolveInfo result = getPackageManager().resolveActivity(intent, 0); if (result != null) { SharedPreferences.Editor editor = sp.edit(); editor.putString("target_package", result.activityInfo.packageName); editor.putString("target_activity", result.activityInfo.name); editor.apply(); } // 启动时的代码 String pkg = sp.getString("target_package", null); String cls = sp.getString("target_activity", null); if (pkg != null && cls != null) { Intent intent = new Intent(); intent.setComponent(new ComponentName(pkg, cls)); startActivity(intent); }
二、能不能无需知晓包名直接启动Activity
严格来说,Android启动Activity必须知道它所属的包名,但如果你保存的activityInfo.name是完整类名(包含包名),可以通过以下方式间接实现“不用手动输入包名”启动:
方法1:拆分完整类名得到包名
把完整类名按最后一个.拆分,前半部分就是包名,后半部分是类名:
String savedActivityName = sp.getString("saved_activity", null); if (savedActivityName == null) return; int lastDotPos = savedActivityName.lastIndexOf('.'); if (lastDotPos == -1) return; // 类名格式不对 String pkgName = savedActivityName.substring(0, lastDotPos); String clsName = savedActivityName.substring(lastDotPos + 1); Intent intent = new Intent(); intent.setComponent(new ComponentName(pkgName, clsName)); startActivity(intent);
方法2:直接用setClassName传入完整类名
Android的Intent.setClassName()方法支持直接传入完整类名,底层会自动拆分包名和类名:
String savedActivityName = sp.getString("saved_activity", null); if (savedActivityName == null) return; Intent intent = new Intent(); // 第一个参数是当前上下文,第二个是完整Activity类名 intent.setClassName(this, savedActivityName); startActivity(intent);
注意:如果你的
savedActivityName只是短类名(比如MainActivity)而不是完整路径,这个方法会默认使用当前应用的包名,这就会启动错误的Activity,所以一定要确保保存的是activityInfo.name的原始值(它本身就是完整类名)。
内容的提问来源于stack exchange,提问作者Jack
相关产品推荐
相关产品推荐

