diff --git a/mobile/src/main/java/com/github/shadowsocks/App.kt b/mobile/src/main/java/com/github/shadowsocks/App.kt index dd80764f..5727a116 100644 --- a/mobile/src/main/java/com/github/shadowsocks/App.kt +++ b/mobile/src/main/java/com/github/shadowsocks/App.kt @@ -174,12 +174,16 @@ class App : Application() { } } - fun listenForPackageChanges(callback: () -> Unit): BroadcastReceiver { + fun listenForPackageChanges(onetime: Boolean = true, callback: () -> Unit): BroadcastReceiver { val filter = IntentFilter(Intent.ACTION_PACKAGE_ADDED) filter.addAction(Intent.ACTION_PACKAGE_REMOVED) filter.addDataScheme("package") - val result = broadcastReceiver { _, intent -> - if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) callback() + val result = object : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent) { + if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) return + callback() + if (onetime) app.unregisterReceiver(this) + } } app.registerReceiver(result, filter) return result diff --git a/mobile/src/main/java/com/github/shadowsocks/AppManager.kt b/mobile/src/main/java/com/github/shadowsocks/AppManager.kt index 598bff2b..415fa59b 100644 --- a/mobile/src/main/java/com/github/shadowsocks/AppManager.kt +++ b/mobile/src/main/java/com/github/shadowsocks/AppManager.kt @@ -63,11 +63,14 @@ class AppManager : AppCompatActivity(), Toolbar.OnMenuItemClickListener { private var receiver: BroadcastReceiver? = null private var cachedApps: List? = null private fun getApps(pm: PackageManager): List { - if (receiver == null) receiver = app.listenForPackageChanges { - synchronized(AppManager) { cachedApps = null } - AppManager.instance?.reloadApps() - } return synchronized(AppManager) { + if (receiver == null) receiver = app.listenForPackageChanges { + synchronized(AppManager) { + receiver = null + cachedApps = null + } + AppManager.instance?.reloadApps() + } // Labels and icons can change on configuration (locale, etc.) changes, therefore they are not cached. val cachedApps = cachedApps ?: pm.getInstalledPackages(PackageManager.GET_PERMISSIONS) .filter { it.packageName != app.packageName && diff --git a/mobile/src/main/java/com/github/shadowsocks/ProfileConfigFragment.kt b/mobile/src/main/java/com/github/shadowsocks/ProfileConfigFragment.kt index f71be5d9..c664d84f 100644 --- a/mobile/src/main/java/com/github/shadowsocks/ProfileConfigFragment.kt +++ b/mobile/src/main/java/com/github/shadowsocks/ProfileConfigFragment.kt @@ -21,6 +21,7 @@ package com.github.shadowsocks import android.app.Activity +import android.content.BroadcastReceiver import android.content.Intent import android.os.Build import android.os.Bundle @@ -60,6 +61,7 @@ class ProfileConfigFragment : PreferenceFragmentCompatDividers(), Toolbar.OnMenu private lateinit var plugin: IconListPreference private lateinit var pluginConfigure: EditTextPreference private lateinit var pluginConfiguration: PluginConfiguration + private lateinit var receiver: BroadcastReceiver override fun onCreatePreferencesFix(savedInstanceState: Bundle?, rootKey: String?) { preferenceManager.preferenceDataStore = DataStore.privateStore @@ -102,7 +104,7 @@ class ProfileConfigFragment : PreferenceFragmentCompatDividers(), Toolbar.OnMenu } pluginConfigure.onPreferenceChangeListener = this initPlugins() - app.listenForPackageChanges { initPlugins() } + receiver = app.listenForPackageChanges(false) { initPlugins() } DataStore.privateStore.registerChangeListener(this) } @@ -202,6 +204,7 @@ class ProfileConfigFragment : PreferenceFragmentCompatDividers(), Toolbar.OnMenu override fun onDestroy() { DataStore.privateStore.unregisterChangeListener(this) + app.unregisterReceiver(receiver) super.onDestroy() } } diff --git a/mobile/src/main/java/com/github/shadowsocks/plugin/PluginManager.kt b/mobile/src/main/java/com/github/shadowsocks/plugin/PluginManager.kt index 74c34167..3b9e4bda 100644 --- a/mobile/src/main/java/com/github/shadowsocks/plugin/PluginManager.kt +++ b/mobile/src/main/java/com/github/shadowsocks/plugin/PluginManager.kt @@ -21,6 +21,7 @@ package com.github.shadowsocks.plugin import android.annotation.SuppressLint +import android.content.BroadcastReceiver import android.content.ContentResolver import android.content.Intent import android.content.pm.PackageManager @@ -84,11 +85,16 @@ object PluginManager { """, Base64.DEFAULT)) } - private val receiver by lazy { app.listenForPackageChanges { synchronized(this) { cachedPlugins = null } } } + private var receiver: BroadcastReceiver? = null private var cachedPlugins: Map? = null fun fetchPlugins(): Map { - receiver return synchronized(this) { + if (receiver == null) receiver = app.listenForPackageChanges { + synchronized(this) { + receiver = null + cachedPlugins = null + } + } if (cachedPlugins == null) { val pm = app.packageManager cachedPlugins = (pm.queryIntentContentProviders(Intent(PluginContract.ACTION_NATIVE_PLUGIN),