eSIM'leri ve SIM kartları algılama
Kartlar algılanıyor
SIM kart ve eSIM'leri olan Android cihazlar, telefon API'lerinde [`TelephonyManager`](/reference/android/telephony/TelephonyManager) ve [`SubscriptionManager`](/reference/android/telephony/SubscriptionManager) dahil olmak üzere telefon API'lerinde aşağıdaki kimlikleri kullanır: * Abonelik Kimliği: Mobil abonelik için benzersiz kimlik. * Mantıksal yuva dizini veya kimliği: Mantıksal bir SIM yuvasını belirten benzersiz dizin. Mantıksal slot kimlikleri 0'dan başlar ve cihazdaki desteklenen etkin slot sayısına bağlı olarak artar. Örneğin, çift SIM kartlı cihazlarda genellikle yuva 0 ve yuva 1 bulunur. Bir cihazda birden fazla fiziksel slot varsa ancak yalnızca tek bir etkin yuva varsa cihazda yalnızca mantıksal yuva kimliği 0 olur. * Fiziksel yuva dizini veya kimliği: Fiziksel SIM yuvasını belirten benzersiz dizin. Fiziksel slot kimlikleri 0'dan başlar ve cihazdaki fiziksel yuva sayısına bağlı olarak artar. Bu sayı, bir cihazın sahip olduğu mantıksal slot sayısından farklıdır. Bu mantık, cihazın kullanabileceği etkin slot sayısına karşılık gelir. Örneğin, çift SIM ve tek SIM modları arasında geçiş yapan bir cihazda her zaman iki fiziksel yuva bulunabilir. Ancak tek SIM modunda yalnızca bir mantıksal yuva bulunur. * Kart kimliği: UiccCard'ı tanımlamak için kullanılan benzersiz kimlik. ![İki mantıksal slot ve üç fiziksel yuvalı destek kaydında kimliklerin nasıl kullanıldığını gösteren şema](/images/guide/topics/connectivity/tel-ids.png) Yukarıdaki şemada: * Cihazın iki mantıksal yuvası vardır. * Fiziksel 0 yuvasında etkin bir profile sahip fiziksel bir UICC kartı var. * Fiziksel yuva 2'de, etkin profile sahip bir eUICC bulunur. * Fiziksel yuva 1 şu anda kullanımda değil. ![Üç mantıksal slot ve iki fiziksel yuva bulunan durumlarda kimliklerin nasıl kullanıldığını gösteren şema](/images/guide/topics/connectivity/tel-ids-2.png) Yukarıdaki şemada: * Cihazın üç mantıksal yuvası vardır. * Fiziksel 0 yuvasında etkin bir profile sahip fiziksel bir UICC kartı var. * Fiziksel yuva 1'de, her ikisi de MEP (Çoklu Etkin Profiller) kullanarak etkin olan iki indirilmiş profile sahip bir eUICC bulunur.
Oturum başlatma protokolüne genel bakış
Android, Oturum Başlatma Protokolü'nü (SIP) destekleyen bir API sunar. Bu, uygulamalarınıza SIP tabanlı internet telefon özellikleri eklemenize olanak tanır. Android, uygulamaların oturumları, aktarım düzeyindeki iletişimi veya ses kaydı ya da çalma işlemlerini doğrudan yönetmek zorunda kalmadan giden ve gelen sesli aramaları kolayca ayarlamasını sağlayan tam bir SIP protokolü yığını ve entegre çağrı yönetimi hizmetleri içerir.
Aşağıda, SIP API'yi kullanabilecek uygulama türlerine ilişkin örnekler verilmiştir:
- Video konferans
- Anında mesajlaşma
Gereksinimler ve sınırlamalar
SIP uygulaması geliştirme gereksinimleri şunlardır:
- Android 2.3 veya sonraki sürümleri çalıştıran bir mobil cihazınızın olması gerekir.
- SIP, kablosuz bir veri bağlantısı üzerinden çalışır. Bu nedenle cihazınızda veri bağlantısı (mobil veri hizmeti veya kablosuz ağ ile) olmalıdır. Yani ortalama görüntüleme süresi (AVD) ile test yapamazsınız, yalnızca fiziksel bir cihazda test edebilirsiniz. Ayrıntılar için SIP uygulamalarını test etme bölümüne bakın.
- Uygulamanın iletişim oturumundaki her katılımcının bir SIP hesabı olmalıdır. SIP hesapları sunan birçok farklı SIP sağlayıcısı vardır.
Not: android.net.sip
kitaplığı görüntülü görüşmeleri desteklemez. android.net.sip
gibi bir SIP yığını kullanarak VOIP çağrısını uygulamak istiyorsanız herhangi bir VOIP çağrısı uygulamasının temeli olarak birçok modern açık kaynak alternatifinden birini inceleyin. Alternatif olarak, bu çağrıların cihazın Çevirici uygulamasıyla sıkı bir şekilde entegre edilmesini sağlamak için ConnectionService
API'yi uygulayabilirsiniz.
SIP API sınıfları ve arayüzleri
Android SIP API'ye dahil olan sınıfların ve bir arayüzün (SipRegistrationListener
) özetini burada bulabilirsiniz:
Ders/Arayüz | Açıklama |
---|---|
SipAudioCall |
SIP üzerinden yapılan bir sesli internet aramasını yönetir. |
SipAudioCall.Listener |
Bir arama alındığında ("çalırken") veya giden bir arama ("arama sırasında") gibi SIP aramasıyla ilgili etkinlikleri dinleyici. |
SipErrorCode |
SIP işlemleri sırasında döndürülen hata kodlarını tanımlar. |
SipManager |
SIP bağlantılarını başlatma gibi SIP görevleri için API'ler sağlar ve ilgili SIP hizmetlerine erişim sağlar. |
SipProfile |
SIP hesabı, alan ve sunucu bilgilerini içeren bir SIP profili tanımlar. |
SipProfile.Builder |
SIPProfili oluşturmak için yardımcı sınıfı. |
SipSession |
SIP iletişim kutusuyla veya iletişim kutusunda olmayan bağımsız bir işlemle ilişkili SIP oturumunu temsil eder. |
SipSession.Listener |
Bir oturumun kaydedilmesi ("kayıt sırasında") veya giden bir arama ("arama sırasında") gibi, SIP oturumuyla ilgili etkinliklerin dinleyicisi. |
SipSession.State |
"Kayıtlı", "giden arama" ve "aramada" gibi SIP oturum durumlarını tanımlar. |
SipRegistrationListener |
SIP kayıt etkinliklerini işleyen bir arayüzdür. |
Manifest oluşturuluyor
SIP API kullanan bir uygulama geliştiriyorsanız, bu özelliğin yalnızca Android 2.3 (API düzeyi 9) ve platformun sonraki sürümlerinde desteklendiğini unutmayın. Ayrıca, Android 2.3 (API düzeyi 9) veya sonraki sürümleri çalıştıran cihazlarda tüm cihazlar SIP desteği sunmaz.
SIP kullanmak için aşağıdaki izinleri uygulamanızın manifest dosyasına ekleyin:
android.permission.USE_SIP
android.permission.INTERNET
Uygulamanızın yalnızca SIP'yi destekleyebilen cihazlara yüklenebilmesi için aşağıdaki bilgileri uygulama manifestinize ekleyin:
<uses-sdk android:minSdkVersion="9" />
Bu, uygulamanızın Android 2.3 veya sonraki bir sürümü gerektirdiğini gösterir. Daha fazla bilgi için API Düzeyleri'ni ve <uses-sdk>
öğesiyle ilgili belgeleri inceleyin.
Uygulamanızın, SIM'i desteklemeyen cihazlardan (örneğin, Google Play'de) nasıl filtrelendiğini kontrol etmek için aşağıdakini uygulamanızın manifest dosyasına ekleyin:
<uses-feature android:name="android.software.sip.voip" />
Bu, uygulamanızın SIP API kullandığını belirtir. Beyan, uygulamanın SIP desteği sunmayan cihazlardan filtrelenmesini isteyip istemediğinizi belirten bir android:required
özelliği içermelidir.
Uygulamanıza bağlı olarak başka <uses-feature>
beyanları da gerekebilir. Daha fazla bilgi için <uses-feature>
öğesiyle ilgili belgelere bakın.
Uygulamanız arama alacak şekilde tasarlandıysa uygulamanın manifest dosyasında bir alıcı da (BroadcastReceiver
alt sınıfı) tanımlamanız gerekir:
<receiver android:name=".IncomingCallReceiver" android:label="Call Receiver" />
SipDemo manifestinden alıntılar şunlardır:
<?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 oluşturma
SIP API'yi kullanmak için uygulamanızın bir SipManager
nesnesi oluşturması gerekir. SipManager
, uygulamanızda aşağıdakilerle ilgilenir:
- SIP oturumları başlatılıyor.
- Arama başlatma ve alma.
- SIP sağlayıcısı için kaydolma ve kaydı iptal etme
- Oturum bağlantısı doğrulanıyor.
Yeni bir SipManager
örneğini aşağıdaki gibi somutlaştırırsınız:
Kotlin
val sipManager: SipManager? by lazy(LazyThreadSafetyMode.NONE) { SipManager.newInstance(this) }
Java
public SipManager sipManager = null; ... if (sipManager == null) { sipManager = SipManager.newInstance(this); }
SIP Sunucusu ile kaydolma
Tipik bir Android SIP uygulamasında bir veya daha fazla kullanıcı kullanılır. Bu kullanıcıların her birinde SIP hesabı bulunur. Android SIP uygulamasında her SIP hesabı bir SipProfile
nesnesiyle temsil edilir.
SipProfile
, SIP hesabı ile alan ve sunucu bilgilerini içeren bir SIP profili tanımlar. Uygulamayı çalıştıran cihazda SIP hesabıyla ilişkilendirilen profile yerel profil adı verilir. Oturumun bağlı olduğu profile eş profili adı verilir. SIP uygulamanız yerel SipProfile
ile SIP sunucusuna giriş yaptığında, bu işlem, cihazı SIP adresiniz için SIP çağrılarının gönderileceği konum olarak etkili şekilde kaydeder.
Bu bölümde, SipProfile
oluşturma, bunu bir SIP sunucusuna kaydetme ve kayıt etkinliklerini izleme konuları gösterilmektedir.
SipProfile
nesnesini şu şekilde oluşturursunuz:
Kotlin
private var sipProfile: SipProfile? = null ... val builder = SipProfile.Builder(username, domain) .setPassword(password) sipProfile = builder.build()
Java
public SipProfile sipProfile = null; ... SipProfile.Builder builder = new SipProfile.Builder(username, domain); builder.setPassword(password); sipProfile = builder.build();
Aşağıdaki kod alıntısı, arama yapmak ve/veya genel SIP çağrıları almak için yerel profili açar. Arayan, mSipManager.makeAudioCall
üzerinden sonraki aramaları yapabilir. Bu alıntı, cihaz bir arama aldığında amaç filtresi tarafından kullanılacak olan android.SipDemo.INCOMING_CALL
işlemini de ayarlar (Arama almak için amaç filtresi oluşturma bölümüne bakın). Kayıt adımı şudur:
Kotlin
val intent = Intent("android.SipDemo.INCOMING_CALL") val pendingIntent: PendingIntent = PendingIntent.getBroadcast(this, 0, intent, Intent.FILL_IN_DATA) sipManager?.open(sipProfile, pendingIntent, null)
Java
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);
Son olarak, bu kod SipManager
üzerinde bir SipRegistrationListener
ayarlar. Bu işlem, SipProfile
operatörünün SIP servis sağlayıcınıza başarıyla kaydedilip kaydedilmediğini izler:
Kotlin
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.") } })
Java
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."); } }
Uygulamanız bir profil kullanarak işini tamamladığında, ilişkili nesneleri belleğe serbest bırakmak ve cihazın sunucudaki kaydını silmek için profili kapatmalıdır. Örneğin:
Kotlin
fun closeLocalProfile() { try { sipManager?.close(sipProfile?.uriString) } catch (ee: Exception) { Log.d("WalkieTalkieActivity/onDestroy", "Failed to close local profile.", ee) } }
Java
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); } }
Sesli arama yapılıyor
Sesli arama yapmak için aşağıdakileri kullanıyor olmanız gerekir:
- Aramayı yapan bir
SipProfile
("yerel profil") ve çağrıyı almak için geçerli bir SIP adresi ("eş profili") SipManager
nesnesi.
Sesli arama yapmak için SipAudioCall.Listener
kurmanız gerekir. İstemcinin SIP yığınıyla etkileşiminin büyük bir kısmı dinleyiciler üzerinden gerçekleşir. Bu snippet'te, çağrı oluşturulduktan sonra SipAudioCall.Listener
cihazının ayarları nasıl yaptığını görebilirsiniz:
Kotlin
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. } }
Java
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
kurulumunu tamamladıktan sonra sesli arama yapabilirsiniz. SipManager
yöntemi makeAudioCall
aşağıdaki parametreleri alır:
- Yerel SIP profili (arayan).
- Eş SIP profili (aranan kullanıcı).
SipAudioCall
kaynağından çağrı etkinliklerini dinlemek için birSipAudioCall.Listener
. Bunull
olabilir ancak yukarıda gösterildiği gibi, görüşme bittikten sonra dinleyici ayar yapmak için kullanılır.- Saniye cinsinden zaman aşımı değeri.
Örneğin:
Kotlin
val call: SipAudioCall? = sipManager?.makeAudioCall( sipProfile?.uriString, sipAddress, listener, 30 )
Java
call = sipManager.makeAudioCall(sipProfile.getUriString(), sipAddress, listener, 30);
Çağrıları alıyor
Aramaları almak için SIP uygulaması, gelen arama olduğunu belirten bir amaca yanıt verebilen bir BroadcastReceiver
alt sınıfını içermelidir. Dolayısıyla, uygulamanızda aşağıdakileri yapmanız gerekir:
AndroidManifest.xml
içinde bir<receiver>
belirtin. SipDemo'da bu,<receiver android:name=".IncomingCallReceiver" android:label="Call Receiver" />
.BroadcastReceiver
alt sınıfı olan alıcıyı uygulayın. SipDemo'da bu,IncomingCallReceiver
.- Birisi yerel profili aradığında alıcınızı tetikleyen bekleme niyetiyle yerel profili (
SipProfile
) başlatın. - Gelen bir aramayı temsil eden işleme göre filtreleyen bir intent filtresi oluşturun. SipDemo'da bu işlem
android.SipDemo.INCOMING_CALL
şeklindedir.
BroadcastReceiver Alt Sınıflandırması
Arama almak için SIP uygulamanız BroadcastReceiver
alt sınıfı olmalıdır. Android sistemi, gelen SIP aramalarını işler ve bir arama aldığında "gelen arama" amacını (uygulama tarafından tanımlandığı şekilde) yayınlar. SipDemo örneğindeki alt sınıflandırılmış
BroadcastReceiver
kodunu burada görebilirsiniz.
Kotlin
/** * 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() } } } }
Java
/** * 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(); } } } }
Arama almak için intent filtresi oluşturma
SIP hizmeti yeni bir arama aldığında, uygulama tarafından sağlanan eylem dizesiyle bir amaç gönderir. SipDemo'da bu işlem dizesi android.SipDemo.INCOMING_CALL
şeklindedir.
SipDemo'dan alınan bu kod alıntısı android.SipDemo.INCOMING_CALL
işlem dizesine göre SipProfile
nesnesinin bekleyen bir niyetle nasıl oluşturulduğunu gösterir. SipProfile
bir çağrı aldığında PendingIntent
nesnesi bir yayın gerçekleştirir:
Kotlin
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)
Java
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);
Yayın, intent filtresi tarafından engellenecek ve daha sonra alıcıyı (IncomingCallReceiver
) tetikleyecektir. Uygulamanızın manifest dosyasında bir intent filtresi belirtebilir veya SipDemo örnek uygulamanın onCreate()
yöntemindeki (uygulamanın Activity
) kodundaki gibi kod kullanarak yapabilirsiniz:
Kotlin
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) ... } ... }
Java
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 uygulamalarını test etme
SIP uygulamalarını test etmek için şunlara ihtiyacınız vardır:
- Android 2.3 veya sonraki sürümleri çalıştıran bir mobil cihaz. SIP, kablosuz bağlantı üzerinden çalıştığından testinizi gerçek bir cihazda yapmanız gerekir. AVD ile yapılan testler çalışmıyor.
- SIP hesabı. SIP hesapları sunan birçok farklı SIP sağlayıcısı vardır.
- Arama yapıyorsanız bu işlem geçerli bir SIP hesabına da gitmelidir.
SIP uygulamasını test etmek için:
- Cihazınızda kablosuz ağa bağlanın (Ayarlar > Kablosuz ve ağlar > Kablosuz > Kablosuz ayarları).
- Cihazda Geliştirme bölümünde açıklandığı şekilde mobil cihazınızı test için ayarlayın.
- Uygulamanızı Cihazda Geliştirme bölümünde açıklandığı şekilde mobil cihazınızda çalıştırın.
- Android Studio kullanıyorsanız Olay Günlüğü konsolunu açarak uygulama günlüğü çıkışını görüntüleyebilirsiniz (Görünüm > Araç Pencereleri > Olay Günlüğü).
- Uygulamanızın, çalıştırıldığında Logcat'i otomatik olarak başlatacak şekilde yapılandırıldığından emin olun:
- Çalıştır > Yapılandırmaları Düzenle'yi seçin.
- Run/Debug Configurations (Çalıştır/Hata Ayıklama Yapılandırmaları) penceresinde Miscellaneous (Çeşitli) sekmesini seçin.
- Logcat altında logcat'i otomatik olarak göster'i ve ardından Tamam'ı seçin.