tencent cloud

Android

PDF
フォーカスモード
フォントサイズ
最終更新日: 2026-02-06 09:27:46

業務フロー

このセクションでは、1V1オーディオ・ビデオ通話におけるいくつかの一般的な業務フローをまとめて、全体のシナリオの実装をよりよく理解するのに役立ちます。
ボイス通話の流れ
ビデオ通話の流れ
下の図は1V1ボイス通話のシーケンス図を示しており、発信、応答、通話、切断などの流れが含まれています。



下図は、1V1ビデオ通話のシーケンス図を示しており、発信、応答、通話、切断などの流れが含まれています。




アクセスの準備

ステップ1:サービスを利用する

1V1オーディオ・ビデオ通話シナリオは通常、Tencent CloudのChatReal-Time Communicationの2つの有料PaaSサービスに依存して構築する必要があります。
1. まず、TRTCコントロールパネルにログインしてアプリケーションを作成する必要があります。この時、IMコントロールパネルでは、現在のTRTCアプリケーションと同じSDKAppIDのIM体験版アプリケーションが自動的に同期して作成され、両方のアカウントと認証システムを共通して利用できます。その後、必要に応じてTRTCまたはIMアプリケーションのバージョンをアップグレードすることができます。たとえば、プレミアム版では、より多くの付加価値機能サービスが使えます。



説明:
テスト環境と本番環境に使用するアプリケーションをそれぞれ作成することをお勧めします。1年間に各Tencent Cloudアカウント(UIN)に毎月10,000分間の無料時間が提供されます。
TRTC月額プランは体験版(デフォルト)、ベーシック版、プロフェッショナル版に分かれており、異なる付加価値機能サービスが使えます。詳細はバージョン機能と月額プランの説明を参照してください。
2. アプリケーションが作成された後、「アプリケーション管理→アプリケーション概要セクション」を選択してそのアプリケーションの基本情報を確認できます。この一連の操作において、これからの便宜上、SDKAppIDSDKSecretKeyを大切に保管してください。また、キーの漏洩によるトラフィックの不正利用にご注意ください。




ステップ2:SDKをインポートする

TRTC SDKとIM SDKはmavenCentralレポジトリーにパブリッシュされました。gradleを設定することで自動的に更新をダウンロードできます。
1. dependenciesに適切なバージョンのSDK依存を追加してください。
dependencies {
// TRTC Lite版SDK、TRTCとライブ再生の2つの機能を含みます。
implementation 'com.tencent.liteav:LiteAVSDK_TRTC:latest.release'
// IM SDKを追加、最新のバージョン番号を記入することがお勧めです。
implementation 'com.tencent.imsdk:imsdk-plus:Version number'
// Quicプラグインを追加する必要がある場合、次の行のコメントを解除(注意:プラグインのバージョン番号とIM SDKのバージョン番号が同じである必要がある)
// implementation 'com.tencent.imsdk:timquic-plugin:Version number'
}
説明:
推奨される自動読み込みの方法以外に、SDKをダウンロードして手動でインポートすることもできます。詳細はTRTC SDKの手動統合IM SDKの手動統合を参照してください。
Quicプラグインはaxp-quicマルチキャスト伝送プロトコルを提供し、回線品質低下環境にも強く、ネットワークのパケットロス率が70%に達してもサービスを提供できます。アルティメット版のユーザーにのみ開放されており、非アルティメット版の場合は、アルティメットプランを購入した後に使用できます。詳細は価格説明を参照してください。機能が正常に動作するために、ターミナルSDKをバージョン7.7.5282以上に更新してください。
2. defaultConfigで、Appが使用するCPUアーキテクチャを指定します。
defaultConfig {
ndk {
abiFilters "armeabi-v7a", "arm64-v8a"
}
}
説明:
TRTC SDKはarmeabi/armeabi-v7a/arm64-v8aアーキテクチャをサポートし、さらにエミュレータ専用のx86/x86_64アーキテクチャもサポートします。
IM SDKはarmeabi-v7a/arm64-v8a/x86/x86_64アーキテクチャをサポートしており、インストールパッケージのサイズを削減するため、特定のアーキテクチャのSOファイルのみをパッケージに含めることができます。

ステップ3:プロジェクトの設定

1. AndroidManifest.xmlでアプリの権限を設定し、オーディオ・ビデオ通話シナリオではTRTC SDKおよびIM SDKに以下の権限が必要です。
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera.autofocus" />
注意:
android:hardwareAccelerated="false"を設定しないでください。ハードウェアアクセラレーションをオフにすると、相手のビデオストリームがレンダリングできなくなります。
TRTC SDKは権限申請ロジックが構築されていないため、対応する権限について自分で宣言する必要があります。一部の権限(例えば、ストレージ、録音、カメラなど)は、実行時に動的な申請が必要です。
もしAndroidプロジェクトのtargetSdkVersionが31または対象デバイスがAndroid 12以上のシステムバージョンに関連している場合、Bluetooth機能を正常に使用するため、公式にはコード内でandroid.permission.BLUETOOTH_CONNECT権限を動的な申請する必要があります。詳細はBluetooth権限を参照してください。
2. 私たちはSDK内部でJavaのリフレクション特性を使用しているため、proguard-rules.proファイル内でSDK関連クラスを難読化しないリストに追加する必要があります。
-keep class com.tencent.** { *; }

ステップ4:認証クレデンシャル

