diff --git a/app-common/src/main/java/im/angry/openeuicc/core/LocalProfileAssistantWrapper.kt b/app-common/src/main/java/im/angry/openeuicc/core/LocalProfileAssistantWrapper.kt index b715ca0..aab9e63 100644 --- a/app-common/src/main/java/im/angry/openeuicc/core/LocalProfileAssistantWrapper.kt +++ b/app-common/src/main/java/im/angry/openeuicc/core/LocalProfileAssistantWrapper.kt @@ -54,9 +54,8 @@ class LocalProfileAssistantWrapper(orig: LocalProfileAssistant) : override fun euiccMemoryReset() = lpa.euiccMemoryReset() - override fun setNickname(iccid: String, nickname: String) { + override fun setNickname(iccid: String, nickname: String): Boolean = lpa.setNickname(iccid, nickname) - } override fun close() = lpa.close() diff --git a/app-common/src/main/java/im/angry/openeuicc/service/EuiccChannelManagerService.kt b/app-common/src/main/java/im/angry/openeuicc/service/EuiccChannelManagerService.kt index a20c8db..c4d16df 100644 --- a/app-common/src/main/java/im/angry/openeuicc/service/EuiccChannelManagerService.kt +++ b/app-common/src/main/java/im/angry/openeuicc/service/EuiccChannelManagerService.kt @@ -414,12 +414,16 @@ class EuiccChannelManagerService : LifecycleService(), OpenEuiccContextMarker { getString(R.string.task_profile_rename_failure), R.drawable.ic_task_rename ) { - euiccChannelManager.withEuiccChannel(slotId, portId) { channel -> + val res = euiccChannelManager.withEuiccChannel(slotId, portId) { channel -> channel.lpa.setNickname( iccid, name ) } + + if (!res) { + throw RuntimeException("Profile not renamed") + } } fun launchProfileDeleteTask( diff --git a/app-common/src/main/java/im/angry/openeuicc/ui/ProfileRenameFragment.kt b/app-common/src/main/java/im/angry/openeuicc/ui/ProfileRenameFragment.kt index a3e4571..8582278 100644 --- a/app-common/src/main/java/im/angry/openeuicc/ui/ProfileRenameFragment.kt +++ b/app-common/src/main/java/im/angry/openeuicc/ui/ProfileRenameFragment.kt @@ -14,7 +14,6 @@ import im.angry.openeuicc.common.R import im.angry.openeuicc.service.EuiccChannelManagerService.Companion.waitDone import im.angry.openeuicc.util.* import kotlinx.coroutines.launch -import net.typeblog.lpac_jni.LocalProfileAssistant class ProfileRenameFragment : BaseMaterialDialogFragment(), EuiccChannelFragmentMarker { companion object { @@ -96,49 +95,21 @@ class ProfileRenameFragment : BaseMaterialDialogFragment(), EuiccChannelFragment lifecycleScope.launch { ensureEuiccChannelManager() euiccChannelManagerService.waitForForegroundTask() - val res = euiccChannelManagerService.launchProfileRenameTask( + euiccChannelManagerService.launchProfileRenameTask( slotId, portId, requireArguments().getString("iccid")!!, name ).waitDone() - when (res) { - is LocalProfileAssistant.ProfileNameTooLongException -> { - Toast.makeText( - requireContext(), - R.string.profile_rename_too_long, - Toast.LENGTH_LONG - ).show() - } + if (parentFragment is EuiccProfilesChangedListener) { + (parentFragment as EuiccProfilesChangedListener).onEuiccProfilesChanged() + } - is LocalProfileAssistant.ProfileNameIsInvalidUTF8Exception -> { - Toast.makeText( - requireContext(), - R.string.profile_rename_encoding_error, - Toast.LENGTH_LONG - ).show() - } - - is Throwable -> { - Toast.makeText( - requireContext(), - R.string.profile_rename_failure, - Toast.LENGTH_LONG - ).show() - } - - else -> { - if (parentFragment is EuiccProfilesChangedListener) { - (parentFragment as EuiccProfilesChangedListener).onEuiccProfilesChanged() - } - - try { - dismiss() - } catch (e: IllegalStateException) { - // Ignored - } - } + try { + dismiss() + } catch (e: IllegalStateException) { + // Ignored } } } 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 9898558..bb299a3 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 @@ -8,7 +8,10 @@ import im.angry.openeuicc.OpenEuiccApplication import im.angry.openeuicc.common.R import im.angry.openeuicc.util.* -class SettingsActivity: AppCompatActivity(), EuiccChannelFragmentMarker { +class SettingsActivity: AppCompatActivity() { + private val appContainer + get() = (application as OpenEuiccApplication).appContainer + override fun onCreate(savedInstanceState: Bundle?) { enableEdgeToEdge() super.onCreate(savedInstanceState) diff --git a/app-common/src/main/java/im/angry/openeuicc/ui/wizard/DownloadWizardMethodSelectFragment.kt b/app-common/src/main/java/im/angry/openeuicc/ui/wizard/DownloadWizardMethodSelectFragment.kt index 6203364..d329048 100644 --- a/app-common/src/main/java/im/angry/openeuicc/ui/wizard/DownloadWizardMethodSelectFragment.kt +++ b/app-common/src/main/java/im/angry/openeuicc/ui/wizard/DownloadWizardMethodSelectFragment.kt @@ -1,7 +1,6 @@ package im.angry.openeuicc.ui.wizard import android.app.AlertDialog -import android.content.ClipboardManager import android.graphics.BitmapFactory import android.os.Bundle import android.view.LayoutInflater @@ -9,7 +8,6 @@ import android.view.View import android.view.ViewGroup import android.widget.ImageView import android.widget.TextView -import android.widget.Toast import androidx.activity.result.contract.ActivityResultContracts import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.DividerItemDecoration @@ -70,9 +68,6 @@ class DownloadWizardMethodSelectFragment : DownloadWizardActivity.DownloadWizard DownloadMethod(R.drawable.ic_gallery_black, R.string.download_wizard_method_gallery) { gallerySelectorLauncher.launch("image/*") }, - DownloadMethod(R.drawable.ic_paste_go, R.string.download_wizard_method_clipboard) { - handleLoadFromClipboard() - }, DownloadMethod(R.drawable.ic_edit, R.string.download_wizard_method_manual) { gotoNextFragment(DownloadWizardDetailsFragment()) } @@ -108,22 +103,6 @@ class DownloadWizardMethodSelectFragment : DownloadWizardActivity.DownloadWizard return view } - private fun handleLoadFromClipboard() { - val clipboard = requireContext().getSystemService(ClipboardManager::class.java) - val text = clipboard.primaryClip?.getItemAt(0)?.text - - if (text == null) { - Toast.makeText( - requireContext(), - R.string.profile_download_no_lpa_string, - Toast.LENGTH_SHORT - ).show() - return - } - - processLpaString(text.toString()) - } - private fun processLpaString(s: String) { val components = s.split("$") if (components.size < 3 || components[0] != "LPA:1") { 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 3723aea..f16a086 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 @@ -57,15 +57,13 @@ class DownloadWizardSlotSelectFragment : DownloadWizardActivity.DownloadWizardSt super.beforeNext() if (adapter.selected.freeSpace < LOW_NVRAM_THRESHOLD) { - val activity = requireActivity() - 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) { _, _ -> - activity.finish() + requireActivity().finish() } show() } diff --git a/app-common/src/main/res/drawable/ic_paste_go.xml b/app-common/src/main/res/drawable/ic_paste_go.xml deleted file mode 100644 index 7536fff..0000000 --- a/app-common/src/main/res/drawable/ic_paste_go.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/app-common/src/main/res/layout/fragment_slot_select.xml b/app-common/src/main/res/layout/fragment_slot_select.xml new file mode 100644 index 0000000..b818b80 --- /dev/null +++ b/app-common/src/main/res/layout/fragment_slot_select.xml @@ -0,0 +1,27 @@ + + + + + + + + \ No newline at end of file diff --git a/app-common/src/main/res/menu/fragment_slot_select.xml b/app-common/src/main/res/menu/fragment_slot_select.xml new file mode 100644 index 0000000..e129008 --- /dev/null +++ b/app-common/src/main/res/menu/fragment_slot_select.xml @@ -0,0 +1,9 @@ + + + + \ 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 1f1f389..dacfd68 100644 --- a/app-common/src/main/res/values-ja/strings.xml +++ b/app-common/src/main/res/values-ja/strings.xml @@ -18,6 +18,8 @@ 新しい eSIM プロファイルに切り替えることができません。 ニックネームは 64 文字以内にしてください ICCID をクリップボードにコピーしました + スロットを選択 + 選択 USB の権限を許可 USB スマートカードリーダーにアクセスするには許可が必要です。 USB スマートカードリーダー経由で eSIM に接続できません。 diff --git a/app-common/src/main/res/values-zh-rCN/strings.xml b/app-common/src/main/res/values-zh-rCN/strings.xml index d9d6c77..b97969d 100644 --- a/app-common/src/main/res/values-zh-rCN/strings.xml +++ b/app-common/src/main/res/values-zh-rCN/strings.xml @@ -19,6 +19,8 @@ 无法切换到新的 eSIM 配置文件。 昵称不能超过 64 个字符 已复制 ICCID 到剪贴板 + 选择卡槽 + 选择 授予 USB 权限 需要获得访问 USB 智能卡读卡器的权限。 无法通过 USB 智能卡读卡器连接到 eSIM。 diff --git a/app-common/src/main/res/values/strings.xml b/app-common/src/main/res/values/strings.xml index 39d2c43..bd3b3af 100644 --- a/app-common/src/main/res/values/strings.xml +++ b/app-common/src/main/res/values/strings.xml @@ -33,6 +33,9 @@ ICCID copied to clipboard EID copied to clipboard + Select Slot + Select + Grant USB permission Permission is needed to access the USB smart card reader. Cannot connect to eSIM via a USB smart card reader. @@ -55,9 +58,8 @@ This download may fail This download may fail due to low remaining capacity. - No LPA string found in clipboard Incorrect LPA String - Could not parse QR code or clipboard content as an LPA string for downloading eSIMs. + The LPA string could not be parsed Download Wizard Back @@ -73,7 +75,6 @@ How would you like to download the eSIM profile? Scan a QR code with camera Load a QR code from gallery - Load from Clipboard Enter manually Input or confirm details for downloading your eSIM: Downloading your eSIM… @@ -97,9 +98,6 @@ Logs have been saved to the selected path. Would you like to share the log through another app? New nickname - Failed to encode nickname as UTF-8 - Nickname is too long - Unknown failure when renaming profile Are you sure you want to delete the profile %s? This operation is irreversible. Type \'%s\' here to confirm deletion diff --git a/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/LocalProfileAssistant.kt b/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/LocalProfileAssistant.kt index 48ab1c5..4ff65fa 100644 --- a/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/LocalProfileAssistant.kt +++ b/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/LocalProfileAssistant.kt @@ -12,10 +12,6 @@ interface LocalProfileAssistant { val lastApduException: Exception?, ) : Exception("Failed to download profile") - class ProfileRenameException() : Exception("Failed to rename profile") - class ProfileNameTooLongException() : Exception("Profile name too long") - class ProfileNameIsInvalidUTF8Exception() : Exception("Profile name is invalid UTF-8") - val valid: Boolean val profiles: List val notifications: List @@ -44,14 +40,9 @@ interface LocalProfileAssistant { fun euiccMemoryReset() - /** - * Nickname must be valid UTF-8 and shorter than 64 chars. - * - * May throw one of: ProfileRenameException, ProfileNameTooLongException, ProfileNameIsInvalidUTF8Exception - */ fun setNickname( iccid: String, nickname: String - ) + ): Boolean fun close() } \ No newline at end of file diff --git a/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/LpacJni.kt b/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/LpacJni.kt index d50c1c1..8e3f53a 100644 --- a/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/LpacJni.kt +++ b/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/LpacJni.kt @@ -19,7 +19,7 @@ internal object LpacJni { external fun es10cEnableProfile(handle: Long, iccid: String, refresh: Boolean): Int external fun es10cDisableProfile(handle: Long, iccid: String, refresh: Boolean): Int external fun es10cDeleteProfile(handle: Long, iccid: String): Int - external fun es10cSetNickname(handle: Long, iccid: String, nickNullTerminated: ByteArray): Int + external fun es10cSetNickname(handle: Long, iccid: String, nick: String): Int // es10b external fun es10bListNotification(handle: Long): Long // A native pointer to a linked list. Handle with linked list-related methods below. May be 0 (null) diff --git a/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/impl/LocalProfileAssistantImpl.kt b/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/impl/LocalProfileAssistantImpl.kt index 0330d82..b617f2b 100644 --- a/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/impl/LocalProfileAssistantImpl.kt +++ b/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/impl/LocalProfileAssistantImpl.kt @@ -239,23 +239,8 @@ class LocalProfileAssistantImpl( } == 0 @Synchronized - override fun setNickname(iccid: String, nickname: String) { - val encoded = try { - Charsets.UTF_8.encode(nickname).array() - } catch (e: CharacterCodingException) { - throw LocalProfileAssistant.ProfileNameIsInvalidUTF8Exception() - } - - if (encoded.size >= 64) { - throw LocalProfileAssistant.ProfileNameTooLongException() - } - - val encodedNullTerminated = encoded + byteArrayOf(0) - - if (LpacJni.es10cSetNickname(contextHandle, iccid, encodedNullTerminated) != 0) { - throw LocalProfileAssistant.ProfileRenameException() - } - } + override fun setNickname(iccid: String, nickname: String): Boolean = + LpacJni.es10cSetNickname(contextHandle, iccid, nickname) == 0 override fun euiccMemoryReset() { LpacJni.es10cEuiccMemoryReset(contextHandle) diff --git a/libs/lpac-jni/src/main/jni/lpac-jni/lpac-jni.c b/libs/lpac-jni/src/main/jni/lpac-jni/lpac-jni.c index e438107..8f4752b 100644 --- a/libs/lpac-jni/src/main/jni/lpac-jni/lpac-jni.c +++ b/libs/lpac-jni/src/main/jni/lpac-jni/lpac-jni.c @@ -205,16 +205,16 @@ Java_net_typeblog_lpac_1jni_LpacJni_es10cDisableProfile(JNIEnv *env, jobject thi JNIEXPORT jint JNICALL Java_net_typeblog_lpac_1jni_LpacJni_es10cSetNickname(JNIEnv *env, jobject thiz, jlong handle, - jstring iccid, jbyteArray nick) { + jstring iccid, jstring nick) { struct euicc_ctx *ctx = (struct euicc_ctx *) handle; const char *_iccid = NULL; - jbyte *_nick = NULL; + const char *_nick = NULL; int ret; _iccid = (*env)->GetStringUTFChars(env, iccid, NULL); - _nick = (*env)->GetByteArrayElements(env, nick, NULL); - ret = es10c_set_nickname(ctx, _iccid, (const char *) _nick); - (*env)->ReleaseByteArrayElements(env, nick, _nick, JNI_ABORT); + _nick = (*env)->GetStringUTFChars(env, nick, NULL); + ret = es10c_set_nickname(ctx, _iccid, _nick); + (*env)->ReleaseStringUTFChars(env, nick, _nick); (*env)->ReleaseStringUTFChars(env, iccid, _iccid); return ret; }