diff --git a/mobile/src/main/java/com/github/shadowsocks/ProfilesFragment.kt b/mobile/src/main/java/com/github/shadowsocks/ProfilesFragment.kt index aa830498e0..606c1801a9 100644 --- a/mobile/src/main/java/com/github/shadowsocks/ProfilesFragment.kt +++ b/mobile/src/main/java/com/github/shadowsocks/ProfilesFragment.kt @@ -42,7 +42,11 @@ import androidx.appcompat.widget.TooltipCompat import androidx.core.os.bundleOf import androidx.core.view.ViewCompat import androidx.fragment.app.DialogFragment +import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.* +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import com.github.shadowsocks.aidl.TrafficStats import com.github.shadowsocks.bg.BaseService import com.github.shadowsocks.database.Profile @@ -457,22 +461,30 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener, Sea private fun importOrReplaceProfiles(dataUris: List, replace: Boolean = false) { if (dataUris.isEmpty()) return val activity = activity as MainActivity - try { - ProfileManager.createProfilesFromJson(dataUris.asSequence().map { - activity.contentResolver.openInputStream(it) - }.filterNotNull(), replace) - } catch (e: Exception) { - activity.snackbar(e.readableMessage).show() + lifecycleScope.launch { + try { + withContext(Dispatchers.IO) { + ProfileManager.createProfilesFromJson(dataUris.asSequence().map { + activity.contentResolver.openInputStream(it) + }.filterNotNull(), replace) + } + } catch (e: Exception) { + activity.snackbar(e.readableMessage).show() + } } } private val importProfiles = registerForActivityResult(OpenJson) { importOrReplaceProfiles(it) } private val replaceProfiles = registerForActivityResult(OpenJson) { importOrReplaceProfiles(it, true) } private val exportProfiles = registerForActivityResult(SaveJson) { data -> - if (data != null) ProfileManager.serializeToJson()?.let { profiles -> + if (data != null) lifecycleScope.launch { val activity = activity as MainActivity try { - activity.contentResolver.openOutputStream(data)!!.bufferedWriter().use { - it.write(profiles.toString(2)) + withContext(Dispatchers.IO) { + ProfileManager.serializeToJson()?.let { profiles -> + activity.contentResolver.openOutputStream(data)!!.bufferedWriter().use { + it.write(profiles.toString(2)) + } + } } } catch (e: Exception) { Timber.w(e) diff --git a/tv/src/main/java/com/github/shadowsocks/tv/MainPreferenceFragment.kt b/tv/src/main/java/com/github/shadowsocks/tv/MainPreferenceFragment.kt index 198245f728..d18a2c9abc 100644 --- a/tv/src/main/java/com/github/shadowsocks/tv/MainPreferenceFragment.kt +++ b/tv/src/main/java/com/github/shadowsocks/tv/MainPreferenceFragment.kt @@ -30,7 +30,11 @@ import androidx.activity.result.ActivityResultLauncher import androidx.fragment.app.setFragmentResultListener import androidx.fragment.app.viewModels import androidx.leanback.preference.LeanbackPreferenceFragmentCompat +import androidx.lifecycle.lifecycleScope import androidx.preference.* +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import com.github.shadowsocks.BootReceiver import com.github.shadowsocks.Core import com.github.shadowsocks.aidl.IShadowsocksService @@ -228,22 +232,30 @@ class MainPreferenceFragment : LeanbackPreferenceFragmentCompat(), ShadowsocksCo private val replaceProfiles = registerForActivityResult(OpenJson) { dataUris -> if (dataUris.isEmpty()) return@registerForActivityResult val context = requireContext() - try { - ProfileManager.createProfilesFromJson(dataUris.asSequence().map { - context.contentResolver.openInputStream(it) - }.filterNotNull(), true) - } catch (e: Exception) { - Timber.w(e) - Toast.makeText(context, e.readableMessage, Toast.LENGTH_SHORT).show() + lifecycleScope.launch { + try { + withContext(Dispatchers.IO) { + ProfileManager.createProfilesFromJson(dataUris.asSequence().map { + context.contentResolver.openInputStream(it) + }.filterNotNull(), true) + } + } catch (e: Exception) { + Timber.w(e) + Toast.makeText(context, e.readableMessage, Toast.LENGTH_SHORT).show() + } + populateProfiles() } - populateProfiles() } private val exportProfiles = registerForActivityResult(SaveJson) { data -> - if (data != null) ProfileManager.serializeToJson()?.let { profiles -> + if (data != null) lifecycleScope.launch { val context = requireContext() try { - context.contentResolver.openOutputStream(data)!!.bufferedWriter().use { - it.write(profiles.toString(2)) + withContext(Dispatchers.IO) { + ProfileManager.serializeToJson()?.let { profiles -> + context.contentResolver.openOutputStream(data)!!.bufferedWriter().use { + it.write(profiles.toString(2)) + } + } } } catch (e: Exception) { Timber.w(e)