Loading feature/settings/import/src/main/kotlin/app/k9mail/feature/settings/import/ui/ImportAppFetcher.kt +21 −12 Original line number Diff line number Diff line Loading @@ -14,7 +14,7 @@ internal class ImportAppFetcher( */ @WorkerThread fun isAtLeastOneAppInstalled(): Boolean { return supportedApps.any { packageName -> packageManager.isAppInstalled(packageName) } return supportedApps.any { app -> packageManager.isAppInstalled(app.packageName) } } @Suppress("SwallowedException") Loading @@ -33,17 +33,20 @@ internal class ImportAppFetcher( @WorkerThread fun getAppInfoList(): List<AppInfo> { return supportedApps .mapNotNull { packageName -> packageManager.loadAppInfo(packageName) } .mapNotNull { app -> packageManager.loadAppInfo(app) } .toList() } @Suppress("SwallowedException") private fun PackageManager.loadAppInfo(packageName: String): AppInfo? { private fun PackageManager.loadAppInfo(app: AppVersion): AppInfo? { return try { val applicationInfo = getApplicationInfo(packageName, 0) val packageInfo = getPackageInfo(app.packageName, 0) val isImportSupported = packageInfo.versionCode >= app.minVersionCode val applicationInfo = getApplicationInfo(app.packageName, 0) val appName = packageManager.getApplicationLabel(applicationInfo).toString() AppInfo(packageName, appName) AppInfo(app.packageName, appName, isImportSupported) } catch (e: PackageManager.NameNotFoundException) { null } Loading @@ -52,29 +55,35 @@ internal class ImportAppFetcher( /** * Get the list of application IDs of supported apps excluding our own app. */ private val supportedApps: Sequence<String> private val supportedApps: Sequence<AppVersion> get() { val myPackageName = context.packageName return SUPPORTED_APPS .asSequence() .filterNot { packageName -> packageName == myPackageName } .filterNot { app -> app.packageName == myPackageName } } companion object { private val SUPPORTED_APPS = listOf( // K-9 Mail "com.fsck.k9", AppVersion("com.fsck.k9", 39005), // Thunderbird for Android (release) "net.thunderbird.android", AppVersion("net.thunderbird.android", 1), // Thunderbird for Android (beta) "net.thunderbird.android.beta", AppVersion("net.thunderbird.android.beta", 4), // Thunderbird for Android (daily) "net.thunderbird.android.daily", AppVersion("net.thunderbird.android.daily", 1), ) } } internal data class AppInfo(val packageName: String, private val appName: String) { private data class AppVersion(val packageName: String, val minVersionCode: Int) internal data class AppInfo( val packageName: String, val appName: String, val isImportSupported: Boolean, ) { // ArrayAdapter is using `toString()` when rendering list items. See PickAppDialogFragment. override fun toString() = appName } feature/settings/import/src/test/kotlin/app/k9mail/feature/settings/import/ui/ImportAppFetcherTest.kt +23 −11 Original line number Diff line number Diff line Loading @@ -50,28 +50,39 @@ class ImportAppFetcherTest { } @Test fun `getAppInfoList() with another app installed`() { installPackage("com.fsck.k9", "K-9 Mail") fun `getAppInfoList() with another supported app installed`() { installPackage("com.fsck.k9", "K-9 Mail", versionCode = 40000) val result = importAppFetcher.getAppInfoList() assertThat(result).containsExactly( AppInfo("com.fsck.k9", "K-9 Mail"), AppInfo("com.fsck.k9", "K-9 Mail", isImportSupported = true), ) } @Test fun `getAppInfoList() with multiple other apps installed`() { installPackage("com.fsck.k9", "K-9 Mail") installPackage("net.thunderbird.android.beta", "Thunderbird Beta") installPackage("net.thunderbird.android.daily", "Thunderbird Daily") fun `getAppInfoList() with another unsupported app installed`() { installPackage("com.fsck.k9", "K-9 Mail", versionCode = 39004) val result = importAppFetcher.getAppInfoList() assertThat(result).containsExactly( AppInfo("com.fsck.k9", "K-9 Mail", isImportSupported = false), ) } @Test fun `getAppInfoList() with multiple other supported apps installed`() { installPackage("com.fsck.k9", "K-9 Mail", versionCode = 39005) installPackage("net.thunderbird.android.beta", "Thunderbird Beta", versionCode = 4) installPackage("net.thunderbird.android.daily", "Thunderbird Daily", versionCode = 1) val result = importAppFetcher.getAppInfoList() assertThat(result).containsExactlyInAnyOrder( AppInfo("com.fsck.k9", "K-9 Mail"), AppInfo("net.thunderbird.android.beta", "Thunderbird Beta"), AppInfo("net.thunderbird.android.daily", "Thunderbird Daily"), AppInfo("com.fsck.k9", "K-9 Mail", isImportSupported = true), AppInfo("net.thunderbird.android.beta", "Thunderbird Beta", isImportSupported = true), AppInfo("net.thunderbird.android.daily", "Thunderbird Daily", isImportSupported = true), ) } Loading @@ -82,7 +93,7 @@ class ImportAppFetcherTest { return appContext.createPackageContext(MY_PACKAGE_NAME, 0) } private fun installPackage(packageName: String, name: String = "irrelevant") { private fun installPackage(packageName: String, name: String = "irrelevant", versionCode: Int = 1) { val packageManager = shadowOf(appContext.packageManager) packageManager.installPackage( Loading @@ -91,6 +102,7 @@ class ImportAppFetcherTest { this.applicationInfo = ApplicationInfo().apply { this.name = name } this.versionCode = versionCode }, ) } Loading Loading
feature/settings/import/src/main/kotlin/app/k9mail/feature/settings/import/ui/ImportAppFetcher.kt +21 −12 Original line number Diff line number Diff line Loading @@ -14,7 +14,7 @@ internal class ImportAppFetcher( */ @WorkerThread fun isAtLeastOneAppInstalled(): Boolean { return supportedApps.any { packageName -> packageManager.isAppInstalled(packageName) } return supportedApps.any { app -> packageManager.isAppInstalled(app.packageName) } } @Suppress("SwallowedException") Loading @@ -33,17 +33,20 @@ internal class ImportAppFetcher( @WorkerThread fun getAppInfoList(): List<AppInfo> { return supportedApps .mapNotNull { packageName -> packageManager.loadAppInfo(packageName) } .mapNotNull { app -> packageManager.loadAppInfo(app) } .toList() } @Suppress("SwallowedException") private fun PackageManager.loadAppInfo(packageName: String): AppInfo? { private fun PackageManager.loadAppInfo(app: AppVersion): AppInfo? { return try { val applicationInfo = getApplicationInfo(packageName, 0) val packageInfo = getPackageInfo(app.packageName, 0) val isImportSupported = packageInfo.versionCode >= app.minVersionCode val applicationInfo = getApplicationInfo(app.packageName, 0) val appName = packageManager.getApplicationLabel(applicationInfo).toString() AppInfo(packageName, appName) AppInfo(app.packageName, appName, isImportSupported) } catch (e: PackageManager.NameNotFoundException) { null } Loading @@ -52,29 +55,35 @@ internal class ImportAppFetcher( /** * Get the list of application IDs of supported apps excluding our own app. */ private val supportedApps: Sequence<String> private val supportedApps: Sequence<AppVersion> get() { val myPackageName = context.packageName return SUPPORTED_APPS .asSequence() .filterNot { packageName -> packageName == myPackageName } .filterNot { app -> app.packageName == myPackageName } } companion object { private val SUPPORTED_APPS = listOf( // K-9 Mail "com.fsck.k9", AppVersion("com.fsck.k9", 39005), // Thunderbird for Android (release) "net.thunderbird.android", AppVersion("net.thunderbird.android", 1), // Thunderbird for Android (beta) "net.thunderbird.android.beta", AppVersion("net.thunderbird.android.beta", 4), // Thunderbird for Android (daily) "net.thunderbird.android.daily", AppVersion("net.thunderbird.android.daily", 1), ) } } internal data class AppInfo(val packageName: String, private val appName: String) { private data class AppVersion(val packageName: String, val minVersionCode: Int) internal data class AppInfo( val packageName: String, val appName: String, val isImportSupported: Boolean, ) { // ArrayAdapter is using `toString()` when rendering list items. See PickAppDialogFragment. override fun toString() = appName }
feature/settings/import/src/test/kotlin/app/k9mail/feature/settings/import/ui/ImportAppFetcherTest.kt +23 −11 Original line number Diff line number Diff line Loading @@ -50,28 +50,39 @@ class ImportAppFetcherTest { } @Test fun `getAppInfoList() with another app installed`() { installPackage("com.fsck.k9", "K-9 Mail") fun `getAppInfoList() with another supported app installed`() { installPackage("com.fsck.k9", "K-9 Mail", versionCode = 40000) val result = importAppFetcher.getAppInfoList() assertThat(result).containsExactly( AppInfo("com.fsck.k9", "K-9 Mail"), AppInfo("com.fsck.k9", "K-9 Mail", isImportSupported = true), ) } @Test fun `getAppInfoList() with multiple other apps installed`() { installPackage("com.fsck.k9", "K-9 Mail") installPackage("net.thunderbird.android.beta", "Thunderbird Beta") installPackage("net.thunderbird.android.daily", "Thunderbird Daily") fun `getAppInfoList() with another unsupported app installed`() { installPackage("com.fsck.k9", "K-9 Mail", versionCode = 39004) val result = importAppFetcher.getAppInfoList() assertThat(result).containsExactly( AppInfo("com.fsck.k9", "K-9 Mail", isImportSupported = false), ) } @Test fun `getAppInfoList() with multiple other supported apps installed`() { installPackage("com.fsck.k9", "K-9 Mail", versionCode = 39005) installPackage("net.thunderbird.android.beta", "Thunderbird Beta", versionCode = 4) installPackage("net.thunderbird.android.daily", "Thunderbird Daily", versionCode = 1) val result = importAppFetcher.getAppInfoList() assertThat(result).containsExactlyInAnyOrder( AppInfo("com.fsck.k9", "K-9 Mail"), AppInfo("net.thunderbird.android.beta", "Thunderbird Beta"), AppInfo("net.thunderbird.android.daily", "Thunderbird Daily"), AppInfo("com.fsck.k9", "K-9 Mail", isImportSupported = true), AppInfo("net.thunderbird.android.beta", "Thunderbird Beta", isImportSupported = true), AppInfo("net.thunderbird.android.daily", "Thunderbird Daily", isImportSupported = true), ) } Loading @@ -82,7 +93,7 @@ class ImportAppFetcherTest { return appContext.createPackageContext(MY_PACKAGE_NAME, 0) } private fun installPackage(packageName: String, name: String = "irrelevant") { private fun installPackage(packageName: String, name: String = "irrelevant", versionCode: Int = 1) { val packageManager = shadowOf(appContext.packageManager) packageManager.installPackage( Loading @@ -91,6 +102,7 @@ class ImportAppFetcherTest { this.applicationInfo = ApplicationInfo().apply { this.name = name } this.versionCode = versionCode }, ) } Loading