UserSigはTencent Cloudが設計したセキュリティ保護署名で、悪意のある攻撃者がクラウドサービスの使用権を盗用するのを防ぐためのものです。Tencent CloudのReal-Time Communication(TRTC)とChat(IM)サービスは、このセキュリティ保護メカニズムを採用しており、TRTCは入室時に認証を行い、IMはログイン時に認証を行います。
デバッグフェーズクライアントサンプルコードコントロールパネル取得の2つの方法でUserSigを計算生成でき、デバッグテストのみに使用します。
本番フェーズ:クライアントのリバースエンジニアリングによるキーの漏洩を防ぐため、より高いセキュリティレベルのサーバー側UserSig計算を推奨します。
具体的な実装の流れは以下の通りです。
1. AppがSDKの初期化関数を呼び出す前に、最初にサーバーにUserSigをリクエストします。
2. サーバーはSDKAppIDとUserIDに基づいてUserSigを計算します。
3. サーバーは計算されたUserSigをAppに返します。
4. Appは、特定のAPIを通じてSDKにUserSigを伝達します。
5. SDKがSDKAppID + UserID + UserSigをTencent Cloudのクラウドサーバーに提出して検証します。
6. Tencent CloudはUserSigを検証し、合法性を確認します。
7. 検証を通過した後、IM SDKにChatサービスを提供し、TRTC SDKにReal-Time Communicationサービスを提供します。



