شناسایی سیمکارت داخلی و سیمکارت فیزیکی
درحال شناسایی کارتها
دستگاههای Android دارای سیمکارت و سیمکارت داخلی از شناسههای زیر در میاناهای برنامهسازی کاربردی تلفن استفاده میکنند، ازجمله [`TelephonyManager`](/reference/android/telephony/TelephonyManager) و [`SubscriptionManager`](/reference/android/telephony/SubscriptionManager): * شناسه اشتراک: شناسه یکتا برای اشتراک تلفن همراه. * شناسه یا نمایه شکاف منطقی: نمایه یکتایی که به شکاف سیمکارت منطقی اشاره دارد. شناسههای شکاف منطقی از ۰ شروع میشود و بسته به تعداد شکافهای فعال پشتیبانیشده در دستگاه افزایش مییابد. برای مثال، دستگاه دوسیمکارته معمولاً شیار ۰ و شیار ۱ دارد. اگر دستگاهی چند شکاف فیزیکی داشته باشد اما فقط از یک شکاف فعال پشتیبانی کند، فقط شناسه شکاف منطقی ۰ را خواهد داشت. * شناسه یا نمایه شکاف فیزیکی: نمایه یکتایی که به شکاف سیمکارت فیزیکی اشاره دارد. شناسههای شکاف فیزیکی از ۰ شروع میشود و بسته به تعداد شکافهای فیزیکی دستگاه افزایش مییابد. این با تعداد شکافهای منطقیای که دستگاه دارد متفاوت است، که با تعداد شکافهای فعالی که دستگاه قادر به استفاده از آنها است مطابقت دارد. برای مثال، دستگاهی که بین حالت دوسیمکارته و تکسیمکارته جابهجا میشود ممکن است همیشه دو شیار فیزیکی داشته باشد، اما در حالت تکسیمکارته فقط یک شیار منطقی خواهد داشت. * شناسه کارت: شناسه یکتایی که برای شناسایی UiccCard استفاده میشود.  در نمودار بالا: * دستگاه دو شکاف منطقی دارد. * در شکاف فیزیکی ۰، یک کارت UICC فیزیکی با نمایه فعال وجود دارد. * در شیار فیزیکی ۲، یک eUICC با نمایه فعال وجود دارد. * شیار فیزیکی ۱ درحالحاضر استفاده نمیشود.  در نمودار بالا: * دستگاه سه جایگاه منطقی دارد. * در شکاف فیزیکی ۰، یک کارت UICC فیزیکی با نمایه فعال وجود دارد. * در شکاف فیزیکی ۱، یک eUICC وجود دارد که دو نمایه بارگیریشده دارد و هر دو بااستفاده از MEP (چند نمایه فعالشده) فعال هستند.
نمای کلی پروتکل سیپ
Android یک API ارائه میدهد که از پروتکل سیپ (SIP) پشتیبانی میکند. این به شما امکان میدهد ویژگیهای تلفن اینترنتی مبتنی بر SIP را به برنامههایتان اضافه کنید. Android شامل پشته کامل پروتکل SIP و خدمات مدیریت تماس یکپارچه است که به برنامهها اجازه میدهد بهراحتی تماسهای صوتی ورودی و خروجی را راهاندازی کنند، بدون اینکه نیاز باشد جلسات، ارتباطات سطح انتقال، یا ضبط یا بازپخش صدا را مستقیماً مدیریت کنند.
در اینجا نمونههایی از انواع برنامههایی که ممکن است از SIP API استفاده کنند آورده شده است:
- کنفرانس ویدیویی
- پیام رسانی فوری
الزامات و محدودیتها
الزامات توسعه برنامه SIP در اینجا آمده است:
- باید دستگاه همراهی داشته باشید که Android نسخه ۲.۳ یا بالاتر داشته باشد.
- SIP ازطریق اتصال داده بیسیم اجرا میشود، بنابراین دستگاهتان باید اتصال داده داشته باشد (با سرویس داده تلفن همراه یا Wi-Fi). این یعنی نمیتوانید در AVD آزمایش کنید—فقط میتوانید در دستگاه فیزیکی آزمایش کنید. برای جزئیات، به آزمایش کردن برنامههای SIP مراجعه کنید.
- هر شرکتکننده در جلسه ارتباطی برنامه باید حساب SIP داشته باشد. ارائهدهندگان SIP مختلفی وجود دارند که حساب SIP ارائه میدهند.
توجه: کتابخانه android.net.sip از تماسهای ویدیویی پشتیبانی نمیکند. اگر میخواهید تماس VOIP را بااستفاده از پشته SIP مانند
android.net.sip پیادهسازی کنید، به یکی از جایگزینهای متنباز مدرن
بهعنوان مبنای هرگونه پیادهسازی تماس VOIP نگاه کنید. یا میتوانید
ConnectionService
API را پیادهسازی کنید تا این تماسها را بهطور کامل در برنامه «شمارهگیر» دستگاه
ادغام کنید.
کلاسها و رابطهای SIP API
در اینجا خلاصهای از کلاسها و یک میانای
(SipRegistrationListener) که در Android SIP
API گنجانده شده است ارائه شده است:
| کلاس/میانا | شرح |
|---|---|
SipAudioCall |
تماس صوتی اینترنتی را ازطریق SIP مدیریت میکند. |
SipAudioCall.Listener |
شنونده رویدادهای مربوط به تماس SIP، مثلاً وقتی تماسی دریافت میشود («درحال زنگ خوردن») یا تماسی برقرار میشود («درحال تماس گرفتن»). |
SipErrorCode |
کدهای خطای برگرداندهشده درطول کنشهای SIP را تعریف میکند. |
SipManager |
میاناهای برنامهسازی کاربردی را برای کارهای SIP، مثل شروع اتصالهای SIP، ارائه میدهد و دسترسی به سرویسهای SIP مرتبط را فراهم میکند. |
SipProfile |
نمایه SIP را تعریف میکند، ازجمله حساب SIP، دامنه، و اطلاعات سرور. |
SipProfile.Builder |
کلاس کمکی برای ایجاد SipProfile. |
SipSession |
نشاندهنده جلسه SIP است که با کادر گفتگوی SIP یا تراکنش مستقل خارج از کادر گفتگو مرتبط است. |
SipSession.Listener |
شنونده رویدادهای مربوط به جلسه SIP، مثلاً وقتی جلسهای درحال ثبت شدن است («درحال ثبت») یا تماسی خروجی است («درحال تماس»). |
SipSession.State |
وضعیتهای جلسه SIP را تعریف میکند، مانند «درحال ثبت»، «تماس خروجی»، و «درحال تماس». |
SipRegistrationListener |
میانایی که شنونده رویدادهای ثبت SIP است. |
درحال ایجاد مانیفست
اگر درحال توسعه برنامهای هستید که از SIP API استفاده میکند، بهخاطر داشته باشید که این ویژگی فقط در Android 2.3 (سطح میانای برنامهسازی کاربردی ۹) و نسخههای بالاتر پلاتفرم پشتیبانی میشود. همچنین، در میان دستگاههایی که Android 2.3 (سطح میانای برنامهسازی کاربردی ۹) یا بالاتر را اجرا میکنند، همه دستگاهها از SIP پشتیبانی نمیکنند.
برای استفاده از SIP، اجازههای زیر را به مانیفست برنامهتان اضافه کنید:
android.permission.USE_SIPandroid.permission.INTERNET
برای اطمینان از اینکه برنامهتان فقط در دستگاههایی نصب میشود که میتوانند از SIP پشتیبانی کنند، موارد زیر را به مانیفست برنامهتان اضافه کنید:
<uses-sdk android:minSdkVersion="9" />
این نشان میدهد که برنامه شما به Android نسخه ۲.۳ یا بالاتر نیاز دارد. برای
کسب اطلاعات بیشتر،
سطوح API
و اسناد مربوط به
عنصر <uses-sdk>
را ببینید.
برای کنترل نحوه فیلتر شدن برنامهتان از دستگاههایی که از SIP پشتیبانی نمیکنند (برای مثال، در Google Play)، موارد زیر را به مانیفست برنامهتان اضافه کنید:
<uses-feature android:name="android.software.sip.voip" />
این نشان میدهد که برنامه شما از SIP API استفاده میکند. اعلامیه باید
شامل مشخصه android:required باشد که نشان میدهد آیا
میخواهید برنامه از دستگاههایی که از SIP پشتیبانی نمیکنند فیلتر شود یا نه.
بسته به پیادهسازی شما، ممکن است به اظهارنامههای <uses-feature> دیگری نیز نیاز باشد. برای اطلاعات بیشتر، به مستندات
مربوط به عنصر
<uses-feature>
مراجعه کنید.
اگر برنامه شما برای دریافت تماس طراحی شده است، باید یک گیرنده (زیرکلاس BroadcastReceiver) نیز در مانیفست برنامه تعریف کنید:
<receiver android:name=".IncomingCallReceiver" android:label="Call Receiver" />
در اینجا گزیدههایی از مانیفست SipDemo آورده شده است:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.android.sip"> ... <receiver android:name=".IncomingCallReceiver" android:label="Call Receiver" /> ... <uses-sdk android:minSdkVersion="9" /> <uses-permission android:name="android.permission.USE_SIP" /> <uses-permission android:name="android.permission.INTERNET" /> ... <uses-feature android:name="android.software.sip.voip" android:required="true" /> <uses-feature android:name="android.hardware.wifi" android:required="true" /> <uses-feature android:name="android.hardware.microphone" android:required="true" /> </manifest>
درحال ایجاد SipManager
برای استفاده از SIP API، برنامه شما باید یک شیء SipManager ایجاد کند. SipManager
موارد زیر را در برنامهتان مدیریت میکند:
- درحال شروع جلسههای SIP.
- برقراری و دریافت تماس.
- ثبتنام و لغو ثبتنام با ارائهدهنده SIP.
- درحال درستیسنجی اتصال جلسه.
SipManager جدیدی را بهصورت زیر نمونهسازی میکنید:
کاتلین
val sipManager: SipManager? by lazy(LazyThreadSafetyMode.NONE) { SipManager.newInstance(this) }
جاوا
public SipManager sipManager = null; ... if (sipManager == null) { sipManager = SipManager.newInstance(this); }
ثبتنام با سرور SIP
یک برنامه SIP معمولی Android شامل یک یا چند کاربر است که هرکدام
یک حساب SIP دارند. در برنامه SIP Android، هر حساب SIP با یک شیء SipProfile نشان داده میشود.
SipProfile نمایه SIP را تعریف میکند، ازجمله حساب SIP، و اطلاعات دامنه و سرور. نمایه مرتبط با حساب SIP در دستگاهی که برنامه را اجرا میکند نمایه محلی نامیده میشود. نمایهای که جلسه به آن متصل است
نمایه همتا نامیده میشود. وقتی برنامه SIP شما با SipProfile محلی به سرور SIP وارد میشود، این کار بهطور مؤثری دستگاه را بهعنوان مکانی برای ارسال تماسهای SIP به نشانی SIP شما ثبت میکند.
این بخش نحوه ایجاد SipProfile،
ثبت آن در سرور SIP، و پیگیری رویدادهای ثبت را نشان میدهد.
یک شیء SipProfile را بهصورت زیر ایجاد میکنید:
کاتلین
private var sipProfile: SipProfile? = null ... val builder = SipProfile.Builder(username, domain) .setPassword(password) sipProfile = builder.build()
جاوا
public SipProfile sipProfile = null; ... SipProfile.Builder builder = new SipProfile.Builder(username, domain); builder.setPassword(password); sipProfile = builder.build();
گزیده کد زیر نمایه محلی را برای برقراری تماس و/یا
دریافت تماسهای SIP عمومی باز میکند. تماسگیرنده میتواند تماسهای بعدی را ازطریق
mSipManager.makeAudioCall برقرار کند. این گزیده همچنین کنش
android.SipDemo.INCOMING_CALL را تنظیم میکند که وقتی دستگاه تماسی دریافت میکند، توسط فیلتر قصد
استفاده خواهد شد (به راهاندازی
فیلتر قصد برای دریافت تماس مراجعه کنید). این مرحله ثبتنام است:
کاتلین
val intent = Intent("android.SipDemo.INCOMING_CALL") val pendingIntent: PendingIntent = PendingIntent.getBroadcast(this, 0, intent, Intent.FILL_IN_DATA) sipManager?.open(sipProfile, pendingIntent, null)
جاوا
Intent intent = new Intent(); intent.setAction("android.SipDemo.INCOMING_CALL"); PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, Intent.FILL_IN_DATA); sipManager.open(sipProfile, pendingIntent, null);
درنهایت، این کد SipRegistrationListener را در SipManager تنظیم میکند. این گزینه ردیابی میکند که آیا SipProfile باموفقیت در فراهمساز خدمات SIP شما ثبت شده است یا نه:
کاتلین
sipManager?.setRegistrationListener(sipProfile?.uriString, object : SipRegistrationListener { override fun onRegistering(localProfileUri: String) { updateStatus("Registering with SIP Server...") } override fun onRegistrationDone(localProfileUri: String, expiryTime: Long) { updateStatus("Ready") } override fun onRegistrationFailed( localProfileUri: String, errorCode: Int, errorMessage: String ) { updateStatus("Registration failed. Please check settings.") } })
جاوا
sipManager.setRegistrationListener(sipProfile.getUriString(), new SipRegistrationListener() { public void onRegistering(String localProfileUri) { updateStatus("Registering with SIP Server..."); } public void onRegistrationDone(String localProfileUri, long expiryTime) { updateStatus("Ready"); } public void onRegistrationFailed(String localProfileUri, int errorCode, String errorMessage) { updateStatus("Registration failed. Please check settings."); } }
وقتی برنامه شما استفاده از نمایهای را تمام کرد، باید آن را ببندد تا اشیای مرتبط را در حافظه آزاد کند و ثبتنام دستگاه را در سرور لغو کند. برای مثال:
کاتلین
fun closeLocalProfile() { try { sipManager?.close(sipProfile?.uriString) } catch (ee: Exception) { Log.d("WalkieTalkieActivity/onDestroy", "Failed to close local profile.", ee) } }
جاوا
public void closeLocalProfile() { if (sipManager == null) { return; } try { if (sipProfile != null) { sipManager.close(sipProfile.getUriString()); } } catch (Exception ee) { Log.d("WalkieTalkieActivity/onDestroy", "Failed to close local profile.", ee); } }
درحال برقراری تماس صوتی
برای برقراری تماس صوتی، باید موارد زیر را داشته باشید:
- یک
SipProfileکه تماس را برقرار میکند («نمایه محلی»)، و یک نشانی SIP معتبر برای دریافت تماس («نمایه همتا»). - شیء
SipManager.
برای برقراری تماس صوتی، باید SipAudioCall.Listener راهاندازی کنید. بخش زیادی از تعامل کارخواه با
پشته SIP ازطریق شنوندگان اتفاق میافتد. در این قطعه کد، میبینید که چگونه SipAudioCall.Listener پساز برقراری تماس، موارد را راهاندازی میکند:
کاتلین
var listener: SipAudioCall.Listener = object : SipAudioCall.Listener() { override fun onCallEstablished(call: SipAudioCall) { call.apply { startAudio() setSpeakerMode(true) toggleMute() } } override fun onCallEnded(call: SipAudioCall) { // Do something. } }
جاوا
SipAudioCall.Listener listener = new SipAudioCall.Listener() { @Override public void onCallEstablished(SipAudioCall call) { call.startAudio(); call.setSpeakerMode(true); call.toggleMute(); ... } @Override public void onCallEnded(SipAudioCall call) { // Do something. } };
وقتی SipAudioCall.Listener را راهاندازی کردید، میتوانید
تماس بگیرید. روش SipManager
makeAudioCall پارامترهای زیر را میگیرد:
- نمایه SIP محلی (تماسگیرنده).
- نمایه SIP همتا (کاربری که با او تماس گرفته میشود).
SipAudioCall.Listenerبرای گوش دادن به رویدادهای تماس ازSipAudioCall. این میتواندnullباشد، اما همانطور که در بالا نشان داده شده است، از شنونده برای راهاندازی چیزها پساز برقراری تماس استفاده میشود.- مقدار زمان اتمام، برحسب ثانیه.
برای مثال:
کاتلین
val call: SipAudioCall? = sipManager?.makeAudioCall( sipProfile?.uriString, sipAddress, listener, 30 )
جاوا
call = sipManager.makeAudioCall(sipProfile.getUriString(), sipAddress, listener, 30);
دریافت تماسها
برای دریافت تماس، برنامه SIP باید شامل زیرکلاس BroadcastReceiver باشد که توانایی پاسخ دادن به قصد را داشته باشد
که نشان میدهد تماس ورودی وجود دارد. بنابراین، باید موارد زیر را در برنامهتان انجام دهید:
- در
AndroidManifest.xml،<receiver>را اعلام کنید. در SipDemo، این<receiver android:name=".IncomingCallReceiver" android:label="Call Receiver" />است. - گیرنده را که زیرکلاسی از
BroadcastReceiverاست پیادهسازی کنید. در SipDemo، اینIncomingCallReceiverاست. - نمایه محلی (
SipProfile) را با قصد معوقی که هنگام تماس با نمایه محلی گیرنده شما را فعال میکند مقداردهی اولیه کنید. - فیلتر قصدی راهاندازی کنید که براساس کنشی که نشاندهنده تماس ورودی است فیلتر کند. در SipDemo، این کنش
android.SipDemo.INCOMING_CALLاست.
زیرکلاسسازی BroadcastReceiver
برای دریافت تماس، برنامه SIP شما باید زیرکلاس BroadcastReceiver باشد. سیستم
Android تماسهای SIP ورودی را مدیریت میکند و هنگام دریافت تماس،
هدف «تماس ورودی» (همانطور که توسط برنامه تعریف شده است) را
پخش میکند. در اینجا کد BroadcastReceiver
زیرکلاسشده از نمونه SipDemo آمده است.
کاتلین
/** * Listens for incoming SIP calls, intercepts and hands them off to WalkieTalkieActivity. */ class IncomingCallReceiver : BroadcastReceiver() { /** * Processes the incoming call, answers it, and hands it over to the * WalkieTalkieActivity. * @param context The context under which the receiver is running. * @param intent The intent being received. */ override fun onReceive(context: Context, intent: Intent) { val wtActivity = context as WalkieTalkieActivity var incomingCall: SipAudioCall? = null try { incomingCall = wtActivity.sipManager?.takeAudioCall(intent, listener) incomingCall?.apply { answerCall(30) startAudio() setSpeakerMode(true) if (isMuted) { toggleMute() } wtActivity.call = this wtActivity.updateStatus(this) } } catch (e: Exception) { incomingCall?.close() } } private val listener = object : SipAudioCall.Listener() { override fun onRinging(call: SipAudioCall, caller: SipProfile) { try { call.answerCall(30) } catch (e: Exception) { e.printStackTrace() } } } }
جاوا
/** * Listens for incoming SIP calls, intercepts and hands them off to WalkieTalkieActivity. */ public class IncomingCallReceiver extends BroadcastReceiver { /** * Processes the incoming call, answers it, and hands it over to the * WalkieTalkieActivity. * @param context The context under which the receiver is running. * @param intent The intent being received. */ @Override public void onReceive(Context context, Intent intent) { SipAudioCall incomingCall = null; try { SipAudioCall.Listener listener = new SipAudioCall.Listener() { @Override public void onRinging(SipAudioCall call, SipProfile caller) { try { call.answerCall(30); } catch (Exception e) { e.printStackTrace(); } } }; WalkieTalkieActivity wtActivity = (WalkieTalkieActivity) context; incomingCall = wtActivity.sipManager.takeAudioCall(intent, listener); incomingCall.answerCall(30); incomingCall.startAudio(); incomingCall.setSpeakerMode(true); if(incomingCall.isMuted()) { incomingCall.toggleMute(); } wtActivity.call = incomingCall; wtActivity.updateStatus(incomingCall); } catch (Exception e) { if (incomingCall != null) { incomingCall.close(); } } } }
راهاندازی فیلتر قصد برای دریافت تماسها
وقتی سرویس SIP تماس جدیدی دریافت میکند، قصدی را با رشته کنش ارائهشده توسط برنامه ارسال میکند. در SipDemo، این رشته کنش
android.SipDemo.INCOMING_CALL است.
این گزیده کد از SipDemo نشان میدهد که چگونه شیء SipProfile با قصد معوق براساس رشته کنش android.SipDemo.INCOMING_CALL ایجاد میشود. وقتی SipProfile تماسی دریافت کند، شیء PendingIntent همهفرستی انجام خواهد داد:
کاتلین
val sipManager: SipManager? by lazy(LazyThreadSafetyMode.NONE) { SipManager.newInstance(this) } var sipProfile: SipProfile? = null ... val intent = Intent("android.SipDemo.INCOMING_CALL") val pendingIntent: PendingIntent = PendingIntent.getBroadcast(this, 0, intent, Intent.FILL_IN_DATA) sipManager?.open (sipProfile, pendingIntent, null)
جاوا
public SipManager sipManager = null; public SipProfile sipProfile = null; ... Intent intent = new Intent(); intent.setAction("android.SipDemo.INCOMING_CALL"); PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, Intent.FILL_IN_DATA); sipManager.open(sipProfile, pendingIntent, null);
فیلتر قصد همهفرستی را رهگیری میکند و سپس گیرنده (IncomingCallReceiver) را فعال میکند. میتوانید فیلتر قصد را در فایل مانیفست برنامهتان مشخص کنید یا این کار را در کد انجام دهید، مانند روش onCreate() برنامه نمونه SipDemo از Activity برنامه:
کاتلین
class WalkieTalkieActivity : Activity(), View.OnTouchListener { ... lateinit var callReceiver: IncomingCallReceiver ... override fun onCreate(savedInstanceState: Bundle) { val filter = IntentFilter().apply { addAction("android.SipDemo.INCOMING_CALL") } callReceiver = IncomingCallReceiver() this.registerReceiver(callReceiver, filter) ... } ... }
جاوا
public class WalkieTalkieActivity extends Activity implements View.OnTouchListener { ... public IncomingCallReceiver callReceiver; ... @Override public void onCreate(Bundle savedInstanceState) { IntentFilter filter = new IntentFilter(); filter.addAction("android.SipDemo.INCOMING_CALL"); callReceiver = new IncomingCallReceiver(); this.registerReceiver(callReceiver, filter); ... } ... }
درحال آزمایش برنامههای SIP
برای آزمایش برنامههای SIP، به موارد زیر نیاز دارید:
- دستگاه همراهی که Android نسخه ۲.۳ یا بالاتر داشته باشد. SIP روی بیسیم اجرا میشود، بنابراین باید آن را روی دستگاه واقعی آزمایش کنید. آزمایش روی AVD کار نخواهد کرد.
- حساب SIP. ارائهدهندگان SIP مختلفی وجود دارند که حساب SIP ارائه میدهند.
- اگر تماس برقرار میکنید، باید با حساب SIP معتبری باشد.
برای آزمایش برنامه SIP:
- در دستگاهتان، به شبکه بیسیم متصل شوید (تنظیمات > بیسیم و شبکهها > Wi-Fi > تنظیمات Wi-Fi).
- دستگاه همراهتان را برای آزمایش راهاندازی کنید، همانطور که در توسعه در دستگاه شرح داده شده است.
- برنامهتان را در دستگاه همراهتان اجرا کنید، همانطور که در توسعه در دستگاه شرح داده شده است.
- اگر از Android Studio استفاده میکنید، میتوانید خروجی گزارش برنامه را با باز کردن کنسول «گزارش رویداد» (مشاهده > پنجرههای ابزار > گزارش رویداد) مشاهده کنید.
- مطمئن شوید برنامهتان بهگونهای پیکربندی شده باشد که Logcat را بهطور خودکار هنگام اجرا راهاندازی کند:
- اجرا > ویرایش پیکربندیها را انتخاب کنید.
- برگه متفرقه را در پنجره پیکربندیهای اجرا/اشکالزدایی انتخاب کنید.
- در بخش Logcat، نمایش خودکار logcat را انتخاب کنید، سپس تأیید را انتخاب کنید.