调用startActivity()
失败。理想情况下,我们会将该调用追溯到 Android 系统,并找出它为什么无法获取一些可能导致修复的信息。取而代之的是,我提出以下可能的解决方案。
我正在假设所有已安装的软件包都可以显示“apps-info”屏幕,除非该软件包是一个隐藏的模块。
我查看了一个运行 API 30 的 Android 模拟器,并进行了上述检查。我不相信这个理论在所有情况下都有效。您提到“文件”应用程序是一个问题。此应用程序显示为一个模块,但不在您建议的已安装应用程序列表中。更新的代码解决了这个问题。
我已经组装了一个小应用程序,可以根据上面提到的类别测试是否创建了应用程序信息屏幕。我已将其包含在此处以供进一步查看。代码中的注释解释了应用程序的工作原理。
class MainActivity : AppCompatActivity() {
private var mActivitiesStarted = 1 // This activity counts.
@RequiresApi(Build.VERSION_CODES.Q)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val modulesByPackageName = packageManager.getInstalledModules(MATCH_ALL)
.asSequence()
.filter { it.packageName != null } // packageName can be null according to the docs.
.associate { moduleInfo -> Pair(moduleInfo.packageName, moduleInfo.isHidden) }
// Comment/uncomment code in different paths to start apps-info activities for the
// various categories of packages/modules.
val installedByPackageName = mutableSetOf<String>()
packageManager.getInstalledPackages(0).forEach {
installedByPackageName.add(it.packageName)
when (modulesByPackageName[it.packageName]) {
true -> {
// Package is a module that is hidden. We should not be able to get to apps-info.
// Unfortunately, for testing, the activity will start but the apps-info
// screen will not display. This condition cannot be tested through a count
// of activities.
Log.d(
"MainActivity",
"<<<<Can't reach app-info for ${it.packageName} (hidden module)"
)
// This will fail to display but the activity will start.
// startAppsInfo(it.packageName)
}
false -> {
// Package is a module that is not hidden. We should be able to get to apps-info.
Log.d(
"MainActivity",
"<<<<Can reach app-info for ${it.packageName} (not hidden module)"
)
// This should be successful.
startAppsInfo(it.packageName)
mActivitiesStarted++
}
else -> {
// Package is not a module. We should be able to get to apps-info.
Log.d(
"MainActivity",
"<<<<Can reach app-info for ${it.packageName} (not module)"
)
// This should be successful.
startAppsInfo(it.packageName)
mActivitiesStarted++
}
}
}
// Look at modules that are not hidden but do not appear in the installed packages list.
// This should pick up modules like com.google.android.documentsui (Files).
modulesByPackageName.filter { !it.value && !installedByPackageName.contains(it.key) }
.forEach {
Log.d(
"MainActivity",
"<<<<Can reach app-info for ${it.key} (module but not in installed packages)"
)
// This should be successful.
startAppsInfo(it.key!!)
mActivitiesStarted++
}
// Check that we started the number of activities that we expected. Post to ensure that
// all activities start and can be counted.
Handler(Looper.getMainLooper()).post {
val activityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
// getRunningTasks is deprecated, but it still returns tasks for the current app.
val runningTasks = activityManager.getRunningTasks(Integer.MAX_VALUE)
val numActivities = runningTasks[0].numActivities
Log.d(
"MainActivity",
"<<<<activitiesStarted=$mActivitiesStarted numActivities=$numActivities"
)
}
}
private fun startAppsInfo(appPackageName: String) {
val intent = Intent(
Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
Uri.parse("package:$appPackageName")
)
startActivity(intent)
}
}