注意:
デバッグフェーズのローカルUserSig計算方式をオンライン環境に適用することは推奨しません。逆コンパイルによって容易に解読され、キーが漏洩する可能性があります。
複数の言語(Java/GO/PHP/Node.js/Python/C#/C++)のUserSigサーバーサイド計算のソースコードを提供しています。詳細はサーバーサイドUserSig計算を参照してください。

ステップ5:SDKの初期化

1. IM SDK初期化とイベントモニターの追加
// イベントリスナーを追加
V2TIMManager.getInstance().addIMSDKListener(imSdkListener);
// IM SDKを初期化、このインターフェースを呼び出した後、すぐにログインインターフェースを呼び出すことができます。
V2TIMManager.getInstance().initSDK(context, sdkAppID, null);
// SDK初期化後にはいくつかのイベントが発生します。例えば、接続状態、ログインチケットの有効期限切れなど。
private V2TIMSDKListener imSdkListener = new V2TIMSDKListener() {
@Override
public void onConnecting() {
Log.d(TAG, "IM SDKがTencent Cloudクラウドサーバーに接続中");
}
@Override
public void onConnectSuccess() {
Log.d(TAG, "IM SDKはすでにTencent Cloudクラウドサーバーに接続しました");
}
};
// イベントリスナーを削除
V2TIMManager.getInstance().removeIMSDKListener(imSdkListener);
// IM SDKの初期化解除
V2TIMManager.getInstance().unInitSDK();
説明:
アプリケーションのライフサイクルがSDKのライフサイクルと一致している場合、アプリケーションを終了する前に初期化解除を行う必要はありません。特定の画面に入った後にのみSDKを初期化し、その画面を離れた後は使用しない場合は、SDKをデイニシャライゼーションすることができます。
2. TRTC SDKインスタンスの作成とイベントモニターの設定
// TRTC SDKのインスタンスを作成する(シングルトンパターン)
TRTCCloud mTRTCCloud = TRTCCloud.sharedInstance(context);
// TRTCイベントリスナーを追加
mTRTCCloud.addListener(trtcSdkListener);
// SDKからの各種イベント通知(例:エラーコード、警告コード、オーディオ・ビデオの状態パラメータなど)
private TRTCCloudListener trtcSdkListener = new TRTCCloudListener() {
@Override
public void onError(int errCode, String errMsg, Bundle extraInfo) {
Log.d(TAG, errCode + errMsg);
}
@Override
public void onWarning(int warningCode, String warningMsg, Bundle extraInfo) {
Log.d(TAG, warningCode + warningMsg);
}
};
// TRTCイベントリスナーを削除
mTRTCCloud.removeListener(trtcSdkListener);
// TRTC SDKインスタンスを破棄する(シングルトンパターン)
TRTCCloud.destroySharedInstance();
説明:
SDKイベント通知のモニタリングを推奨します。一般的なエラーに関するログ出力と処理についてはエラーコード表を参照してください。

アクセスの流れ

ステップ1:ログイン

IM SDK初期化後、SDKログインインターフェースを呼び出してアカウントの身元を検証し、アカウントの機能使用権限を取得する必要があります。そのため、他の機能を使用する前に、必ずログインしたことを確認してください。ログインされない場合、機能が異常になったり利用できなくなったりする可能性があります。TRTCのオーディオ・ビデオサービスのみをご利用の場合、このステップを無視しても構いません。

タイムライン図





ログイン操作

// ログイン:userIDはカスタマイズ可能、userSigはステップ1を参照して取得します。
V2TIMManager.getInstance().login(userID, userSig, new V2TIMCallback() {
@Override
public void onSuccess() {
Log.i("imsdk", "success");
}
@Override
public void onError(int code, String desc) {
// 以下のエラーコードが返された場合、UserSigの使用期限が切れている。新しく発行されたUserSigを使用して再ログインします。
// 1. ERR_USER_SIG_EXPIRED(6206)
// 2. ERR_SVR_ACCOUNT_USERSIG_EXPIRED(70001)
// 注意:他のエラーコードの場合、IM SDKのログインが無限ループになる恐れがありますので、ログインインターフェースをここで呼び出さないでください。
Log.i("imsdk", "failure, code:" + code + ", desc:" + desc);
}
});

ログアウト操作

// ログアウト
V2TIMManager.getInstance().logout(new V2TIMCallback() {
@Override
public void onSuccess() {
Log.i("imsdk", "success");
}
@Override
public void onError(int code, String desc) {
Log.i("imsdk", "failure, code:" + code + ", desc:" + desc);
}
});
説明:
アプリケーションのライフサイクルがIM SDKのライフサイクルと一致している場合、アプリケーションを終了する前にログアウトする必要はありません。特定の画面に入った後にのみIM SDKを使用し、その画面を離れた後は使用しない場合は、ログアウトおよびIM SDKをデイニシャライゼーションすることができます。

ステップ2:発信

タイムライン図





発信を開始する

1. 発信側ローカル画面プレビュー(ビデオ通話の場合のみが必要、ボイス通話の場合このステップをスキップ)
// ビデオエンコードのパラメータを設定し、リモートのユーザーが見る画面の品質を決定
TRTCCloudDef.TRTCVideoEncParam encParam = new TRTCCloudDef.TRTCVideoEncParam();
encParam.videoResolution = TRTCCloudDef.TRTC_VIDEO_RESOLUTION_960_540;
encParam.videoFps = 15;
encParam.videoBitrate = 850;
encParam.videoResolutionMode = TRTCCloudDef.TRTC_VIDEO_RESOLUTION_MODE_PORTRAIT;
mTRTCCloud.setVideoEncoderParam(encParam);
// ローカルのカメラプレビューを開始(イン/アウトカメラを指定してビデオキャプチャーが可能)
mTRTCCloud.startLocalPreview(isFrontCamera, previewView);
注意:
業務のニーズに応じて、ビデオエンコーディングのパラメータTRTCVideoEncParamを自由に設定できます。各グレードの最適な解像度とビットレートの組み合わせの詳細は、解像度ビットレート参照表を参照してください。
enterRoomの前に、上記のインターフェースを呼び出すと、SDKはカメラのプレビューのみを開始し、enterRoomを呼び出すまでローカルビデオのプッシュストリームを開始しません。
2. 発信側が通話招待のシグナルを送信
// カスタムデータの構築
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("cmd", "av_call");
JSONObject msgJsonObject = new JSONObject();
msgJsonObject.put("callType", "videoCall"); // 通話タイプ(ビデオ通話、ボイス通話)を指定
msgJsonObject.put("roomId", generateRoomId()); // TRTCルーム番号を指定(発信側でランダム生成)
jsonObject.put("msg", msgJsonObject);
} catch (JSONException e) {
e.printStackTrace();
}
String data = jsonObject.toString();
// 通話招待シグナルを送信
V2TIMManager.getSignalingManager().invite(receiver, data, false, v2TIMOfflinePushInfo, timeout, new V2TIMCallback() {
@Override
public void onError(int code, String desc) {
// 通話招待シグナルの送信に失敗
// 発信失敗、再試行可能
}
@Override
public void onSuccess() {
// 通話招待シグナルの送信に成功
// 発信ページをレンダリングし、呼出音を再生
}
});
注意:
オーディオ・ビデオ通話シナリオでは、通常、招待シグナルにオフラインプッシュ情報v2TIMOfflinePushInfoを設定する必要があります。詳細はオフラインプッシュメッセージを参照してください。
招待シグナル内で合理的なタイムアウトパラメータtimeoutを設定することをお勧めします。単位は秒です。SDKはタイムアウトしたかを検知し、発信がタイムアウトした時の自動切断を実現します。
3. 着信側に通話招待通知が届く
// 着信ユーザーが発信リクエストを受信し、inviteIDはそのリクエストのためのID、inviterは発信ユーザーのIDです。
V2TIMManager.getSignalingManager().addSignalingListener(new V2TIMSignalingListener() {
@Override
public void onReceiveNewInvitation(String inviteID, String inviter,
String groupId, List<String> inviteeList, String data) {
if (!data.isEmpty()) {
try {
JSONObject jsonObject = new JSONObject(data);
String command = jsonObject.getString("cmd");
JSONObject messageJsonObject = jsonObject.getJSONObject("msg");
if (command.equals("av_call")) {
String callType = messageJsonObject.getString("callType");
String roomId = messageJsonObject.getString("roomId");
// 発信ページをレンダリングし、呼出音を再生
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
});
注意:
発信側が発信リクエストを開始し、着信音が発信リクエストを受け取った時、開発者は発信/着信ページのレンダリングと呼出音の再生を自身で実装する必要があります。
4. 着信側ローカル画面プレビュー(ビデオ通話の場合のみが必要、ボイス通話の場合このステップをスキップ)
if (callType.equals("videoCall")) {
// ビデオエンコードのパラメータを設定し、リモートのユーザーが見る画面の品質を決定
TRTCCloudDef.TRTCVideoEncParam encParam = new TRTCCloudDef.TRTCVideoEncParam();
encParam.videoResolution = TRTCCloudDef.TRTC_VIDEO_RESOLUTION_960_540;
encParam.videoFps = 15;
encParam.videoBitrate = 850;
encParam.videoResolutionMode = TRTCCloudDef.TRTC_VIDEO_RESOLUTION_MODE_PORTRAIT;
mTRTCCloud.setVideoEncoderParam(encParam);
// ローカルのカメラプレビューを開始(イン/アウトカメラを指定してビデオキャプチャーが可能)
mTRTCCloud.startLocalPreview(isFrontCamera, previewView);
}

発信取消

1. 発信側が呼び出しをキャンセル
V2TIMManager.getSignalingManager().cancel(inviteId, data, new V2TIMCallback() { @Override public void onError(int code, String desc) { // 呼び出しのキャンセルに失敗しました
// 提示のキャンセルに失敗しました。再試行してみてください。 } @Override public void onSuccess() { // 呼び出しをキャンセルしました
// 発信ページが破棄され、呼び出し音の再生が停止します } });
2. 着信側にキャンセルの通知が届く
@Override public void onInvitationCancelled(String inviteID, String inviter, String data) {
// 発信ページが破棄され、呼び出し音の再生が停止します }

発信タイムアウト

発信側と着信側の両方にタイムアウトの通知が届き、同時に発信/着信ページが破棄され、呼出音/着信音の再生が停止します。
@Override
public void onInvitationTimeout(String inviteID, List<String> inviteeList) {
// タイムアウトの通知、ページの破棄、呼出着信音の再生停止
}

ステップ3:応答

シグナルを受信

1. 着信側が受取のシグナルを送信
V2TIMManager.getSignalingManager().accept(inviteId, data, new V2TIMCallback() { @Override public void onError(int code, String desc) { // 応答に失敗、「例外が発生しました」、「再試行してください」が表示されます。 } @Override public void onSuccess() { // 応答に成功、通話ページをレンダリング、呼出音の再生が停止します。
if (callType.equals("videoCall")) {
// ビデオ通話を開始
startVideoCall();
} else {
// ボイス通話を開始
startAudioCall();
} } });
2. 発信側が応答通知を受信
@Override
public void onInviteeAccepted(String inviteID, String invitee, String data) {
if (callType.equals("videoCall")) {
// ビデオ通話を開始
startVideoCall();
} else {
// ボイス通話を開始
startAudioCall();
}
}

ボイス通話

1. 発信側と着信側は共に同じTRTCルームに入り、ボイス通話を開始します。
private void startAudioCall() {
TRTCCloudDef.TRTCParams params = new TRTCCloudDef.TRTCParams(); params.sdkAppId = SDKAPPID; // TRTCアプリケーションID、コントロールパネルで取得 params.userSig = USERSIG; // TRTC認証クレデンシャル、サーバー側で生成
params.strRoomId = roomId; // 部屋番号、文字列の部屋番号を例に params.userId = userId; // ユーザー名はIMに同期することをお勧めします
mTRTCCloud.startLocalAudio(TRTCCloudDef.TRTC_AUDIO_QUALITY_SPEECH);
mTRTCCloud.enterRoom(params, TRTCCloudDef.TRTC_APP_SCENE_AUDIOCALL);
}
注意:
ボイス通話モードで、TRTC入室シナリオはTRTC_APP_SCENE_AUDIOCALLを選択する必要があります。入室ロールTRTCRoleTypeを指定しないでください。
音声キャプチャーstartLocalAudioを開始する時、音質パラメータを設定できます。ボイス通話モードではTRTC_AUDIO_QUALITY_SPEECHに設定することをお勧めします。
SDKデフォルトの自動購読モードでは、ユーザーがルームに入ると、そのルームのオーディオストリームをすぐに受信し、オーディオは自動的にデコードされ再生されます。手動でプルストリームする必要はありません。
2. 入室結果で通話状態をラベリングします。
// 通話の状態をラベリングする
boolean isOnCalling = false;
// 入室結果イベントコールバック
@Override
public void onEnterRoom(long result) {
if (result > 0) {
// 入室成功、通話中であることをラベリングする
isOnCalling = true;
} else {
// 入室失敗、通話異常を表示
isOnCalling = false;
}
}

ビデオ通話

1. 発信側と着信側が同じTRTCルームに入り、ビデオ通話を開始します。
private void startVideoCall() {
TRTCCloudDef.TRTCParams params = new TRTCCloudDef.TRTCParams();
params.sdkAppId = SDKAPPID; // TRTCアプリケーションID、コントロールパネルで取得
params.userSig = USERSIG; // TRTC認証クレデンシャル、サーバー側で生成
params.strRoomId = roomId; // 部屋番号、文字列の部屋番号を例に
params.userId = userId; // ユーザー名はIMに同期することをお勧めします
mTRTCCloud.startLocalAudio(TRTCCloudDef.TRTC_AUDIO_QUALITY_SPEECH);
mTRTCCloud.enterRoom(params, TRTCCloudDef.TRTC_APP_SCENE_VIDEOCALL);
}
注意:
ビデオ通話モードで、TRTC入室シナリオはTRTC_APP_SCENE_VIDEOCALLを選択する必要があります。入室ロールTRTCRoleTypeを指定しないでください。
音声キャプチャーstartLocalAudioを開始する時、音質パラメータを設定できます。ビデオ通話モードではTRTC_AUDIO_QUALITY_SPEECHに設定することをお勧めします。
SDKデフォルトの自動購読モードでは、音声は自動的にデコードされて再生されますが、ビデオは手動でstartRemoteViewを呼び出してリモートビデオストリームをプルしてレンダリングし再生する必要があります。
2. 入室結果で通話状態をラベリングし、リモートビデオストリームをプルします。
// 通話の状態をラベリングする
boolean isOnCalling = false;
// 入室結果イベントコールバック
@Override
public void onEnterRoom(long result) {
if (result > 0) {
// 入室成功、通話中であることをラベリングする
isOnCalling = true;
} else {
// 入室失敗、通話異常を表示
isOnCalling = false;
}
}
// リモートビデオストリームをプル
@Override
public void onUserVideoAvailable(String userId, boolean available) {
// リモートユーザーがメインビデオ画面をパブリッシュ/キャンセル
if (available) {
// リモートユーザーのビデオストリームを購読し、ビデオレンダリングコントロールにバインド
mTRTCCloud.startRemoteView(userId, TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG, view);
} else {
// リモートユーザーのビデオストリームの購読を停止し、レンダリングコントロールをリリース
mTRTCCloud.stopRemoteView(userId, TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG);
}
}

ステップ4:拒否

タイムライン図





アクティブ拒否

1. 着信側が通話拒否シグナルを送信
private void rejectInvite(String inviteId, String data, final V2TIMCallback callback) { V2TIMManager.getSignalingManager().reject(inviteId, data, new V2TIMCallback() { @Override public void onError(int code, String desc) { if (callback != null) { callback.onError(code, desc); } } @Override public void onSuccess() { if (callback != null) { callback.onSuccess(); } } }); }
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("cmd", "av_call");
JSONObject msgJsonObject = new JSONObject();
msgJsonObject.put("callType", "videoCall"); // 通話タイプ(ビデオ通話、ボイス通話)を指定
msgJsonObject.put("reason", "active"); // 拒否タイプを指定(アクティブ拒否、ビジー拒否)
jsonObject.put("msg", msgJsonObject);
} catch (JSONException e) {
e.printStackTrace();
}
rejectInvite(inviteId, jsonObject.toString(), new V2TIMCallback() { @Override public void onError(int code, String desc) { // 拒否に失敗、「例外が発生しました」、「再試行してください」が表示されます。 } @Override public void onSuccess() { // 拒否に成功、発信ページが破棄され、着信音の再生をが停止します。 } });
2. 発信側が拒否通知を受け取る
@Override public void onInviteeRejected(String inviteID, String invitee, String data) {
if (!data.isEmpty()) {
try {
JSONObject jsonObject = new JSONObject(data);
String command = jsonObject.getString("cmd");
JSONObject messageJsonObject = jsonObject.getJSONObject("msg");
if (command.equals("av_call")) {
String reason = messageJsonObject.getString("reason");
if (reason.equals("active")) {
// 相手が拒否したと表示
} else if (reason.equals("busy")) {
// 相手がビジー状態であると表示
}
// 発信ページが破棄され、呼び出し音の再生が停止します
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}

ビジー拒否

着信側に新しい通話招待が届いた場合、ローカルの通話状態が通話中であると判断したら、自動的にビジー拒否が実行されます。
@Override
public void onReceiveNewInvitation(String inviteID, String inviter,
String groupId, List<String> inviteeList, String data) {
if (!data.isEmpty()) {
try {
JSONObject jsonObject = new JSONObject(data);
String command = jsonObject.getString("cmd");
JSONObject messageJsonObject = jsonObject.getJSONObject("msg");
if (command.equals("av_call") && isOnCalling) {
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("cmd", "av_call");
JSONObject msgJsonObject = new JSONObject();
msgJsonObject.put("callType", "videoCall"); // 通話タイプ(ビデオ通話、ボイス通話)を指定
msgJsonObject.put("reason", "busy"); // 拒否タイプを指定(アクティブ拒否、ビジー拒否)
jsonObject.put("msg", msgJsonObject);
} catch (JSONException e) {
e.printStackTrace();
}
// ローカル通話中、ビジー拒否シグナルを送信
rejectInvite(inviteId, jsonObject.toString(), new V2TIMCallback() {
@Override
public void onError(int code, String desc) {
// ビジー拒否に失敗
}
@Override
public void onSuccess() {
// ビジー拒否に成功
}
});
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
注意:
アクティブ拒否とビジー拒否は両方ともrejectシグナリングで実現されていますが、シグナリングのカスタムデータであるdatareasonフィールドを通じて区別する必要があります。

ステップ5:切断

タイムライン図





通話を切断

1. 任意側が部屋から退出すると、ローカル通話状態がリセットされます。
private void hangup() {
mTRTCCloud.stopLocalAudio();
mTRTCCloud.stopLocalPreview();
mTRTCCloud.exitRoom();
}
@Override
public void onExitRoom(int reason) {
// 部屋から正常に退出し、通話を切断しました
isOnCalling = false;
}
2. もう一方にリモート退室の通知が届いた場合、ローカルで退室を実行し、通話状態がリセットされます。
@Override
public void onRemoteUserLeaveRoom(String userId, int reason) {
hangup();
}
@Override
public void onExitRoom(int reason) {
// 部屋から正常に退出し、通話を切断しました
isOnCalling = false;
}

ステップ6:機能制御

マイクのオン・オフ

// マイクをオンにする
mTRTCCloud.muteLocalAudio(false);
// マイクをオフにする
mTRTCCloud.muteLocalAudio(true);

スピーカーのオン・オフ

// スピーカーをオンにする
mTRTCCloud.muteAllRemoteAudio(false);
// スピーカーをオフにする
mTRTCCloud.muteAllRemoteAudio(true);

カメラのオン・オフ

// カメラを開き、イン・アウトカメラとレンダリングコントロールを指定
mTRTCCloud.startLocalPreview(isFrontCamera, videoView);
// カメラをオフにする
mTRTCCloud.stopLocalPreview();

スピーカーとハンズフリーの切り替え

// スピーカーに切り替える
mTRTCCloud.getDeviceManager().setAudioRoute(TXDeviceManager.TXAudioRoute.TXAudioRouteEarpiece);
// ハンズフリーに切り替える
mTRTCCloud.getDeviceManager().setAudioRoute(TXDeviceManager.TXAudioRoute.TXAudioRouteSpeakerphone);

カメラの切り替え

// 現在がインカメラかどうかを判断
boolean isFrontCamera = mTRTCCloud.getDeviceManager().isFrontCamera();
// 前後カメラの切り替え、true: :インカメラに切り替える、; false: :アウトカメラに切り替える
mTRTCCloud.getDeviceManager().switchCamera(!isFrontCamera);

詳細設定

ネットワーク状態の提示

オーディオ・ビデオ通話において、通話がカクカクする心の準備をするために、相手の通信状況に関する通知を送る必要があります。
@Override
public void onNetworkQuality(TRTCCloudDef.TRTCQuality localQuality, ArrayList<TRTCCloudDef.TRTCQuality> remoteQuality) {
if (remoteQuality.size() > 0) {
switch (remoteQuality.get(0).quality) {
case TRTCCloudDef.TRTC_QUALITY_Excellent:
Log.i(TAG, "相手のネットワーク状態がとてもいい");
break;
case TRTCCloudDef.TRTC_QUALITY_Good:
Log.i(TAG, "相手のネットワーク状態が比較的良い");
break;
case TRTCCloudDef.TRTC_QUALITY_Poor:
Log.i(TAG, "相手のネットワーク状態が普通");
break;
case TRTCCloudDef.TRTC_QUALITY_Bad:
Log.i(TAG, "相手のネットワーク状態が不安定");
break;
case TRTCCloudDef.TRTC_QUALITY_Vbad:
Log.i(TAG, "相手のネットワーク状態がかなり悪い");
break;
case TRTCCloudDef.TRTC_QUALITY_Down:
Log.i(TAG, "相手のネットワーク状態が極めて悪い");
break;
default:
Log.i(TAG, "未定義");
break;
}
}
}
注意:
localQualityはローカルユーザーのネットワーク品質評価結果で、そのuserIdフィールドは空です。
remoteQualityはリモートユーザーのネットワーク品質評価結果を表し、その結果はリモートとローカルの両方の影響を受けます。

通話時間の統計

TRTCリモートユーザーの入室時間を通話時間の統計の開始時間、ローカルユーザーの退室時間を通話時間の統計の終了時間にすることをお勧めします。
// 通話開始時間
long callStartTime = 0;
// 通話終了時間
long callFinishTime = 0;
// 通話の持続時間(秒)
long callDuration = 0;
// リモートユーザー入室コールバック
@Override
public void onRemoteUserEnterRoom(String userId) {
callStartTime = System.currentTimeMillis();
}
// ローカルユーザー退室コールバック
@Override
public void onExitRoom(int reason) {
callFinishTime = System.currentTimeMillis();
callDuration = (callFinishTime - callStartTime) / 1000;
}
注意:
強制終了やネットワークの切断などの異常終了が発生した場合、クライアントでは関連する時間を統計できない可能性があります。これにより、サーバー側イベントコールバックで入退室イベントを監視し、この通話の時間を統計することができます。

ビデオ顔加工エフェクト

TRTCはサードパーティーの顔加工エフェクト製品をサポートし、以下にTencent Effectを例にして、サードパーティー顔加工のアクセスプロセスを示します。
1. Tencent Effect SDKを統合し、License認可を申請します。詳細はライブショー→アクセスの準備の手順を参照してください。
2. リソースコピー(該当する場合)。リソースファイルがassetsディレクトリに内蔵されている場合、使用する前にAppのプライベートディレクトリにcopyする必要があります。
XmagicResParser.setResPath(new File(getFilesDir(), "xmagic").getAbsolutePath());
//loading
//リソースファイルをプライベートディレクトリにcopyする必要がありますが、一度だけ実行必要です。
XmagicResParser.copyRes(getApplicationContext());
リソースファイルがネットワークから動的にダウンロードされた場合、ダウンロード成功後にリソースファイルのパスを設定する必要があります。
XmagicResParser.setResPath(ダウンロードしたリソースファイルのローカルパス);
3. サードパーティー顔加工のビデオデータコールバックを設定し、顔加工SDKに処理された各フレームの結果データをTRTC SDK内部でレンダリング処理に渡します。
mTRTCCloud.setLocalVideoProcessListener(TRTCCloudDef.TRTC_VIDEO_PIXEL_FORMAT_Texture_2D, TRTCCloudDef.TRTC_VIDEO_BUFFER_TYPE_TEXTURE, new TRTCCloudListener.TRTCVideoFrameListener() {
@Override
public void onGLContextCreated() {
// SDK内部のOpenGL環境が作成、この時点でサードパーティー顔加工の初期化作業が可能
if (mXmagicApi == null) {
XmagicApi mXmagicApi = new XmagicApi(context, XmagicResParser.getResPath(), new XmagicApi.OnXmagicPropertyErrorListener());
} else {
mXmagicApi.onResume();
}
}
@Override
public int onProcessVideoFrame(TRTCCloudDef.TRTCVideoFrame srcFrame, TRTCCloudDef.TRTCVideoFrame dstFrame) {
// サードパーティー顔加工コンポーネントをアクセスするためのビデオ処理コールバック
if (mXmagicApi != null) {
dstFrame.texture.textureId = mXmagicApi.process(srcFrame.texture.textureId, srcFrame.width, srcFrame.height);
}
return 0;
}
@Override
public void onGLContextDestory() {
// SDK内部のOpenGL環境が破棄、この時点でサードパーティー顔加工のリソース破棄が可能
mXmagicApi.onDestroy();
}
});
注意:
ステップ1、ステップ2は、異なるサードパーティ顔加工製品の実装方法によって異なりますが、ステップ3はTRTCにおいて、サードパーティー顔加工製品を統合するための共通で重要なステップです。
シナリオプランTencent Effect統合ガイドはTRTC SDKへのTencent Effectの統合を参照してください。Tencent Effectを単独で統合するガイドはTencent Effectの単独統合を参照してください。

ウィンドウサイズの切り替え

TRTCには、ビデオ画面を操作するための多くのインターフェースがあり、これらのインターフェースではビデオレンダリングコントロールを指定する必要があります。Androidプラットフォームでは、TXCloudVideoViewをビデオレンダリングコントロールとして使用し、SurfaceViewTextureViewの2つのレンダリング方式をサポートしています。以下、レンダリングコントロールのタイプを指定する方法と、ビデオレンダリングコントロールを更新する方法について説明します。
1. 特定のプランを強制的に使用したい場合や、ローカルビデオレンダリングコントロールをTXCloudVideoViewに変換したい場合は、以下の方法でプログラムを組めます。
// TextureViewの強制使用
TextureView textureView = findViewById(R.id.texture_view);
TXCloudVideoView cloudVideoView = new TXCloudVideoView(context);
cloudVideoView.addVideoView(textureView);
// SurfaceViewの強制使用
SurfaceView surfaceView = findViewById(R.id.surface_view);
TXCloudVideoView cloudVideoView = new TXCloudVideoView(surfaceView);
2. もし業務が表示エリアの切り替えるインタラクションがあるシナリオに関連している場合、TRTC SDKのローカルプレビュー画面更新、リモートユーザーのビデオレンダリングコントロール更新機能で実装できます。
// ローカルプレビュー画面のレンダリングコントロールを更新
mTRTCCloud.updateLocalView(videoView);
// リモートユーザーのビデオレンダリングコントロールを更新
mTRTCCloud.updateRemoteView(userId, streamType, videoView);
注意:
videoViewTXCloudVideoViewタイプのにターゲットビデオレンダリングコントロールです。streamTypeTRTC_VIDEO_STREAM_TYPE_BIGTRTC_VIDEO_STREAM_TYPE_SUBのみに対応します。

オフラインプッシュメッセージ

オーディオ・ビデオ通話シナリオでは通常、着信ユーザーAppがオフラインの場合でも着信メッセージを受け取ることができるように、オフラインプッシュメッセージを使用する必要があります。オフラインプッシュの統合ガイドについては、オフラインメッセージプッシュを参照してください。以下では、特にステップ7:オフラインプッシュメッセージを送信、ステップ8:オフラインプッシュメッセージを解析の実装方法について詳しく説明します。

オフラインプッシュメッセージの送信

inviteで通話招待を送る際、V2TIMOfflinePushInfoを通じてオフラインプッシュのパラメータを設定できます。V2TIMOfflinePushInfoのsetExtでカスタムextデータを設定し、ユーザーがオフラインプッシュが届いたときにアプリを起動し、通知をクリックしてジャンプする時のコールバックでextフィールドを取得できます。そして、extフィールドの内容に基づいて指定されたUIページにジャンプします。
import com.google.gson.Gson;
import com.tencent.imsdk.v2.V2TIMCallback;
import com.tencent.imsdk.v2.V2TIMManager;
import com.tencent.imsdk.v2.V2TIMOfflinePushInfo;
import com.tencent.qcloud.tuicore.TUILogin;
import com.tencent.qcloud.tuicore.push.OfflinePushExtConfigInfo;
import com.tencent.qcloud.tuicore.push.OfflinePushExtInfo;

import org.json.JSONException;
import org.json.JSONObject;

JSONObject contentObj = new JSONObject();
try {
contentObj.put("cmd", "av_call");
JSONObject contentDetailObj = new JSONObject();
contentDetailObj.put("callType", "videoCall");
contentDetailObj.put("roomId", generateRoomId());
contentObj.put("cmdInfo", contentDetailObj);
} catch (JSONException e) {
e.printStackTrace();
}
String data = contentObj.toString();

OfflinePushExtInfo offlinePushExtInfo = new OfflinePushExtInfo();

offlinePushExtInfo.getBusinessInfo().setSenderId(TUILogin.getLoginUser());
offlinePushExtInfo.getBusinessInfo().setSenderNickName(mNickname);
offlinePushExtInfo.getBusinessInfo().setFaceUrl(mFaceUrl);
offlinePushExtInfo.getBusinessInfo().setSendTime(System.currentTimeMillis() / 1000);
offlinePushExtInfo.getBusinessInfo().setDesc("You have a new call invitation");
offlinePushExtInfo.getBusinessInfo().setChatAction(OfflinePushExtInfo.REDIRECT_ACTION_CALL);
offlinePushExtInfo.getBusinessInfo().setCustomData(data.getBytes());

offlinePushExtInfo.getConfigInfo().setFCMPushType(OfflinePushExtConfigInfo.FCM_PUSH_TYPE_DATA);
offlinePushExtInfo.getConfigInfo().setFCMNotificationType(OfflinePushExtConfigInfo.FCM_NOTIFICATION_TYPE_TIMPUSH);

V2TIMOfflinePushInfo v2TIMOfflinePushInfo = new V2TIMOfflinePushInfo();
v2TIMOfflinePushInfo.setTitle(mNickname);
v2TIMOfflinePushInfo.setDesc("You have a new call invitation");
v2TIMOfflinePushInfo.setExt(new Gson().toJson(offlinePushExtInfo).getBytes());

v2TIMOfflinePushInfo.setAndroidOPPOChannelID("tuikit");
v2TIMOfflinePushInfo.setAndroidHuaWeiCategory("IM");
v2TIMOfflinePushInfo.setAndroidVIVOCategory("IM");

// カスタム着信音の設定
v2TIMOfflinePushInfo.setIOSSound("phone_ringing.mp3");
v2TIMOfflinePushInfo.setAndroidSound("phone_ringing");

v2TIMOfflinePushInfo.setIOSInterruptionLevel("time-sensitive");
v2TIMOfflinePushInfo.enableIOSBackgroundNotification(false);
v2TIMOfflinePushInfo.setAndroidHonorImportance("NORMAL");
v2TIMOfflinePushInfo.setAndroidMeizuNotifyType(1);

V2TIMManager.getSignalingManager().invite(receiver, data, false, v2TIMOfflinePushInfo, timeout, new V2TIMCallback() {
@Override
public void onError(int code, String desc) {
// 通話招待の送信に失敗
}
@Override
public void onSuccess() {
// 通話招待の送信に成功
}
});

オフラインプッシュメッセージの解析

オフラインプッシュの通知バーメッセージを受信すると、事前に設定したジャンプページに自動的にジャンプします。画面起動のonResume()メソッドで、getIntent().getExtras()を呼び出してパススルーされたオフラインプッシュのパラメータを取得し、カスタムジャンプを行うことができます。具体的にはTUIKitDemoのhandleOfflinePush()メソッドを参照してください。
private void handleOfflinePush() {
// ログイン状態に基づいて、IMに再ログインする必要があるかどうかを判断します。
// 1. ログイン状態がV2TIMManager.V2TIM_STATUS_LOGOUTの場合、ログイン画面に移動して、IMに再ログインします
if (V2TIMManager.getInstance().getLoginStatus() == V2TIMManager.V2TIM_STATUS_LOGOUT) {
Intent intent = new Intent(MainActivity.this, SplashActivity.class);
if (getIntent() != null) {
intent.putExtras(getIntent());
}
startActivity(intent);
finish();
return;
}
// 2. そうでない場合、アプリがバックグラウンドで待機しているだけで、オフラインプッシュパラメータを直接解析します。
final OfflineMessageBean bean = OfflineMessageDispatcher.parseOfflineMessage(getIntent());
if (bean != null) {
setIntent(null);
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (manager != null) {
manager.cancelAll();
}
if (bean.action == OfflineMessageBean.REDIRECT_ACTION_CALL) {
Intent startActivityIntent = new Intent(context, MyCustomActivity.class);
startActivityIntent.putExtras(getIntent());
startActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(startActivityIntent);
}
}
}
注意:
FCMは通知バーのメッセージをクリックすると、デフォルトでアプリデフォルトのLauncherページにジャンプします。画面起動のonResume()メソッドでgetIntent().getExtras()を呼び出してパススルーされたオフラインプッシュパラメータを取得し、カスタムジャンプを行うことができます。

例外処理

TRTCエラー処理

TRTC SDKは回復不可能なエラーが発生した場合、onErrorコールバックでスローされます。詳細はエラーコード表を参照してください。

UserSig関係

UserSig検証に失敗すると入室に失敗します。UserSigツールを使用して検証できます。
列挙値
取得値
説明
ERR_TRTC_INVALID_USER_SIG
-3320
入室パラメータUserSigが正しくありません。TRTCParams.userSigが空であるかどうかを確認してください。
ERR_TRTC_USER_SIG_CHECK_FAILED
-100018
UserSig検証失敗、パラメータTRTCParams.userSigが正しく入力されているか、または期限切れでないかを確認してください。

入退室関係

入室に失敗した場合は、まず入室パラメータが正しいかどうかを確認してください。また、入退室インターフェースは必ずペアで呼び出す必要があります。入室に失敗した場合でも、退室インターフェースを呼び出す必要があります。
列挙値
取得値
説明
ERR_TRTC_CONNECT_SERVER_TIMEOUT
-3308
入室リクエストがタイムアウトしました。ネットワークが切断されているか、VPNが使用されているかを確認してください。また、4Gに切り替えてテストすることもできます。
ERR_TRTC_INVALID_SDK_APPID
-3317
入室パラメータSDKAppIDエラー。TRTCParams.sdkAppIdが空であるかどうか確認してください。
ERR_TRTC_INVALID_ROOM_ID
-3318
入室パラメータroomIdエラー。TRTCParams.roomIdまたはTRTCParams.strRoomIdが空であるかどうか確認してください。roomIdとstrRoomIdは混在できません。
ERR_TRTC_INVALID_USER_ID
-3319
入室パラメータuserIdが正しくありません。TRTCParams.userIdが空であるかどうかを確認してください。
ERR_TRTC_ENTER_ROOM_REFUSED
-3340
入室リクエストが拒否されました。enterRoomで同じIdのルームに連続して入室しようとしていないか確認してください。

デバイス関係

デバイス関連のエラーをリスニングし、関連するエラーが発生した場合にUIでユーザーに通知します。
列挙値
取得値
説明
ERR_CAMERA_START_FAIL
-1301
カメラの起動に失敗しました。例えば、WindowsまたはMacデバイスで、カメラの設定プログラム(ドライバー)に異常があります。デバイスを無効にしてから再度有効にするか、マシンを再起動するか、または設定プログラムを更新してください。
ERR_MIC_START_FAIL
-1302
マイクの起動に失敗しました。例えば、WindowsまたはMacデバイスで、マイクの設定プログラム(ドライバー)に異常があります。デバイスを無効にしてから再度有効にするか、マシンを再起動するか、設定プログラムを更新してください。
ERR_CAMERA_NOT_AUTHORIZED
-1314
カメラが許可されていません。これは通常、モバイルデバイスで発生し、ユーザーによって権限が拒否された可能性があります。
ERR_MIC_NOT_AUTHORIZED
-1317
マイクが許可されていません。これは通常、モバイルデバイスで発生し、ユーザーによって権限が拒否された可能性があります。
ERR_CAMERA_OCCUPY
-1316
カメラが使用中です。他のカメラを試してみてください。
ERR_MIC_OCCUPY
-1319
マイクが使用中です。たとえば、モバイルデバイスが通話中の場合、マイクを開くと失敗します。

オフラインプッシュを受信できない時のトラブルシューティング

1. 送信したメッセージはカスタムメッセージの場合
カスタムメッセージのオフラインプッシュは通常のメッセージとは少し異なり、カスタムメッセージの内容は解析できず、プッシュする内容を確認できないため、デフォルトではプッシュしません。プッシュする必要がある場合、sendMessageの時にofflinePushInfodescフィールドを設定する必要があります。プッシュ時にはデフォルトでdesc情報が表示されます。
2. 端末の通知バー設定の影響
オフラインプッシュの最も直感的な表現は通知バーの提示であり、そのため他の通知と同様に、デバイスの通知関連設定の影響を受けます。例えば、Huaweiの場合:
「設定-通知-ロック画面通知-通知を表示しない」を選択することは、ロック画面の状態でのオフラインプッシュ通知の表示に影響します。
「設定-通知-その他の通知設定-通知バーに通知アイコンを表示する」を選択することは、ステータスバーでのオフラインプッシュ通知のアイコン表示に影響します。
「設定-通知-アプリの通知管理-通知を許可」を選択し、オン・オフにすることは、オフラインプッシュ通知の表示に直接影響します。
「設定-通知-アプリの通知管理-通知音」と「携帯電話の設定-通知-アプリの通知管理-サイレント通知」を選択することは、オフラインプッシュ通知の音に影響します。
3. 手順に従ってアクセスを完了してもオフラインプッシュを受信できない
まず、IMコントロールパネルでオフラインテストツールを通じて自己診断して、正常にプッシュできるかどうかを確認してください。プッシュに異常がある場合、デバイスの状態が異常であれば、IMコントロールパネルの設定の各パラメータが正しいかどうかを確認する必要があります。また、ベンダーのプッシュサービス登録とIMのオフラインプッシュ設定が正しく設定されているかどうかを含む、コードの初期化登録の過程を確認する必要があります。プッシュに異常があり、デバイスの状態が正常である場合、channel IDを正しく記入する必要があるかどうか、またはバックエンドサービスが正常に動作しているかどうかを確認する必要があります。
オフラインプッシュはベンダーの能力に依存し、一部の簡単な文字はベンダーによってフィルタリングされ、パススルーできない可能性があります。
オフラインプッシュメッセージがタイムリーにプッシュされない、または時々受信できない場合は、ベンダーのプッシュ制限を確認する必要があります。

画面遷移に失敗した

オフラインプッシュ通知の通知バーをタップすると、指定された画面にジャンプします。その原理は、バックエンドがコントロールパネルで設定した各ベンダーのジャンプ方法と画面パラメータに基づいて、ベンダーのインターフェースルールに従ってベンダーサーバーに伝達し、タップ時に対応する画面の起動とジャンプをします。対応する画面の起動は、マニフェストファイルの設定にも依存しており、コントロールパネルで設定されたものと一致していなければ、正しく起動してジャンプすることはできません。
1. まず、コントロールパネルとリストファイルの関連設定がお互いに対応しているかどうか、正しいかどうかを重点的に調査する必要があります。この辺の詳細はTUIKitDemoの設定を参照してください。なお、一部のベンダーが提供するインターフェース方法には違いがあることに注意してください。
2. 設定された画面にジャンプした場合は、設定画面内のオフラインメッセージの解析と画面のリダイレクトが正常であるかを再確認する必要があります。

ヘルプとサポート

この記事はお役に立ちましたか?

フィードバック