diff --git a/app-common/src/main/AndroidManifest.xml b/app-common/src/main/AndroidManifest.xml
index f53e6ff..a33838f 100644
--- a/app-common/src/main/AndroidManifest.xml
+++ b/app-common/src/main/AndroidManifest.xml
@@ -19,6 +19,11 @@
android:name="im.angry.openeuicc.ui.NotificationsActivity"
android:label="@string/profile_notifications" />
+
+
@@ -28,15 +33,9 @@
android:label="@string/pref_advanced_logs" />
-
-
+ euiccChannelManager.withEuiccChannel(slotId, portId) { channel ->
+ Triple(slotId, channel.logicalSlotId, portId)
+ }
+ }.toList().sortedBy { it.second }
+ }
+
+ when {
+ knownChannels.isEmpty() -> {
+ finish()
+ }
+ // Detect multiple eUICC chips
+ knownChannels.distinctBy { it.first }.size > 1 -> {
+ SlotSelectFragment.newInstance(
+ knownChannels.map { it.first },
+ knownChannels.map { it.second },
+ knownChannels.map { it.third })
+ .show(supportFragmentManager, SlotSelectFragment.TAG)
+ }
+ else -> {
+ // If the device has only one eSIM "chip" (but may be mapped to multiple slots),
+ // we can skip the slot selection dialog since there is only one chip to save to.
+ onSlotSelected(
+ knownChannels[0].first,
+ knownChannels[0].third
+ )
+ }
+ }
+ }
+ }
+
+ override fun onSlotSelected(slotId: Int, portId: Int) {
+ ProfileDownloadFragment.newInstance(slotId, portId, finishWhenDone = true)
+ .show(supportFragmentManager, ProfileDownloadFragment.TAG)
+ }
+
+ override fun onSlotSelectCancelled() = finish()
+}
\ No newline at end of file
diff --git a/app-common/src/main/java/im/angry/openeuicc/ui/EuiccManagementFragment.kt b/app-common/src/main/java/im/angry/openeuicc/ui/EuiccManagementFragment.kt
index 8e7b158..824b683 100644
--- a/app-common/src/main/java/im/angry/openeuicc/ui/EuiccManagementFragment.kt
+++ b/app-common/src/main/java/im/angry/openeuicc/ui/EuiccManagementFragment.kt
@@ -37,6 +37,7 @@ import im.angry.openeuicc.util.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.TimeoutCancellationException
import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@@ -109,9 +110,16 @@ open class EuiccManagementFragment : Fragment(), EuiccProfilesChangedListener,
LinearLayoutManager(view.context, LinearLayoutManager.VERTICAL, false)
fab.setOnClickListener {
- Intent(requireContext(), DownloadWizardActivity::class.java).apply {
- putExtra("selectedLogicalSlot", logicalSlotId)
- startActivity(this)
+ lifecycleScope.launch {
+ if (preferenceRepository.experimentalDownloadWizardFlow.first()) {
+ Intent(requireContext(), DownloadWizardActivity::class.java).apply {
+ putExtra("selectedLogicalSlot", logicalSlotId)
+ startActivity(this)
+ }
+ } else {
+ ProfileDownloadFragment.newInstance(slotId, portId)
+ .show(childFragmentManager, ProfileDownloadFragment.TAG)
+ }
}
}
}
diff --git a/app-common/src/main/java/im/angry/openeuicc/ui/MainActivity.kt b/app-common/src/main/java/im/angry/openeuicc/ui/MainActivity.kt
index b11a3dd..7711643 100644
--- a/app-common/src/main/java/im/angry/openeuicc/ui/MainActivity.kt
+++ b/app-common/src/main/java/im/angry/openeuicc/ui/MainActivity.kt
@@ -126,10 +126,7 @@ open class MainActivity : BaseEuiccAccessActivity(), OpenEuiccContextMarker {
}
private fun ensureNotificationPermissions() {
- val needsNotificationPerms = Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU;
- val notificationPermsGranted =
- needsNotificationPerms && checkSelfPermission(android.Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED
- if (needsNotificationPerms && !notificationPermsGranted) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && checkSelfPermission(android.Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(
arrayOf(android.Manifest.permission.POST_NOTIFICATIONS),
PERMISSION_REQUEST_CODE
@@ -163,29 +160,38 @@ open class MainActivity : BaseEuiccAccessActivity(), OpenEuiccContextMarker {
// but it could change in the future
euiccChannelManager.notifyEuiccProfilesChanged(channel.logicalSlotId)
- val channelName = getString(R.string.channel_name_format, channel.logicalSlotId)
- newPages.add(Page(channel.logicalSlotId, channelName) {
- appContainer.uiComponentFactory.createEuiccManagementFragment(slotId, portId)
- })
+ newPages.add(
+ Page(
+ channel.logicalSlotId,
+ getString(R.string.channel_name_format, channel.logicalSlotId)
+ ) {
+ appContainer.uiComponentFactory.createEuiccManagementFragment(
+ slotId,
+ portId
+ )
+ })
}
}.collect()
// If USB readers exist, add them at the very last
// We use a wrapper fragment to handle logic specific to USB readers
usbDevice?.let {
- val productName = it.productName ?: getString(R.string.usb)
- newPages.add(Page(EuiccChannelManager.USB_CHANNEL_ID, productName) {
- UsbCcidReaderFragment()
- })
+ newPages.add(
+ Page(
+ EuiccChannelManager.USB_CHANNEL_ID,
+ it.productName ?: getString(R.string.usb)
+ ) { UsbCcidReaderFragment() })
}
viewPager.visibility = View.VISIBLE
if (newPages.size > 1) {
tabs.visibility = View.VISIBLE
} else if (newPages.isEmpty()) {
- newPages.add(Page(-1, "") {
- appContainer.uiComponentFactory.createNoEuiccPlaceholderFragment()
- })
+ newPages.add(
+ Page(
+ -1,
+ ""
+ ) { appContainer.uiComponentFactory.createNoEuiccPlaceholderFragment() })
}
newPages.sortBy { it.logicalSlotId }
diff --git a/app-common/src/main/java/im/angry/openeuicc/ui/ProfileDeleteFragment.kt b/app-common/src/main/java/im/angry/openeuicc/ui/ProfileDeleteFragment.kt
index a06b587..181aeee 100644
--- a/app-common/src/main/java/im/angry/openeuicc/ui/ProfileDeleteFragment.kt
+++ b/app-common/src/main/java/im/angry/openeuicc/ui/ProfileDeleteFragment.kt
@@ -38,13 +38,14 @@ class ProfileDeleteFragment : DialogFragment(), EuiccChannelFragmentMarker {
get() = editText.text.toString() == requireArguments().getString("name")!!
private var deleting = false
- override fun onCreateDialog(savedInstanceState: Bundle?): Dialog =
- AlertDialog.Builder(requireContext(), R.style.AlertDialogTheme).apply {
+ override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
+ return AlertDialog.Builder(requireContext(), R.style.AlertDialogTheme).apply {
setMessage(getString(R.string.profile_delete_confirm, requireArguments().getString("name")))
setView(editText)
setPositiveButton(android.R.string.ok, null) // Set listener to null to prevent auto closing
setNegativeButton(android.R.string.cancel, null)
}.create()
+ }
override fun onResume() {
super.onResume()
diff --git a/app-common/src/main/java/im/angry/openeuicc/ui/ProfileDownloadFragment.kt b/app-common/src/main/java/im/angry/openeuicc/ui/ProfileDownloadFragment.kt
new file mode 100644
index 0000000..f590d36
--- /dev/null
+++ b/app-common/src/main/java/im/angry/openeuicc/ui/ProfileDownloadFragment.kt
@@ -0,0 +1,298 @@
+package im.angry.openeuicc.ui
+
+import android.annotation.SuppressLint
+import android.app.Dialog
+import android.content.DialogInterface
+import android.graphics.BitmapFactory
+import android.os.Bundle
+import android.text.Editable
+import android.util.Log
+import android.view.*
+import android.widget.ProgressBar
+import android.widget.TextView
+import android.widget.Toast
+import androidx.activity.result.contract.ActivityResultContracts
+import androidx.appcompat.app.AlertDialog
+import androidx.appcompat.widget.Toolbar
+import androidx.lifecycle.lifecycleScope
+import com.google.android.material.textfield.TextInputLayout
+import com.journeyapps.barcodescanner.ScanContract
+import com.journeyapps.barcodescanner.ScanOptions
+import im.angry.openeuicc.common.R
+import im.angry.openeuicc.service.EuiccChannelManagerService
+import im.angry.openeuicc.service.EuiccChannelManagerService.Companion.waitDone
+import im.angry.openeuicc.util.*
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+
+class ProfileDownloadFragment : BaseMaterialDialogFragment(),
+ Toolbar.OnMenuItemClickListener, EuiccChannelFragmentMarker {
+ companion object {
+ const val TAG = "ProfileDownloadFragment"
+
+ const val LOW_NVRAM_THRESHOLD = 30 * 1024 // < 30 KiB, the alert may fail
+
+ fun newInstance(slotId: Int, portId: Int, finishWhenDone: Boolean = false): ProfileDownloadFragment =
+ newInstanceEuicc(ProfileDownloadFragment::class.java, slotId, portId) {
+ putBoolean("finishWhenDone", finishWhenDone)
+ }
+ }
+
+ private lateinit var toolbar: Toolbar
+ private lateinit var profileDownloadServer: TextInputLayout
+ private lateinit var profileDownloadCode: TextInputLayout
+ private lateinit var profileDownloadConfirmationCode: TextInputLayout
+ private lateinit var profileDownloadIMEI: TextInputLayout
+ private lateinit var profileDownloadFreeSpace: TextView
+ private lateinit var progress: ProgressBar
+
+ private var freeNvram: Int = -1
+
+ private var downloading = false
+
+ private val finishWhenDone by lazy {
+ requireArguments().getBoolean("finishWhenDone", false)
+ }
+
+ private val barcodeScannerLauncher = registerForActivityResult(ScanContract()) { result ->
+ result.contents?.let { content ->
+ onScanResult(content)
+ }
+ }
+
+ private val gallerySelectorLauncher = registerForActivityResult(ActivityResultContracts.GetContent()) { result ->
+ if (result == null) return@registerForActivityResult
+
+ lifecycleScope.launch(Dispatchers.IO) {
+ runCatching {
+ requireContext().contentResolver.openInputStream(result)?.let { input ->
+ val bmp = BitmapFactory.decodeStream(input)
+ input.close()
+
+ decodeQrFromBitmap(bmp)?.let {
+ withContext(Dispatchers.Main) {
+ onScanResult(it)
+ }
+ }
+
+ bmp.recycle()
+ }
+ }
+ }
+ }
+
+ private fun onScanResult(result: String) {
+ val components = result.split("$")
+ if (components.size < 3 || components[0] != "LPA:1") return
+ profileDownloadServer.editText?.setText(components[1])
+ profileDownloadCode.editText?.setText(components[2])
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ val view = inflater.inflate(R.layout.fragment_profile_download, container, false)
+
+ toolbar = view.requireViewById(R.id.toolbar)
+ profileDownloadServer = view.requireViewById(R.id.profile_download_server)
+ profileDownloadCode = view.requireViewById(R.id.profile_download_code)
+ profileDownloadConfirmationCode = view.requireViewById(R.id.profile_download_confirmation_code)
+ profileDownloadIMEI = view.requireViewById(R.id.profile_download_imei)
+ profileDownloadFreeSpace = view.requireViewById(R.id.profile_download_free_space)
+ progress = view.requireViewById(R.id.progress)
+
+ toolbar.inflateMenu(R.menu.fragment_profile_download)
+
+ return view
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ toolbar.apply {
+ setTitle(R.string.profile_download)
+ setNavigationOnClickListener {
+ if (!downloading) {
+ dismiss()
+ }
+ }
+ setOnMenuItemClickListener(this@ProfileDownloadFragment)
+ }
+ }
+
+ override fun onMenuItemClick(item: MenuItem): Boolean = downloading ||
+ when (item.itemId) {
+ R.id.scan -> {
+ barcodeScannerLauncher.launch(ScanOptions().apply {
+ setDesiredBarcodeFormats(ScanOptions.QR_CODE)
+ setOrientationLocked(false)
+ })
+ true
+ }
+ R.id.scan_from_gallery -> {
+ gallerySelectorLauncher.launch("image/*")
+ true
+ }
+ R.id.ok -> {
+ if (freeNvram > LOW_NVRAM_THRESHOLD) {
+ startDownloadProfile()
+ } else {
+ AlertDialog.Builder(requireContext()).apply {
+ setTitle(R.string.profile_download_low_nvram_title)
+ setMessage(R.string.profile_download_low_nvram_message)
+ setIcon(android.R.drawable.ic_dialog_alert)
+ setCancelable(true)
+ setPositiveButton(android.R.string.ok) { _, _ ->
+ startDownloadProfile()
+ }
+ setNegativeButton(android.R.string.cancel, null)
+ show()
+ }
+ }
+ true
+ }
+ else -> false
+ }
+
+ override fun onResume() {
+ super.onResume()
+ setWidthPercent(95)
+ }
+
+ @SuppressLint("MissingPermission")
+ override fun onStart() {
+ super.onStart()
+
+ lifecycleScope.launch(Dispatchers.IO) {
+ ensureEuiccChannelManager()
+ if (euiccChannelManagerService.isForegroundTaskRunning) {
+ withContext(Dispatchers.Main) {
+ dismiss()
+ }
+ return@launch
+ }
+
+ withEuiccChannel { channel ->
+ val imei = try {
+ telephonyManager.getImei(channel.logicalSlotId) ?: ""
+ } catch (e: Exception) {
+ ""
+ }
+
+ // Fetch remaining NVRAM
+ val str = channel.lpa.euiccInfo2?.freeNvram?.also {
+ freeNvram = it
+ }?.let { formatFreeSpace(it) }
+
+ withContext(Dispatchers.Main) {
+ profileDownloadFreeSpace.text = getString(
+ R.string.profile_download_free_space,
+ str ?: getText(R.string.unknown)
+ )
+ profileDownloadIMEI.editText!!.text =
+ Editable.Factory.getInstance().newEditable(imei)
+ }
+ }
+ }
+ }
+
+ override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
+ return super.onCreateDialog(savedInstanceState).also {
+ it.setCanceledOnTouchOutside(false)
+ }
+ }
+
+ private fun startDownloadProfile() {
+ val server = profileDownloadServer.editText!!.let {
+ it.text.toString().trim().apply {
+ if (isEmpty()) {
+ it.requestFocus()
+ return@startDownloadProfile
+ }
+ }
+ }
+
+ val code = profileDownloadCode.editText!!.text.toString().trim()
+ .ifBlank { null }
+ val confirmationCode = profileDownloadConfirmationCode.editText!!.text.toString().trim()
+ .ifBlank { null }
+ val imei = profileDownloadIMEI.editText!!.text.toString().trim()
+ .ifBlank { null }
+
+ downloading = true
+
+ profileDownloadServer.editText!!.isEnabled = false
+ profileDownloadCode.editText!!.isEnabled = false
+ profileDownloadConfirmationCode.editText!!.isEnabled = false
+ profileDownloadIMEI.editText!!.isEnabled = false
+
+ progress.isIndeterminate = true
+ progress.visibility = View.VISIBLE
+
+ lifecycleScope.launch {
+ ensureEuiccChannelManager()
+ euiccChannelManagerService.waitForForegroundTask()
+ val err = doDownloadProfile(server, code, confirmationCode, imei)
+
+ if (err != null) {
+ Log.d(TAG, "Error downloading profile")
+ Log.d(TAG, Log.getStackTraceString(err))
+
+ Toast.makeText(requireContext(), R.string.profile_download_failed, Toast.LENGTH_LONG).show()
+ }
+
+ if (parentFragment is EuiccProfilesChangedListener) {
+ (parentFragment as EuiccProfilesChangedListener).onEuiccProfilesChanged()
+ }
+
+ try {
+ dismiss()
+ } catch (e: IllegalStateException) {
+ // Ignored
+ }
+ }
+ }
+
+ private suspend fun doDownloadProfile(
+ server: String,
+ code: String?,
+ confirmationCode: String?,
+ imei: String?
+ ) = withContext(Dispatchers.Main) {
+ // The service is responsible for launching the actual blocking part on the IO context
+ // On our side, we need the Main context because of the UI updates
+ euiccChannelManagerService.launchProfileDownloadTask(
+ slotId,
+ portId,
+ server,
+ code,
+ confirmationCode,
+ imei
+ ).onEach {
+ if (it is EuiccChannelManagerService.ForegroundTaskState.InProgress) {
+ progress.progress = it.progress
+ progress.isIndeterminate = it.progress == 0
+ } else {
+ progress.progress = 100
+ progress.isIndeterminate = false
+ }
+ }.waitDone()
+ }
+
+ override fun onDismiss(dialog: DialogInterface) {
+ super.onDismiss(dialog)
+ if (finishWhenDone) {
+ activity?.finish()
+ }
+ }
+
+ override fun onCancel(dialog: DialogInterface) {
+ super.onCancel(dialog)
+ if (finishWhenDone) {
+ activity?.finish()
+ }
+ }
+}
\ No newline at end of file
diff --git a/app-common/src/main/java/im/angry/openeuicc/ui/SettingsActivity.kt b/app-common/src/main/java/im/angry/openeuicc/ui/SettingsActivity.kt
index bb299a3..52e3272 100644
--- a/app-common/src/main/java/im/angry/openeuicc/ui/SettingsActivity.kt
+++ b/app-common/src/main/java/im/angry/openeuicc/ui/SettingsActivity.kt
@@ -4,14 +4,10 @@ import android.os.Bundle
import android.view.MenuItem
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
-import im.angry.openeuicc.OpenEuiccApplication
import im.angry.openeuicc.common.R
import im.angry.openeuicc.util.*
class SettingsActivity: AppCompatActivity() {
- private val appContainer
- get() = (application as OpenEuiccApplication).appContainer
-
override fun onCreate(savedInstanceState: Bundle?) {
enableEdgeToEdge()
super.onCreate(savedInstanceState)
@@ -19,9 +15,8 @@ class SettingsActivity: AppCompatActivity() {
setSupportActionBar(requireViewById(R.id.toolbar))
setupToolbarInsets()
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
- val settingsFragment = appContainer.uiComponentFactory.createSettingsFragment()
supportFragmentManager.beginTransaction()
- .replace(R.id.settings_container, settingsFragment)
+ .replace(R.id.settings_container, SettingsFragment())
.commit()
}
diff --git a/app-common/src/main/java/im/angry/openeuicc/ui/SettingsFragment.kt b/app-common/src/main/java/im/angry/openeuicc/ui/SettingsFragment.kt
index c2cbee3..6ad74c4 100644
--- a/app-common/src/main/java/im/angry/openeuicc/ui/SettingsFragment.kt
+++ b/app-common/src/main/java/im/angry/openeuicc/ui/SettingsFragment.kt
@@ -20,7 +20,7 @@ import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
-open class SettingsFragment: PreferenceFragmentCompat() {
+class SettingsFragment: PreferenceFragmentCompat() {
private lateinit var developerPref: PreferenceCategory
// Hidden developer options switch
@@ -35,9 +35,9 @@ open class SettingsFragment: PreferenceFragmentCompat() {
// Show / hide developer preference based on whether it is enabled
lifecycleScope.launch {
- preferenceRepository.developerOptionsEnabledFlow
- .onEach { developerPref.isVisible = it }
- .collect()
+ preferenceRepository.developerOptionsEnabledFlow.onEach {
+ developerPref.isVisible = it
+ }.collect()
}
findPreference("pref_info_app_version")?.apply {
@@ -74,6 +74,9 @@ open class SettingsFragment: PreferenceFragmentCompat() {
findPreference("pref_advanced_verbose_logging")
?.bindBooleanFlow(preferenceRepository.verboseLoggingFlow, PreferenceKeys.VERBOSE_LOGGING)
+ findPreference("pref_developer_experimental_download_wizard")
+ ?.bindBooleanFlow(preferenceRepository.experimentalDownloadWizardFlow, PreferenceKeys.EXPERIMENTAL_DOWNLOAD_WIZARD)
+
findPreference("pref_developer_unfiltered_profile_list")
?.bindBooleanFlow(preferenceRepository.unfilteredProfileListFlow, PreferenceKeys.UNFILTERED_PROFILE_LIST)
@@ -136,22 +139,4 @@ open class SettingsFragment: PreferenceFragmentCompat() {
true
}
}
-
- protected fun mergePreferenceOverlay(overlayKey: String, targetKey: String) {
- val overlayCat = findPreference(overlayKey)!!
- val targetCat = findPreference(targetKey)!!
-
- val prefs = buildList {
- for (i in 0..
- if (uri == null) return@registerForActivityResult
- requireActivity().contentResolver.openFileDescriptor(uri, "w")?.use {
- FileOutputStream(it.fileDescriptor).use { os ->
- os.write(diagnosticTextView.text.toString().encodeToByteArray())
- }
- }
- }
-
override fun createNextFragment(): DownloadWizardActivity.DownloadWizardStepFragment? = null
override fun createPrevFragment(): DownloadWizardActivity.DownloadWizardStepFragment? = null
@@ -40,15 +26,7 @@ class DownloadWizardDiagnosticsFragment : DownloadWizardActivity.DownloadWizardS
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_download_diagnostics, container, false)
- view.requireViewById(R.id.download_wizard_diagnostics_save).setOnClickListener {
- saveDiagnostics.launch(
- getString(
- R.string.download_wizard_diagnostics_file_template,
- SimpleDateFormat.getDateTimeInstance().format(Date())
- )
- )
- }
- diagnosticTextView = view.requireViewById(R.id.download_wizard_diagnostics_text)
+ diagnosticTextView = view.requireViewById(R.id.download_wizard_diagnostics_text)
return view
}
@@ -66,14 +44,6 @@ class DownloadWizardDiagnosticsFragment : DownloadWizardActivity.DownloadWizardS
private fun buildDiagnosticsText(): String? = state.downloadError?.let { err ->
val ret = StringBuilder()
- ret.appendLine(
- getString(
- R.string.download_wizard_diagnostics_error_code,
- err.lpaErrorReason
- )
- )
- ret.appendLine()
-
err.lastHttpResponse?.let { resp ->
if (resp.rcode != 200) {
// Only show the status if it's not 200
diff --git a/app-common/src/main/java/im/angry/openeuicc/ui/wizard/DownloadWizardProgressFragment.kt b/app-common/src/main/java/im/angry/openeuicc/ui/wizard/DownloadWizardProgressFragment.kt
index 1b816d4..f6f63fd 100644
--- a/app-common/src/main/java/im/angry/openeuicc/ui/wizard/DownloadWizardProgressFragment.kt
+++ b/app-common/src/main/java/im/angry/openeuicc/ui/wizard/DownloadWizardProgressFragment.kt
@@ -113,19 +113,18 @@ class DownloadWizardProgressFragment : DownloadWizardActivity.DownloadWizardStep
is EuiccChannelManagerService.ForegroundTaskState.Done -> {
hideProgressBar()
- state.downloadError =
- it.error as? LocalProfileAssistant.ProfileDownloadException
-
- // Change the state of the last InProgress item to success (or error)
+ // Change the state of the last InProgress item to Error
progressItems.forEachIndexed { index, progressItem ->
if (progressItem.state == ProgressState.InProgress) {
- progressItem.state =
- if (state.downloadError == null) ProgressState.Done else ProgressState.Error
+ progressItem.state = ProgressState.Error
}
adapter.notifyItemChanged(index)
}
+ state.downloadError =
+ it.error as? LocalProfileAssistant.ProfileDownloadException
+
isDone = true
refreshButtons()
}
diff --git a/app-common/src/main/java/im/angry/openeuicc/ui/wizard/DownloadWizardSlotSelectFragment.kt b/app-common/src/main/java/im/angry/openeuicc/ui/wizard/DownloadWizardSlotSelectFragment.kt
index b268b62..c9a9e0f 100644
--- a/app-common/src/main/java/im/angry/openeuicc/ui/wizard/DownloadWizardSlotSelectFragment.kt
+++ b/app-common/src/main/java/im/angry/openeuicc/ui/wizard/DownloadWizardSlotSelectFragment.kt
@@ -7,7 +7,6 @@ import android.view.View
import android.view.ViewGroup
import android.widget.CheckBox
import android.widget.TextView
-import androidx.appcompat.app.AlertDialog
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
@@ -21,11 +20,6 @@ import kotlinx.coroutines.launch
import net.typeblog.lpac_jni.LocalProfileInfo
class DownloadWizardSlotSelectFragment : DownloadWizardActivity.DownloadWizardStepFragment() {
- companion object {
- const val LOW_NVRAM_THRESHOLD =
- 30 * 1024 // < 30 KiB, alert about potential download failure
- }
-
private data class SlotInfo(
val logicalSlotId: Int,
val isRemovable: Boolean,
@@ -51,21 +45,6 @@ class DownloadWizardSlotSelectFragment : DownloadWizardActivity.DownloadWizardSt
override fun createPrevFragment(): DownloadWizardActivity.DownloadWizardStepFragment? = null
- override fun beforeNext() {
- super.beforeNext()
-
- if (adapter.selected.freeSpace < LOW_NVRAM_THRESHOLD) {
- AlertDialog.Builder(requireContext()).apply {
- setTitle(R.string.profile_download_low_nvram_title)
- setMessage(R.string.profile_download_low_nvram_message)
- setCancelable(true)
- setPositiveButton(android.R.string.ok, null)
- setNegativeButton(android.R.string.cancel, null)
- show()
- }
- }
- }
-
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
@@ -186,9 +165,6 @@ class DownloadWizardSlotSelectFragment : DownloadWizardActivity.DownloadWizardSt
var slots: List = listOf()
var currentSelectedIdx = -1
- val selected: SlotInfo
- get() = slots[currentSelectedIdx]
-
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SlotItemHolder {
val root = LayoutInflater.from(parent.context).inflate(R.layout.download_slot_item, parent, false)
return SlotItemHolder(root)
diff --git a/app-common/src/main/java/im/angry/openeuicc/util/PreferenceUtils.kt b/app-common/src/main/java/im/angry/openeuicc/util/PreferenceUtils.kt
index e768fa9..807706e 100644
--- a/app-common/src/main/java/im/angry/openeuicc/util/PreferenceUtils.kt
+++ b/app-common/src/main/java/im/angry/openeuicc/util/PreferenceUtils.kt
@@ -31,6 +31,7 @@ object PreferenceKeys {
// ---- Developer Options ----
val DEVELOPER_OPTIONS_ENABLED = booleanPreferencesKey("developer_options_enabled")
+ val EXPERIMENTAL_DOWNLOAD_WIZARD = booleanPreferencesKey("experimental_download_wizard")
val UNFILTERED_PROFILE_LIST = booleanPreferencesKey("unfiltered_profile_list")
val IGNORE_TLS_CERTIFICATE = booleanPreferencesKey("ignore_tls_certificate")
}
@@ -48,6 +49,7 @@ class PreferenceRepository(private val context: Context) {
// ---- Developer Options ----
val developerOptionsEnabledFlow = bindFlow(PreferenceKeys.DEVELOPER_OPTIONS_ENABLED, false)
+ val experimentalDownloadWizardFlow = bindFlow(PreferenceKeys.EXPERIMENTAL_DOWNLOAD_WIZARD, false)
val unfilteredProfileListFlow = bindFlow(PreferenceKeys.UNFILTERED_PROFILE_LIST, false)
val ignoreTLSCertificateFlow = bindFlow(PreferenceKeys.IGNORE_TLS_CERTIFICATE, false)
diff --git a/app-common/src/main/res/layout/fragment_download_details.xml b/app-common/src/main/res/layout/fragment_download_details.xml
index 3f58844..ca36d64 100644
--- a/app-common/src/main/res/layout/fragment_download_details.xml
+++ b/app-common/src/main/res/layout/fragment_download_details.xml
@@ -16,10 +16,10 @@
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:textSize="20sp"
- android:layout_marginTop="20dp"
- android:layout_marginBottom="20dp"
- android:layout_marginStart="60dp"
- android:layout_marginEnd="60dp"
+ android:layout_marginTop="20sp"
+ android:layout_marginBottom="20sp"
+ android:layout_marginStart="60sp"
+ android:layout_marginEnd="60sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constrainedWidth="true"
diff --git a/app-common/src/main/res/layout/fragment_download_diagnostics.xml b/app-common/src/main/res/layout/fragment_download_diagnostics.xml
index 88b1ffb..b9a0bc2 100644
--- a/app-common/src/main/res/layout/fragment_download_diagnostics.xml
+++ b/app-common/src/main/res/layout/fragment_download_diagnostics.xml
@@ -17,26 +17,15 @@
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:textSize="20sp"
- android:layout_marginTop="20dp"
- android:layout_marginBottom="20dp"
- android:layout_marginStart="60dp"
- android:layout_marginEnd="60dp"
+ android:layout_marginTop="20sp"
+ android:layout_marginBottom="20sp"
+ android:layout_marginStart="60sp"
+ android:layout_marginEnd="60sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constrainedWidth="true"
app:layout_constraintTop_toTopOf="parent" />
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app-common/src/main/res/menu/fragment_profile_download.xml b/app-common/src/main/res/menu/fragment_profile_download.xml
new file mode 100644
index 0000000..f93ae8d
--- /dev/null
+++ b/app-common/src/main/res/menu/fragment_profile_download.xml
@@ -0,0 +1,21 @@
+
+
\ No newline at end of file
diff --git a/app-common/src/main/res/values-ja/strings.xml b/app-common/src/main/res/values-ja/strings.xml
index d25af49..fed185d 100644
--- a/app-common/src/main/res/values-ja/strings.xml
+++ b/app-common/src/main/res/values-ja/strings.xml
@@ -37,6 +37,11 @@
アクティベーションコード
確認コード (オプション)
IMEI (オプション)
+ 残りの容量: %s
+ QR コードをスキャン
+ ギャラリーから QR コードをスキャン
+ ダウンロード
+ eSIM のダウンロードに失敗しました。アクティベーションまたは QR コードを確認してください。
ダウンロードに失敗する可能性があります
残り容量が少ないため、ダウンロードに失敗する可能性があります。
ダウンロードウィザード
@@ -48,6 +53,7 @@
リムーバブル
内部
内部 - ポート: %d
+ eID:
有効なプロファイル:
空き容量:
eSIM プロファイルをどの方法でダウンロードしますか?
@@ -62,7 +68,6 @@
eSIM プロファイルをダウンロード中です
eSIM プロファイルをストレージに読み込み中です
エラー診断
- エラーコード: %s
最終の HTTP ステータス (サーバー): %d
最終の HTTP レスポンス (サーバー):
最終の HTTP 例外:
@@ -70,8 +75,6 @@
最終の APDU レスポンス (SIM) は成功しました
最終の APDU レスポンス (SIM) は失敗しました
最終の APDU 例外:
- 保存
- %s のエラー診断
新しいニックネーム
%s のプロファイルを削除してもよろしいですか?この操作は元に戻せません。
削除を確認するには「%s」を入力してください
@@ -89,10 +92,11 @@
eUICC 情報 (%s)
アクセスモード
リムーバブル
+ EID
eUICC OS のバージョン
グローバルプラットフォームのバージョン
SAS 認定番号
- Protected Profileのバージョン
+ 保護されたプロファイルのバージョン
NVRAM の空き容量 (eSIM プロファイルストレージ)
GSMA プロダクション証明書
GSMA テスト証明書
@@ -121,6 +125,8 @@
ログ
アプリの最新デバッグログを表示します
開発者オプション
+ 実験的なダウンロードウィザード
+ 実験的な新しいダウンロードウィザードを有効化します。まだ完全に機能していないことにご注意ください。
SM-DP+ TLS 証明書を無視する
SM-DP+ TLS 証明書を無視して任意の RSP を許可します
情報
diff --git a/app-common/src/main/res/values-zh-rCN/strings.xml b/app-common/src/main/res/values-zh-rCN/strings.xml
deleted file mode 100644
index 3bb0d04..0000000
--- a/app-common/src/main/res/values-zh-rCN/strings.xml
+++ /dev/null
@@ -1,137 +0,0 @@
-
-
- 在此设备上未检测到此应用程序可访问的可插拔 eUICC 卡。请插入兼容卡或 USB 读卡器。
- 此 eSIM 上还没有配置文件
- 未知
- 帮助
- 重新加载卡槽
- 逻辑卡槽 %d
- 已启用
- 已禁用
- 提供商:
- 类型:
- 启用
- 禁用
- 删除
- 重命名
- 等待 eSIM 芯片切换配置文件时超时。这可能是您手机基带固件中的一个错误。请尝试切换飞行模式、重新启动应用程序或重新启动手机
- 操作成功, 但是您手机的基带拒绝刷新。您可能需要切换飞行模式或重新启动,以便使用新的配置文件。
- 无法切换到新的 eSIM 配置文件。
- 昵称不能超过 64 个字符
- 已复制 ICCID 到剪贴板
- 选择卡槽
- 选择
- 授予 USB 权限
- 需要获得访问 USB 智能卡读卡器的权限。
- 无法通过 USB 智能卡读卡器连接到 eSIM。
- 长时间运行的后台任务
- 正在下载 eSIM 配置文件
- 无法下载 eSIM 配置文件
- 正在重命名 eSIM 配置文件
- 无法重命名 eSIM 配置文件
- 正在删除 eSIM 配置文件
- 无法删除 eSIM 配置文件
- 正在切换 eSIM 配置文件
- 无法切换 eSIM 配置文件
- 添加新 eSIM
- 服务器 (RSP / SM-DP+)
- 激活码
- 确认码 (可选)
- IMEI (可选)
- 本次下载可能会失败
- 当前芯片的剩余空间不足,可能导致配置下载失败。\n是否继续下载?
- 新昵称
- 您确定要删除 %s 吗?此操作是不可逆的。
- 请输入\'%s\'以确认删除
- 通知列表
- 通知列表 (%s)
- 管理通知
- eSIM 配置文件可以在下载、删除、启用或禁用时向运营商发送通知。此处列出了要发送的这些通知的队列。\n\n在\"设置\"中,您可以指定是否自动发送每种类型的通知。请注意,即使通知已发送,也不会自动从记录中删除,除非队列空间不足。\n\n在这里,您可以手动发送或删除每个待处理的通知。
- 已下载
- 已删除
- 已启用
- 已禁用
- 处理
- 删除
- 保存日志
- %s 的日志
- 设置
- 通知
- 操作 eSIM 配置文件会向运营商发送通知。根据需要在此处微调此行为。
- 下载
- 发送 下载 配置文件的通知
- 删除
- 发送 删除 配置文件的通知
- 切换
- 发送 切换 配置文件的通知\n注意,这种类型的通知是不可靠的。
- 高级
- 允许 禁用/删除 已启用的配置文件
- 默认情况下,此应用程序会阻止您禁用可插拔 eSIM 中已启用的配置文件。\n因为这样做 有时 会使其无法访问。\n勾选此框以 移除 此保护措施。
- 记录详细日志
- 详细日志中包含敏感信息,开启此功能后请仅与你信任的人共享你的日志。
- 日志
- 查看应用程序的最新调试日志
- 信息
- App 版本
- 源码
- 测试
- 准备中
- 可用
- 下载向导
- 返回
- 下一步
- 请选择或确认下载目标 eSIM 卡槽:
- 逻辑卡槽 %d
- 类型:
- 可插拔
- 内置
- 内置, 端口 %d
- 当前配置文件:
- 剩余空间:
- 您想要如何下载 eSIM 配置文件?
- 用相机扫描二维码
- 从图库选择二维码
- 手动输入
- 请输入或确认下载 eSIM 的详细信息:
- 正在下载您的 eSIM...
- 准备中
- 正在连接服务器
- 正在向服务器认证您的设备
- 正在下载 eSIM 配置文件
- 正在写入 eSIM 配置文件
- 错误诊断
- 错误代码: %s
- 上次 HTTP 状态码 (来自服务器): %d
- 上次 HTTP 应答 (来自服务器):
- 上次 HTTP 错误:
- 上次 APDU 应答 (来自 SIM): %s
- 上次 APDU 应答 (来自 SIM) 是成功的
- 上次 APDU 应答 (来自 SIM) 是失败的
- 上次 APDU 错误:
- 保存
- %s 的错误诊断
- eUICC 详情
- eUICC 详情 (%s)
- 访问方式
- 可插拔
- eUICC OS 版本
- GlobalPlatform 版本
- SAS 认证号码
- Protected Profile 版本
- NVRAM 剩余空间 (eSIM 存储容量)
- GSMA 生产环境证书
- GSMA 测试环境证书
- 兼容
- 不兼容
- 是
- 否
- 还有 %d 步成为开发者
- 你现在是开发者了!
- 语言
- 选择 App 语言
- 开发者选项
- 显示未经过滤的配置文件列表
- 在配置文件列表中包括非生产环境的配置文件
- 无视 SM-DP+ 的 TLS 证书
- 允许 RSP 服务器使用任意证书
-
\ No newline at end of file
diff --git a/app-common/src/main/res/values/strings.xml b/app-common/src/main/res/values/strings.xml
index 4a9f529..a5a05ab 100644
--- a/app-common/src/main/res/values/strings.xml
+++ b/app-common/src/main/res/values/strings.xml
@@ -53,6 +53,11 @@
Activation Code
Confirmation Code (Optional)
IMEI (Optional)
+ Space remaining: %s
+ Scan QR Code
+ Scan QR Code from Gallery
+ Download
+ Failed to download eSIM. Check your activation / QR code.
This download may fail
This download may fail due to low remaining capacity.
@@ -66,7 +71,7 @@
Removable
Internal
Internal, port %d
- eID:
+ eID:
Active Profile:
Free Space:
How would you like to download the eSIM profile?
@@ -81,7 +86,6 @@
Downloading eSIM profile
Loading eSIM profile into storage
Error diagnostics
- Error code: %s
Last HTTP status (from server): %d
Last HTTP response (from server):
Last HTTP exception:
@@ -89,8 +93,6 @@
Last APDU response (from SIM) is successful
Last APDU response (from SIM) is a failure
Last APDU exception:
- Save
- Diagnostics at %s
New nickname
@@ -114,7 +116,7 @@
eUICC Info (%s)
Access Mode
Removable
- EID
+ EID
eUICC OS Version
GlobalPlatform Version
SAS Accreditation Number
@@ -154,10 +156,12 @@
Logs
View recent debug logs of the application
Developer Options
+ Experimental Download Wizard
+ Enable the experimental new download wizard. Note that it is not fully working yet.
Show unfiltered profile list
Include non-production profiles in the list
Ignore SM-DP+ TLS certificate
- Accept any TLS certificate used by the RSP server
+ Ignore SM-DP+ TLS certificate, allow any RSP
Info
App Version
Source Code
diff --git a/app-common/src/main/res/xml/locale_config.xml b/app-common/src/main/res/xml/locale_config.xml
index e1a13f8..dd9d189 100644
--- a/app-common/src/main/res/xml/locale_config.xml
+++ b/app-common/src/main/res/xml/locale_config.xml
@@ -2,5 +2,4 @@
-
\ No newline at end of file
diff --git a/app-common/src/main/res/xml/pref_settings.xml b/app-common/src/main/res/xml/pref_settings.xml
index 1da1fd4..52815b9 100644
--- a/app-common/src/main/res/xml/pref_settings.xml
+++ b/app-common/src/main/res/xml/pref_settings.xml
@@ -57,6 +57,12 @@
app:title="@string/pref_developer"
app:iconSpaceReserved="false">
+
+
("pref_info_ara_m")?.apply {
- summary = firstSigner.encodeHex()
- setOnPreferenceClickListener {
- requireContext().getSystemService(ClipboardManager::class.java)!!
- .setPrimaryClip(ClipData.newPlainText("ara-m", summary))
- Toast.makeText(requireContext(), R.string.toast_ara_m_copied, Toast.LENGTH_SHORT)
- .show()
- true
- }
- }
- }
-}
\ No newline at end of file
diff --git a/app-unpriv/src/main/res/values-ja/strings.xml b/app-unpriv/src/main/res/values-ja/strings.xml
index 053a8d1..b8fac39 100644
--- a/app-unpriv/src/main/res/values-ja/strings.xml
+++ b/app-unpriv/src/main/res/values-ja/strings.xml
@@ -30,5 +30,4 @@
挿入された取り外し可能な eSIM がデバイス上で管理できるかどうかは判断できません。デバイスが OMAPI のサポートを宣言していないため、このデバイス上で取り外し可能な eSIM を管理することはサポートされていない可能性があります。\n%s
挿入された取り外し可能な eSIM がデバイス上で管理できるかどうかを確認できません。\n%s
ただし、eSIM プロファイルがすでに読み込まれている場合、有効化されたプロファイル自体は引き続き機能します。また、プロファイルが管理できない場合は、このデバイスで USB カードリーダーを介してプロファイルを管理できる可能性があります。
- ARA-M SHA-1 をクリップボードにコピーしました
diff --git a/app-unpriv/src/main/res/values-zh-rCN/strings.xml b/app-unpriv/src/main/res/values-zh-rCN/strings.xml
deleted file mode 100644
index 8d3060d..0000000
--- a/app-unpriv/src/main/res/values-zh-rCN/strings.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-
- 兼容性检查
- 打开 SIM 卡应用程序
- 系统功能
- 您的设备是否具有管理可插拔 eUICC 卡所需的所有功能。例如,基本的电话功能和 OMAPI 支持。
- 您的设备没有电话功能。
- 您的设备/系统未声明支持 OMAPI。这可能是由于缺少硬件支持,或者可能仅仅是由于缺少标志。请参阅以下两项检查以确定 OMAPI 是否确实受支持。
- OMAPI 连接
- 您的设备是否允许通过 OMAPI 访问 SIM 卡上的安全元件?
- 无法通过 OMAPI 检测到 SIM 卡的 Secure Element。如果您尚未在此设备中插入 SIM 卡,请尝试插入一张 SIM 卡并重试此检查。
- 已成功检测到可访问 Secure Element 的卡槽,但仅限于以下 SIM 卡槽:SIM%s。
- ISD-R 通道访问
- 您的设备是否支持通过 OMAPI 打开 eSIM 的 ISD-R (管理) 通道?
- 无法确定是否支持通过 OMAPI 进行 ISD-R 访问。如果尚未插入,您可能需要插入 SIM 卡 (任何 SIM 卡都可以) 重试。
- OMAPI 只能在以下 SIM 插槽上访问 ISD-R:SIM%s。
- 不在已知的 BUG 名单中
- 确保您的设备不存在与可插拔 eSIM 相关的错误。
- 糟糕,您的设备在访问可插拔 eSIM 时存在错误。这并不表示完全无法使用,但我们不保证该应用在您设备上的行为。
- USB 读卡器支持
- 您的设备是否支持通过 USB 读卡器管理 eSIM?
- 您可以通过此设备上的标准 USB CCID 读取器管理 eSIM (即使您在这里有任何其他检查项失败)。请插入读卡器,然后打开此应用程序以这种方式管理 eSIM。
- 您的设备不支持 USB 读卡器。
- 结论 (USB 读卡器以外)
- 根据之前的所有检查,您的设备与可插拔 eSIM 卡兼容的可能性有多大?
- 您可以使用和管理插入此设备的可插拔 eSIM 卡。
- 已知您的设备在访问可插拔 eSIM 卡时存在问题。\n%s
- 我们无法确定是否可以在您的设备上管理可插拔 eSIM 卡。不过,您的设备确实声明支持 OMAPI,因此它工作的可能性略高。\n%s
- 我们无法确定是否可以在您的设备上管理可插拔 eSIM 卡。由于您的设备未声明支持OMAPI,因此更有可能不支持在此设备上管理可插拔 eSIM。\n%s
- 我们无法确定是否可以在您的设备上管理可插拔 eSIM 卡。\n%s
- 然而,已经加载了eSIM配置文件的可插拔 eSIM 卡仍然可以工作; 即使无法在装置上直接管理可插拔 eSIM 卡中的配置文件,您仍然可以使用 USB 卡读卡器来管理配置文件。
- ARA-M SHA-1 已拷贝到剪贴板
-
\ No newline at end of file
diff --git a/app-unpriv/src/main/res/values/strings.xml b/app-unpriv/src/main/res/values/strings.xml
index 9d80b0e..3cf7347 100644
--- a/app-unpriv/src/main/res/values/strings.xml
+++ b/app-unpriv/src/main/res/values/strings.xml
@@ -4,12 +4,6 @@
Compatibility Check
Open SIM Toolkit
-
- ARA-M SHA-1
-
-
- ARA-M SHA-1 copied to clipboard
-
System Features
Whether your device has all the required features for managing removable eUICC cards. For example, basic telephony and OMAPI support.
diff --git a/app-unpriv/src/main/res/xml/pref_unprivileged_settings.xml b/app-unpriv/src/main/res/xml/pref_unprivileged_settings.xml
deleted file mode 100644
index 3281caf..0000000
--- a/app-unpriv/src/main/res/xml/pref_unprivileged_settings.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/java/im/angry/openeuicc/service/OpenEuiccService.kt b/app/src/main/java/im/angry/openeuicc/service/OpenEuiccService.kt
index 3c522c5..d626333 100644
--- a/app/src/main/java/im/angry/openeuicc/service/OpenEuiccService.kt
+++ b/app/src/main/java/im/angry/openeuicc/service/OpenEuiccService.kt
@@ -110,7 +110,7 @@ class OpenEuiccService : EuiccService(), OpenEuiccContextMarker {
telephonyManager.simSlotMapping = mappings
return
} catch (_: Exception) {
- // ignore
+
}
// Sometimes hardware supports one ordering but not the reverse
diff --git a/app/src/main/java/im/angry/openeuicc/ui/LuiActivity.kt b/app/src/main/java/im/angry/openeuicc/ui/LuiActivity.kt
index de2ca24..d7ac213 100644
--- a/app/src/main/java/im/angry/openeuicc/ui/LuiActivity.kt
+++ b/app/src/main/java/im/angry/openeuicc/ui/LuiActivity.kt
@@ -8,7 +8,6 @@ import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding
import im.angry.openeuicc.R
-import im.angry.openeuicc.ui.wizard.DownloadWizardActivity
class LuiActivity : AppCompatActivity() {
override fun onStart() {
@@ -26,11 +25,10 @@ class LuiActivity : AppCompatActivity() {
}
requireViewById(R.id.lui_skip).setOnClickListener { finish() }
- // TODO: Deactivate DownloadWizardActivity if there is no eSIM found.
+ // TODO: Deactivate LuiActivity if there is no eSIM found.
// TODO: Support pre-filled download info (from carrier apps); UX
requireViewById(R.id.lui_download).setOnClickListener {
- startActivity(Intent(this, DownloadWizardActivity::class.java))
- finish()
+ startActivity(Intent(this, DirectProfileDownloadActivity::class.java))
}
}
}
\ No newline at end of file
diff --git a/app/src/main/java/im/angry/openeuicc/ui/PrivilegedEuiccManagementFragment.kt b/app/src/main/java/im/angry/openeuicc/ui/PrivilegedEuiccManagementFragment.kt
index 12b60bd..688ae6c 100644
--- a/app/src/main/java/im/angry/openeuicc/ui/PrivilegedEuiccManagementFragment.kt
+++ b/app/src/main/java/im/angry/openeuicc/ui/PrivilegedEuiccManagementFragment.kt
@@ -17,16 +17,19 @@ class PrivilegedEuiccManagementFragment: EuiccManagementFragment() {
private var isMEP = false
private var isRemovable = false
+ override suspend fun doRefresh() {
+ super.doRefresh()
+ withEuiccChannel { channel ->
+ isMEP = channel.isMEP
+ isRemovable = channel.port.card.isRemovable
+ }
+ }
+
override suspend fun onCreateFooterViews(
parent: ViewGroup,
profiles: List
): List =
super.onCreateFooterViews(parent, profiles).let { footers ->
- withEuiccChannel { channel ->
- isMEP = channel.isMEP
- isRemovable = channel.port.card.isRemovable
- }
-
if (isMEP) {
val view = layoutInflater.inflate(R.layout.footer_mep, parent, false)
view.requireViewById