eSIM と SIM カードを検出する
カードの検出
SIM カードと eSIM を搭載した Android デバイスでは、電話通信で次の ID が使用されます Google Cloud などの [`TelephonyManager`](/reference/android/telephony/TelephonyManager) と [`SubscriptionManager`](/reference/android/telephony/SubscriptionManager): * サブスクリプション ID: モバイル サブスクリプションの一意の ID。 * 論理スロット インデックス(ID): 論理 SIM スロットを参照する一意のインデックス。 論理スロット ID は 0 から始まり、論理スロット ID はスロットの数に応じて アクティブなスロットの数を表します。たとえばデュアル SIM デバイスでは通常、 スロット 0 とスロット 1 がありますデバイスに複数の物理スロットがあるが、 1 つのアクティブなスロットをサポートする場合、論理スロット ID は 0 のみになります。 * 物理スロット インデックスまたは ID: 物理的な SIM スロットを参照する一意のインデックス。 物理スロット ID は 0 から始まり、物理スロット ID の数に応じて増加します。 スロットにアタッチできます。デバイスの論理スロット数とは異なります。 (デバイスのアクティブなスロット数に対応) できます。(デュアル SIM とシングル SIM を切り替えるデバイスなど) 物理スロットが 2 つある場合もありますが、シングル SIM モードでは、 スロットは 1 つだけです。 * カード ID: UiccCard の識別に使用される一意の ID ![2 つの論理スロットと 3 つの物理スロットがあるケースで ID がどのように使用されるかを示す図](/images/guide/topics/connectivity/tel-ids.png) 上の図の内容は次のとおりです。 * デバイスには 2 つの論理スロットがあります。 * 物理スロット 0 には、アクティブなプロファイルを持つ物理 UICC カードがあります。 * 物理スロット 2 には、アクティブなプロファイルの eUICC があります。 * 物理スロット 1 は現在使用されていません。 ![3 つの論理スロットと 2 つの物理スロットがあるケースで ID がどのように使用されるかを示す図](/images/guide/topics/connectivity/tel-ids-2.png) 上の図の内容は次のとおりです。 * デバイスには 3 つの論理スロットがある。 * 物理スロット 0 には、アクティブなプロファイルを持つ物理 UICC カードがあります。 * 物理スロット 1 には eUICC があり、ダウンロードしたプロファイルが 2 つあり、どちらも MEP(Multiple Enabled Profiles)を使用してアクティブです。
セッション開始プロトコルの概要
Android には、SIP(セッション開始プロトコル)をサポートする API が用意されています。 これにより、SIP ベースのインターネット電話機能をアプリケーションに追加できます。 Android は完全な SIP プロトコル スタックと統合された通話管理を搭載 アプリが音声通話の発信と着信を簡単に設定できるようにするサービス セッション、トランスポート レベルの通信、音声を管理することなく、 直接録画や再生ができます。
SIP API を使用するアプリケーションの種類の例を次に示します。
- ビデオ会議
- インスタント メッセージ
要件と制限事項
SIP アプリケーションを開発するための要件は次のとおりです。
- Android 2.3 以降を搭載しているモバイル デバイスが必要です。
- SIP はワイヤレス データ接続で動作するため、デバイスに モバイルデータ通信または Wi-Fi に接続する必要があります。つまり、 AVD ではテストできず、実機でのみテストできます。詳しくは、 SIP アプリケーションをテストする。
- アプリケーションの通信セッションの各参加者は、 SIP アカウント。さまざまな SIP プロバイダが SIP アカウントを提供しています。
注: android.net.sip
ライブラリは動画をサポートしていません。
できます。次のような SIP スタックを使用して VoIP 通話を実装するには、
android.net.sip
は、数多く存在する最新のオープンソースの一つです。
あらゆる VoIP 通話実装の基盤として利用できます。または
kubectl の「get pods」
ConnectionService
これらの呼び出しをデバイスの電話アプリと緊密に統合する API
。
SIP API のクラスとインターフェース
これらのクラスとインターフェースの概要は以下のとおりです。
(SipRegistrationListener
)
API:
クラス / インターフェース | 説明 |
---|---|
SipAudioCall |
SIP を介したインターネット音声通話を処理します。 |
SipAudioCall.Listener |
SIP 通話に関連するイベントのリスナー(通話中など) 着信(「着信中」)、通話が発信中(「通話中」)などです。 |
SipErrorCode |
SIP アクション中に返されるエラーコードを定義します。 |
SipManager |
SIP 接続の開始などの SIP タスク用の API を提供し、 関連付けることもできます。 |
SipProfile |
SIP アカウント、ドメイン、サーバー情報を含む SIP プロファイルを定義します。 |
SipProfile.Builder |
SipProfile を作成するためのヘルパークラス。 |
SipSession |
SIP ダイアログまたはスタンドアロン トランザクションに関連付けられている SIP セッションを表します。 必要があります。 |
SipSession.Listener |
SIP セッションに関連するイベントのリスナー(セッションの登録時など) (「登録中」)、通話が発信中(「通話中」)などです。 |
SipSession.State |
「登録」、「発信」、「着信」など、SIP セッションの状態を定義します。 |
SipRegistrationListener |
SIP 登録イベントのリスナーであるインターフェース。 |
マニフェストの作成
SIP API を使用するアプリケーションを開発する場合、 この機能は、Android 2.3(API レベル 9)以降の 説明します。また、Android 2.3(API レベル 9)以降を搭載しているデバイスでは、 すべてのデバイスが SIP に対応しているわけではありません。
SIP を使用するには、アプリケーションのマニフェストに次の権限を追加します。
android.permission.USE_SIP
android.permission.INTERNET
次の要件を満たすデバイスにのみアプリをインストールするには、 サポートする必要がある場合は、アプリケーションの manifest:
<uses-sdk android:minSdkVersion="9" />
これは、アプリケーションに Android 2.3 以降が必要であることを示しています。対象
詳細については、以下をご覧ください。
API レベル
およびドキュメントをご覧ください
<uses-sdk>
要素です。
サポートしていないデバイスからのアプリケーションのフィルタリング方法を制御するには SIP(Google Play など)を使用する場合は、アプリの manifest:
<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
を次のようにインスタンス化します。
Kotlin
val sipManager: SipManager? by lazy(LazyThreadSafetyMode.NONE) { SipManager.newInstance(this) }
Java
public SipManager sipManager = null; ... if (sipManager == null) { sipManager = SipManager.newInstance(this); }
SIP サーバーへの登録
一般的な Android SIP アプリケーションでは、1 人以上のユーザーが
持っているかどうかを選択します。Android SIP アプリケーションでは、各 SIP アカウントは
SipProfile
オブジェクトで表されます。
SipProfile
は、SIP を含む SIP プロファイルを定義します。
アカウント、ドメイン、サーバーの情報。SIP に関連付けられたプロファイル
アプリケーションを実行しているデバイス上のアカウントは、ローカル
プロファイルをご覧ください。セッションが接続されているプロファイルは、
ピア プロファイル。SIP アプリケーションが 2 段階認証プロセスを使用して SIP サーバーにログインすると、
これにより、SipProfile
ローカルの
SIP アドレスへの SIP 通話の送信先として指定します。
このセクションでは、SipProfile
を作成する方法について説明します。
SIP サーバーに登録し、登録イベントを追跡します。
SipProfile
オブジェクトは、次のように作成します。
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();
次のコードの抜粋では、通話や通話を行うためのローカル プロファイルを開きます。
一般的な SIP 通話を受信します呼び出し元は、後続の呼び出しを
mSipManager.makeAudioCall
。この抜粋では
android.SipDemo.INCOMING_CALL
: インテントで使用されます
受信時にフィルタできます(
通話を受信するインテント フィルタなど)が含まれます。これは登録手順です。
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);
最後に、このコードは SipManager
に SipRegistrationListener
を設定します。SipProfile
が SIP サービスに正常に登録されたかどうかを追跡します
provider:
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."); } }
プロファイルを使用したアプリの処理が完了したら、プロファイルを閉じてから解放する必要があります。 関連付けられたオブジェクトをメモリに書き込み、サーバーからデバイスの登録を解除します。次に例を示します。
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); } }
音声通話を発信する
音声通話を発信するには、次のものが必要です。
- 呼び出し元の
SipProfile
( 「ローカル プロファイル」)、通話を受けるための有効な SIP アドレス( 「ピアのプロフィール」)を入力します。 SipManager
オブジェクト。
音声通話を発信するには、SipAudioCall.Listener
を設定する必要があります。クライアントとのやり取りの多くは、
SIP スタックはリスナーを介して発生しますこのスニペットでは、呼び出し後に SipAudioCall.Listener
がどのように設定を行うかを示しています。
確立:
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
を設定すると、次のことが可能になります。
電話をかけます。SipManager
メソッド
makeAudioCall
は次のパラメータを取ります。
- ローカル SIP プロファイル(発信側)。
- ピア SIP プロファイル(通話を受けるユーザー)。
- 通話を聴くための
SipAudioCall.Listener
SipAudioCall
のイベント。null
、 ただし、上に示したように、リスナーを使用して、呼び出しが完了したら、セットアップを行います。 あります。 - タイムアウト値(秒)。
例:
Kotlin
val call: SipAudioCall? = sipManager?.makeAudioCall( sipProfile?.uriString, sipAddress, listener, 30 )
Java
call = sipManager.makeAudioCall(sipProfile.getUriString(), sipAddress, listener, 30);
通話を受信する
着信を受けるには、インテントに応答できる BroadcastReceiver
のサブクラスが SIP アプリケーションに含まれている必要があります。
着信があることを示しています。したがって、次のことを行う必要があります。
説明します。
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 サンプルから抜粋)
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(); } } } }
通話を受信するためのインテント フィルタの設定
新しい通話を受信すると、SIP サービスは
アクション文字列を返します。SipDemo では、このアクション文字列を
android.SipDemo.INCOMING_CALL
。
SipDemo からのこのコードの抜粋は、SipProfile
オブジェクトがどのように作成されたかを示しています。
アクション文字列 android.SipDemo.INCOMING_CALL
。「
PendingIntent
オブジェクトは、SipProfile
が呼び出しを受け取るとブロードキャストを実行します。
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);
ブロードキャストがインテント フィルタによってインターセプトされ、
受信側(IncomingCallReceiver
)。インテントを指定すると、
フィルタを使用するか、SipDemo
サンプル アプリケーションの onCreate()
メソッド
アプリケーションの Activity
:
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 アプリケーションのテスト
SIP アプリケーションをテストするには、次のものが必要です。
- Android 2.3 以降を搭載しているモバイル デバイス。SIP は 実際のデバイスでテストする必要があります。AVD でのテストは機能しません。
- SIP アカウント。さまざまな SIP プロバイダが SIP アカウントを提供しています。
- 通話を発信する場合は、有効な SIP アカウントにも発信する必要があります。
SIP アプリケーションをテストする手順は次のとおりです。
- デバイスをワイヤレスに接続します([設定] > [無線とネットワーク] >Wi-Fi >Wi-Fi 設定をご覧ください)。
- デバイスでの開発の説明に沿って、モバイル デバイスをテスト用に設定します。
- デバイスでの開発の説明に従って、モバイル デバイスでアプリケーションを実行します。
- Android Studio を使用している場合は、次のコマンドでアプリケーション ログの出力を表示できます。 イベントログ コンソールを開きます([View] > [Tool Windows] > [Event Log])。
- 実行時に Logcat を自動的に起動するようにアプリケーションを構成します。
<ph type="x-smartling-placeholder">
- </ph>
- [Run] >構成の編集をご覧ください。
- [Run/Debug Configurations] ウィンドウで [Miscellaneous] タブを選択します。
- [Logcat] で、[Show logcat で利用可能な] を選択し、 [OK] を選択します。