API های eUICC

در اندروید ۹، APIهای مدیریت پروفایل (public و @SystemApi) از طریق کلاس EuiccManager در دسترس هستند. APIهای ارتباطی eUICC (@SystemApi only) از طریق کلاس EuiccCardManager در دسترس هستند.

درباره eUICC

همانطور که در شکل 1 نشان داده شده است، اپراتورها می‌توانند با استفاده از EuiccManager برای مدیریت پروفایل‌ها، برنامه‌های اپراتور ایجاد کنند. برنامه‌های اپراتور نیازی به برنامه‌های سیستمی ندارند، اما باید امتیازات اپراتوری اعطا شده توسط پروفایل‌های eUICC را داشته باشند. یک برنامه LPA (LUI و LPA backend) برای فراخوانی @SystemApi باید یک برنامه سیستمی باشد (یعنی در تصویر سیستم گنجانده شده باشد).

گوشی اندروید با اپلیکیشن اپراتور و OEM LPA

شکل ۱. گوشی‌های اندروید با اپلیکیشن اپراتور و OEM LPA

علاوه بر منطق فراخوانی EuiccCardManager و ارتباط با eUICC، برنامه‌های LPA باید موارد زیر را پیاده‌سازی کنند:

  • کلاینت SM-DP+ برای احراز هویت و دانلود پروفایل‌ها با سرور SM-DP+ در ارتباط است
  • [اختیاری] SM-DS برای دریافت پروفایل‌های قابل دانلود بیشتر
  • مدیریت اعلان‌ها برای ارسال اعلان‌ها به سرور جهت به‌روزرسانی وضعیت پروفایل
  • [اختیاری] مدیریت اسلات‌ها شامل جابجایی بین منطق eSIM و pSIM. این مورد در صورتی اختیاری است که گوشی فقط تراشه eSIM داشته باشد.
  • سیم‌کارت الکترونیکی (eSIM) از طریق سیم‌کارت

اگرچه بیش از یک برنامه LPA می‌تواند در یک تلفن اندروید وجود داشته باشد، اما بر اساس اولویت تعریف شده در فایل AndroidManifest.xml هر برنامه، فقط یک LPA می‌تواند به عنوان LPA فعال واقعی انتخاب شود.

از EuiccManager استفاده کنید

رابط‌های برنامه‌نویسی کاربردی LPA از طریق EuiccManager (تحت بسته android.telephony.euicc ) عمومی هستند. یک برنامه اپراتور می‌تواند نمونه EuiccManager را دریافت کند و متدهای موجود در EuiccManager را برای دریافت اطلاعات eUICC و مدیریت اشتراک‌ها (که در اسناد GSMA RSP به عنوان پروفایل شناخته می‌شوند) به عنوان نمونه‌های SubscriptionInfo فراخوانی کند.

برای فراخوانی APIهای عمومی شامل عملیات دانلود، تغییر و حذف اشتراک، برنامه‌ی اپراتور باید امتیازات لازم را داشته باشد. امتیازات اپراتور توسط اپراتور تلفن همراه در فراداده‌ی پروفایل اضافه می‌شود. رابط برنامه‌نویسی کاربردی eUICC قوانین امتیازات اپراتور را بر این اساس اعمال می‌کند.

پلتفرم اندروید قوانین خط‌مشی پروفایل را مدیریت نمی‌کند. اگر یک قانون خط‌مشی در فراداده پروفایل تعریف شده باشد، LPA می‌تواند نحوه مدیریت دانلود و نصب پروفایل را انتخاب کند. برای مثال، یک LPA شخص ثالث OEM می‌تواند قوانین خط‌مشی را با استفاده از یک کد خطای ویژه مدیریت کند (کد خطا از LPA OEM به پلتفرم منتقل می‌شود، سپس پلتفرم کد را به LUI OEM ارسال می‌کند).

برای اطلاعات بیشتر در مورد API های پروفایل های چندگانه فعال، به Multiple enabled profiles مراجعه کنید.

رابط‌های برنامه‌نویسی کاربردی (API)

APIهای زیر را می‌توانید در مستندات مرجع EuiccManager و EuiccManager.java بیابید.

دریافت نمونه (عمومی)

نمونه EuiccManager را از طریق Context#getSystemService دریافت می‌کند. برای جزئیات بیشتر، به getSystemService مراجعه کنید.

EuiccManager mgr = (EuiccManager) context.getSystemService(Context.EUICC_SERVICE);

فعال بودن تیک (عمومی)

بررسی می‌کند که آیا اشتراک تعبیه‌شده فعال است یا خیر. این مورد باید قبل از دسترسی به APIهای LPA بررسی شود. برای جزئیات بیشتر، به isEnabled مراجعه کنید.

