Oturum başlatma protokolüne genel bakış

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 bir SipAudioCall.Listener. Bu null 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:

  1. Cihazınızda kablosuz ağa bağlanın (Ayarlar > Kablosuz ve ağlar > Kablosuz > Kablosuz ayarları).
  2. Cihazda Geliştirme bölümünde açıklandığı şekilde mobil cihazınızı test için ayarlayın.
  3. Uygulamanızı Cihazda Geliştirme bölümünde açıklandığı şekilde mobil cihazınızda çalıştırın.
  4. 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üğü).
  5. Uygulamanızın, çalıştırıldığında Logcat'i otomatik olarak başlatacak şekilde yapılandırıldığından emin olun:
    1. Çalıştır > Yapılandırmaları Düzenle'yi seçin.
    2. Run/Debug Configurations (Çalıştır/Hata Ayıklama Yapılandırmaları) penceresinde Miscellaneous (Çeşitli) sekmesini seçin.
    3. Logcat altında logcat'i otomatik olarak göster'i ve ardından Tamam'ı seçin.