boolean isEnabled = mgr.isEnabled();
if (!isEnabled) {
    return;
}

دریافت عیدی (عمومی)

شناسه EID مربوط به سخت‌افزار eUICC را دریافت می‌کند. اگر eUICC آماده نباشد، ممکن است مقدار آن null باشد. تماس‌گیرنده باید امتیاز اپراتور یا مجوز READ_PRIVILEGED_PHONE_STATE را داشته باشد. برای جزئیات بیشتر، به getEid مراجعه کنید.

String eid = mgr.getEid();
if (eid == null) {
  // Handle null case.
}

دریافت EuiccInfo (عمومی)

اطلاعاتی در مورد eUICC دریافت می‌کند. این شامل نسخه سیستم عامل است. برای جزئیات بیشتر، به getEuiccInfo مراجعه کنید.

EuiccInfo info = mgr.getEuiccInfo();
String osVer = info.getOsVersion();

اشتراک دانلود (عمومی)

اشتراک داده شده (که در اسناد GSMA RSP به عنوان "پروفایل" شناخته می‌شود) را دانلود می‌کند. این اشتراک می‌تواند از یک کد فعال‌سازی ایجاد شود. به عنوان مثال، یک کد فعال‌سازی می‌تواند از یک کد QR تجزیه شود. دانلود یک اشتراک یک عملیات ناهمزمان است.

تماس‌گیرنده یا باید مجوز WRITE_EMBEDDED_SUBSCRIPTIONS را داشته باشد یا امتیازات اپراتور برای اشتراک هدف را داشته باشد. برای جزئیات بیشتر، به downloadSubscription مراجعه کنید.

// Register receiver.
String action = "download_subscription";
BroadcastReceiver receiver =
        new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (!action.equals(intent.getAction())) {
                    return;
                }
                resultCode = getResultCode();
                detailedCode = intent.getIntExtra(
                    EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE,
                    0 /* defaultValue*/);
                resultIntent = intent;
            }
        };
context.registerReceiver(
        receiver,
        new IntentFilter(action),
        "example.broadcast.permission" /* broadcastPermission*/, null /* handler */);

// Download subscription asynchronously.
DownloadableSubscription sub =
        DownloadableSubscription.forActivationCode(code /* encodedActivationCode*/);
Intent intent = new Intent(action);
PendingIntent callbackIntent = PendingIntent.getBroadcast(
        getContext(), 0 /* requestCode */, intent, PendingIntent.FLAG_UPDATE_CURRENT);
mgr.downloadSubscription(sub, true /* switchAfterDownload */, callbackIntent);

اشتراک سوئیچ (عمومی)

اشتراک داده شده را فعال می‌کند (به آن سوئیچ می‌کند). تماس‌گیرنده باید یا WRITE_EMBEDDED_SUBSCRIPTIONS داشته باشد یا امتیازات اپراتور را برای اشتراک فعال فعلی و اشتراک هدف داشته باشد. برای جزئیات بیشتر، به switchToSubscription مراجعه کنید.

// Register receiver.
String action = "switch_to_subscription";
BroadcastReceiver receiver =
        new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (!action.equals(intent.getAction())) {
                    return;
                }
                resultCode = getResultCode();
                detailedCode = intent.getIntExtra(
                    EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE, 0 /* defaultValue*/);
                resultIntent = intent;
            }
        };
context.registerReceiver(receiver, new IntentFilter(action),
        "example.broadcast.permission" /* broadcastPermission*/, null /* handler */);

// Switch to a subscription asynchronously.
Intent intent = new Intent(action);
PendingIntent callbackIntent = PendingIntent.getBroadcast(
        getContext(), 0 /* requestCode */, intent, PendingIntent.FLAG_UPDATE_CURRENT);
mgr.switchToSubscription(1 /* subscriptionId */, callbackIntent);

اشتراک را با پورت (عمومی) تغییر دهید

(از اندروید ۱۳ موجود است) با استفاده از اندیس پورت مشخص شده، اشتراک داده شده را فعال می‌کند. تماس‌گیرنده یا باید WRITE_EMBEDDED_SUBSCRIPTIONS داشته باشد یا برای اشتراک فعال فعلی و اشتراک هدف، امتیاز اپراتور را داشته باشد. برای جزئیات بیشتر، به switchToSubscription مراجعه کنید.

// Register receiver.
String action = "switch_to_subscription";
BroadcastReceiver receiver =
        new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (!action.equals(intent.getAction())) {
                    return;
                }
                resultCode = getResultCode();
                detailedCode = intent.getIntExtra(
                    EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE, 0 /* defaultValue*/);
                resultIntent = intent;
            }
        };
context.registerReceiver(receiver, new IntentFilter(action),
        "example.broadcast.permission" /* broadcastPermission*/, null /* handler */);

// Switch to a subscription asynchronously.
Intent intent = new Intent(action);
PendingIntent callbackIntent = PendingIntent.getBroadcast(
        getContext(), 0 /* requestCode */, intent, PendingIntent.FLAG_UPDATE_CURRENT);
mgr.switchToSubscription(1 /* subscriptionId */, 0 /*portIndex*/, callbackIntent);

آیا درگاه سیم‌کارت در دسترس است (عمومی)

public boolean isSimPortAvailable(int portIndex)

(از اندروید ۱۳ موجود است) برمی‌گرداند که آیا شاخص پورت عبوری در دسترس است یا خیر. یک پورت در صورتی در دسترس است که هیچ اشتراکی روی آن فعال نباشد یا برنامه‌ی فراخوانی، امتیاز اپراتور را روی اشتراک نصب شده روی پورت انتخاب شده داشته باشد. برای جزئیات بیشتر، به isSimPortAvailable مراجعه کنید.

حذف اشتراک (عمومی)

اشتراکی را با شناسه اشتراک حذف می‌کند. اگر اشتراک در حال حاضر فعال باشد، ابتدا غیرفعال می‌شود. تماس‌گیرنده باید یا WRITE_EMBEDDED_SUBSCRIPTIONS یا امتیازات اپراتور را برای اشتراک هدف داشته باشد. برای جزئیات بیشتر، به deleteSubscription مراجعه کنید.

// Register receiver.
String action = "delete_subscription";
BroadcastReceiver receiver =
        new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (!action.equals(intent.getAction())) {
                    return;
                }
                resultCode = getResultCode();
                detailedCode = intent.getIntExtra(
                    EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE,
                    0 /* defaultValue*/);
                resultIntent = intent;
            }
        };
context.registerReceiver(receiver, new IntentFilter(action),
        "example.broadcast.permission" /* broadcastPermission*/,
        null /* handler */);

// Delete a subscription asynchronously.
Intent intent = new Intent(action);
PendingIntent callbackIntent = PendingIntent.getBroadcast(
        getContext(), 0 /* requestCode */, intent, PendingIntent.FLAG_UPDATE_CURRENT);
mgr.deleteSubscription(1 /* subscriptionId */, callbackIntent);

پاک کردن همه اشتراک‌ها (API سیستم)

تمام اشتراک‌ها را در یک دستگاه پاک می‌کند. از اندروید ۱۱ به بعد، باید یک مقدار شمارشی EuiccCardManager#ResetOption ارائه دهید تا مشخص شود که آیا تمام اشتراک‌های آزمایشی، عملیاتی یا هر دو نوع پاک شوند. فراخوانی‌کننده باید مجوز WRITE_EMBEDDED_SUBSCRIPTIONS را داشته باشد.

// Register receiver.
String action = "delete_subscription";
BroadcastReceiver receiver =
        new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (!action.equals(intent.getAction())) {
                    return;
                }
                resultCode = getResultCode();
                detailedCode = intent.getIntExtra(
                    EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE,
                    0 /* defaultValue*/);
                resultIntent = intent;
            }
        };
context.registerReceiver(receiver, new IntentFilter(action),
        "example.broadcast.permission" /* broadcastPermission*/,
        null /* handler */);

// Erase all operational subscriptions asynchronously.
Intent intent = new Intent(action);
PendingIntent callbackIntent = PendingIntent.getBroadcast(
        getContext(), 0 /* requestCode */, intent, PendingIntent.FLAG_UPDATE_CURRENT);
mgr.eraseSubscriptions(
        EuiccCardManager.RESET_OPTION_DELETE_OPERATIONAL_PROFILES, callbackIntent);

شروع فعالیت حل اختلاف (عمومی)

یک فعالیت را برای حل یک خطای قابل حل توسط کاربر آغاز می‌کند. اگر عملیاتی EuiccManager#EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR را برگرداند، این متد می‌تواند برای درخواست از کاربر جهت حل مشکل فراخوانی شود. این متد فقط یک بار برای یک خطای خاص قابل فراخوانی است.

...
mgr.startResolutionActivity(getActivity(), 0 /* requestCode */, resultIntent, callbackIntent);

ثابت‌ها

برای مشاهده‌ی فهرستی از ثابت‌های public در EuiccManager ، به بخش «ثابت‌ها» مراجعه کنید.