番号 | ライブルームのステータス |
1 | ライブストリーミング開始待機中 |
2 | ライブストリーミング中 |
3 | ライブストリーミング一時停止 |
4 | ライブストリーミング終了 |
5 | ライブストリーミングリプレイ中 |
番号 | 特徴 |
1 | ライブルームのステータス変更はライブルームのユーザーにリアルタイムで通知する必要がある |
2 | ライブルームの新規入室ユーザーは現在のライブルームのステータスを取得する必要がある |
2種類の実現方法 | メリット | デメリット |
ライブルームのステータスを何度も頻繁に取得する必要がある場合は、ライブルームのステータスをIMのグループプロファイルに保存する場合に比べて、業務バックエンドに保存することでIM SDKの呼び出し頻度を低下させることができます。IM SDKを統合していない場所に、取得したライブルームのステータスを提供できる可能性があります。 | 業務バックエンドがライブルームステータス読み取り/書き込みモジュールを追加で提供する必要があります。ライブルームデータは業務バックエンドとIMのグループプロファイルの両方から取得するため、ライブルームデータのエラー確率が上昇します。送信したカスタムメッセージが消失する可能性があります。メッセージ量が特に多い場合、優先度の低いメッセージが破棄され、それによってライブルームステータスの表示に影響することがあります。このため、ここでは高優先度のカスタムメッセージを使用することをお勧めします。 | |
開発者は追加のライブルームステータス読み取り/書き込みモジュールを提供する必要がありません。グループ属性変更コールバックは理論上は消失の可能性がありません。ライブルームデータはグループプロファイルから取得し、データソースが1つのため、エラーが少なくなります。 | 公開性の高いモジュールではグループプロファイルを頻繁に取得する必要があり、IMの負荷が増大します。IM SDKモジュールを統合していない場合は、業務バックエンドでIMサーバーSDKを呼び出してグループプロファイルを取得する必要があり、呼び出し頻度にも制限があります。 |
// クライアントがグループプロファイルを取得V2TIMManager.getGroupManager().getGroupsInfo(groupIDList, new V2TIMValueCallback<List<V2TIMGroupInfoResult>>() {@Overridepublic void onSuccess(List<V2TIMGroupInfoResult> v2TIMGroupInfoResults) {// グループプロファイルの取得に成功}@Overridepublic void onError(int code, String desc) {// グループプロファイルの取得に失敗}});// クライアントがグループプロファイルを変更V2TIMGroupInfo v2TIMGroupInfo = new V2TIMGroupInfo();v2TIMGroupInfo.setGroupID("変更したいグループID");v2TIMGroupInfo.setFaceUrl("http://xxxx");V2TIMManager.getGroupManager().setGroupInfo(v2TIMGroupInfo, new V2TIMCallback() {@Overridepublic void onSuccess() {// グループプロファイルの変更に成功}@Overridepublic void onError(int code, String desc) {// グループプロファイルの変更に失敗}});
[[V2TIMManager sharedInstance] getGroupsInfo:@[@"groupA"] succ:^(NSArray<V2TIMGroupInfoResult *> *groupResultList) {// グループプロファイルの取得に成功} fail:^(int code, NSString *desc) {// グループプロファイルの取得に失敗}];V2TIMGroupInfo *info = [[V2TIMGroupInfo alloc] init];info.groupID = @"変更したいグループID";info.faceURL = @"http://xxxx";[[V2TIMManager sharedInstance] setGroupInfo:info succ:^{// グループプロファイルの変更に成功} fail:^(int code, NSString *desc) {// グループプロファイルの変更に失敗}];
// グループプロファイルの取得V2TimValueCallback<List<V2TimGroupInfoResult>> groupinfos = await groupManager.getGroupsInfo(groupIDList: ['groupid1']);// グループプロファイルの変更groupManager.setGroupInfo(info: V2TimGroupInfo.fromJson({"groupAddOpt":GroupAddOptTypeEnum.V2TIM_GROUP_ADD_AUTH// ...その他のプロファイル}));// コールバックTencentImSDKPlugin.v2TIMManager.addGroupListener(listener: V2TimGroupListener(onGroupInfoChanged: ((groupID, changeInfos) {// グループ情報変更コールバック})));
// グループプロファイルの取得let promise = tim.getGroupProfile({ groupID: 'group1', groupCustomFieldFilter: ['key1','key2'] });promise.then(function(imResponse) {console.log(imResponse.data.group);}).catch(function(imError) {console.warn('getGroupProfile error:', imError); // 詳細なグループプロファイル取得失敗の関連情報});// グループプロファイルの変更let promise = tim.updateGroupProfile({groupID: 'group1',name: 'new name', // グループ名の変更introduction: 'this is introduction.', // グループ概要の変更// v2.6.0からは、グループメンバーがグループカスタムフィールド変更のグループプロンプトメッセージを受信でき、関連する内容を取得できるようになりました。詳細についてはMessage.payload.newGroupProfile.groupCustomFieldをご参照くださいgroupCustomField: [{ key: 'group_level', value: 'high'}] // グループディメンションカスタムフィールドの変更});promise.then(function(imResponse) {console.log(imResponse.data.group) // 変更後のグループの詳細データ}).catch(function(imError) {console.warn('updateGroupProfile error:', imError); // グループ情報変更失敗の関連情報});// v2.6.2からは、全員ミュートおよびミュート解除機能が利用できます。現在はグループ全員をミュートにすると、グループプロンプトメッセージの送信がサポートされません。let promise = tim.updateGroupProfile({groupID: 'group1',muteAllMembers: true, // trueは全員ミュート、falseは全員ミュートの解除を表します});promise.then(function(imResponse) {console.log(imResponse.data.group) // 変更後のグループの詳細データ}).catch(function(imError) {console.warn('updateGroupProfile error:', imError); // グループ情報変更失敗の関連情報});
優先度 | 意味 |
High | 高優先度 |
Normal | 通常の優先度 |
Low | 低優先度 |
// カスタムメッセージの作成V2TIMMessage v2TIMMessage = V2TIMManager.getMessageManager().createCustomMessage("シングルチャットカスタムメッセージ".getBytes());// メッセージの優先度を高優先度メッセージに設定しますv2TIMMessage.setPriority(V2TIMMessage.V2TIM_PRIORITY_HIGH)// メッセージを送信しますV2TIMManager.getMessageManager().sendMessage(v2TIMMessage, "receiver_userID", null, V2TIMMessage.V2TIM_PRIORITY_NORMAL, false, null, new V2TIMSendCallback<V2TIMMessage>() {@Overridepublic void onProgress(int progress) {// カスタムメッセージは進捗をコールバックしません}@Overridepublic void onSuccess(V2TIMMessage message) {// グループチャットカスタムメッセージの送信に成功しました}@Overridepublic void onError(int code, String desc) {// グループチャットカスタムメッセージの送信に失敗しました}});
/ テキストメッセージを作成しますV2TIMMessage *message = [[V2TIMManager sharedInstance] createTextMessage:@"content"];// メッセージを送信します[V2TIMManager.sharedInstance sendMessage:messagereceiver:@"userID"groupID:nilpriority:V2TIM_PRIORITY_NORMALonlineUserOnly:NOofflinePushInfo:nilprogress:nilsucc:^{// テキストメッセージ送信に成功しました}fail:^(int code, NSString *desc) {// テキストメッセージ送信に失敗しました}];
/ テキストメッセージを作成しますV2TimValueCallback<V2TimMsgCreateInfoResult> createTextAtMessageRes = await TencentImSDKPlugin.v2TIMManager.getMessageManager().createTextAtMessage(text: "test",atUserList: [],);if(createTextAtMessageRes.code == 0){String id = createTextAtMessageRes.data.id;// テキストメッセージを送信しますV2TimValueCallback<V2TimMessage> sendMessageRes = await TencentImSDKPlugin.v2TIMManager.getMessageManager().sendMessage(id: id, receiver: "", groupID: "groupID");if(sendMessageRes.code == 0){// 送信に成功}}
// テキストメッセージを送信します// 1. メッセージインスタンスを作成します。インターフェースから返されたインスタンスを画面に表示できますlet message = tim.createTextMessage({to: 'user1',conversationType: TIM.TYPES.CONV_C2C,// メッセージの優先度をグループチャットに適用します(v2.4.2からサポート)。あるグループのメッセージが頻度制限を超過すると、バックエンドは高優先度のメッセージを優先的に送信します。詳細については、https://www.tencentcloud.com/document/product/269/3663?from_cn_redirect=1#.E6.B6.88.E6.81.AF.E4.BC.98.E5.85.88.E7.BA.A7.E4.B8.8E.E9.A2.91.E7.8E.87.E6.8E.A7.E5.88.B6)をご参照ください// サポートされる列挙値:TIM.TYPES.MSG_PRIORITY_HIGH, TIM.TYPES.MSG_PRIORITY_NORMAL(デフォルト), TIM.TYPES.MSG_PRIORITY_LOW, TIM.TYPES.MSG_PRIORITY_LOWEST// priority: TIM.TYPES.MSG_PRIORITY_NORMAL,payload: {text: 'Hello world!'},// v2.20.0からは、C2Cメッセージの開封確認機能がサポートされました。送信したメッセージの開封確認が必要な場合は、フラッグシップ版パッケージをご購入の上、メッセージの作成時にneedReadReceiptをtrueに設定する必要がありますneedReadReceipt: true// メッセージのカスタムデータ(クラウドに保存され、相手側に送信されます。プログラムをアンインストールして再インストールした後でも取得できます。v2.10.2からサポート)// cloudCustomData: 'your cloud custom data'});// 2. メッセージの送信let promise = tim.sendMessage(message);promise.then(function(imResponse) {// 送信に成功console.log(imResponse);}).catch(function(imError) {// 送信に失敗console.warn('sendMessage error:', imError);});
{"CallbackCommand": "Group.CallbackAfterSendMsg", // コールバックコマンド"GroupId": "@TGS#2J4SZEAEL", // グループID"Type": "Public", // グループタイプ"From_Account": "jared", // 送信者"Operator_Account":"admin", // リクエストの送信者"Random": 123456, // 乱数"MsgSeq": 123, // メッセージ番号"MsgTime": 1490686222, // メッセージの時間"OnlineOnlyFlag": 1, //オンラインメッセージは1、そうでない場合は0となります。ライブストリーミンググループの場合はこの属性を無視し、デフォルト値の0とします。"MsgBody": [ // メッセージボディです。TIMMessageのメッセージオブジェクトをご参照ください{"MsgType": "TIMTextElem", // テキスト"MsgContent": {"Text": "red packet"}}],"CloudCustomData": "your cloud custom data"}
{"CallbackCommand": "State.StateChange","EventTime": 1629883332497,"Info": {"Action": "Login","To_Account": "testuser316","Reason": "Register"},"KickedDevice": [{"Platform": "Windows"},{"Platform": "Android"}]}
V2TIMMessageListGetOption option = new V2TIMMessageListGetOption();option.setGetType(V2TIMMessageListGetOption.V2TIM_GET_CLOUD_OLDER_MSG); // クラウドのより古いメッセージを取得option.setGetTimeBegin(1640966400); // 2022-01-01 00:00:00から開始option.setGetTimePeriod(1 * 24 * 60 * 60); // 1日全体のメッセージを取得option.setCount(Integer.MAX_VALUE); // 時間範囲内の全メッセージを返すoption.setGroupID(#you group id#); // グループチャットメッセージを取得V2TIMManager.getMessageManager().getHistoryMessageList(option, new V2TIMValueCallback<List<V2TIMMessage>>() {@Overridepublic void onSuccess(List<V2TIMMessage> v2TIMMessages) {Log.i("imsdk", "success");}@Overridepublic void onError(int code, String desc) {Log.i("imsdk", "failure, code:" + code + ", desc:" + desc);}});
// シングルチャットメッセージ履歴の取得// 初回の取得では、lastMsgをnilに設定します// 再度取得する際、lastMsgは返されたメッセージリストの最後の1通を使用することができます[V2TIMManager.sharedInstance getC2CHistoryMessageList:#your user id# count:20 lastMsg:nil succ:^(NSArray<V2TIMMessage *> *msgs) {// 次回取得するlastMsgを記録し、次回の取得に使用しますV2TIMMessage *lastMsg = msgs.lastObject;NSLog(@"success, %@", msgs);} fail:^(int code, NSString *desc) {NSLog(@"fail, %d, %@", code, desc);}];
// シングルチャットメッセージ履歴の取得// 初回の取得では、lastMsgIDをnullに設定します// 再度取得する際、lastMsgIDは返されたメッセージリストの最後の1通のidを使用することができますTencentImSDKPlugin.v2TIMManager.getMessageManager().getC2CHistoryMessageList(userID: "userId",count: 10,lastMsgID: null,);
// あるセッションを開いた際、最初に取得するメッセージリストlet promise = tim.getMessageList({conversationID: 'C2Ctest', count: 15});promise.then(function(imResponse) {const messageList = imResponse.data.messageList; // メッセージリスト。const nextReqMessageID = imResponse.data.nextReqMessageID; // 続けて取得する場合に使用します。ページごとに取得する場合はこのフィールドを渡す必要があります。const isCompleted = imResponse.data.isCompleted; // すべてのメッセージの取得が完了したかどうかを表します。});// その他のメッセージをドロップダウンして確認let promise = tim.getMessageList({conversationID: 'C2Ctest', nextReqMessageID, count: 15});promise.then(function(imResponse) {const messageList = imResponse.data.messageList; // メッセージリスト。const nextReqMessageID = imResponse.data.nextReqMessageID; // 続けて取得する場合に使用します。ページごとに取得する場合はこのフィールドを渡す必要があります。const isCompleted = imResponse.data.isCompleted; // すべてのメッセージの取得が完了したかどうかを表します。});
2TIMManager.getGroupManager().getGroupOnlineMemberCount("group_avchatroom", new V2TIMValueCallback<Integer>() {@Overridepublic void onSuccess(Integer integer) {// ライブストリーミンググループのオンライン数の取得に成功}@Overridepublic void onError(int code, String desc) {// ライブストリーミンググループのオンライン数の取得に失敗}});
[[V2TIMManager sharedInstance] getGroupOnlineMemberCount:@"group_avchatroom" succ:^(NSInteger count) {// ライブストリーミンググループのオンライン数の取得に成功} fail:^(int code, NSString *desc) {// ライブストリーミンググループのオンライン数の取得に失敗}];
groupManager.getGroupOnlineMemberCount(groupID: '');
// v2.8.0より、ライブストリーミンググループのオンライン数のクエリをサポートlet promise = tim.getGroupOnlineMemberCount('group1');promise.then(function(imResponse) {console.log(imResponse.data.memberCount);}).catch(function(imError) {console.warn('getGroupOnlineMemberCount error:', imError); // ライブストリーミンググループのオンライン数の取得に失敗する関連情報});
// グループメンバーuserBを1分間ミュートV2TIMManager.getGroupManager().muteGroupMember("groupA", "userB", 60, new V2TIMCallback() {@Overridepublic void onSuccess() {// グループメンバーのミュートに成功}@Overridepublic void onError(int code, String desc) {// グループメンバーのミュートに失敗}});// 全員ミュートV2TIMGroupInfo info = new V2TIMGroupInfo();info.setGroupID("groupA");info.setAllMuted(true);V2TIMManager.getGroupManager().setGroupInfo(info, new V2TIMCallback() {@Overridepublic void onSuccess() {// 全員ミュートに成功}@Overridepublic void onError(int code, String desc) {// 全員ミュートに失敗}});V2TIMManager.getInstance().addGroupListener(new V2TIMGroupListener() {@Overridepublic void onMemberInfoChanged(String groupID, List<V2TIMGroupMemberChangeInfo> v2TIMGroupMemberChangeInfoList) {// グループメンバーミュートをリッスンfor (V2TIMGroupMemberChangeInfo memberChangeInfo : v2TIMGroupMemberChangeInfoList) {// ミュートされたユーザーIDString userID = memberChangeInfo.getUserID();// ミュート時間long muteTime = memberChangeInfo.getMuteTime();}}@Overridepublic void onGroupInfoChanged(String groupID, List<V2TIMGroupChangeInfo> changeInfos) {// 全員ミュートをリッスンfor (V2TIMGroupChangeInfo groupChangeInfo : changeInfos) {if (groupChangeInfo.getType() == V2TIMGroupChangeInfo.V2TIM_GROUP_INFO_CHANGE_TYPE_SHUT_UP_ALL) {// 全員ミュートされるかどうかboolean isMuteAll = groupChangeInfo.getBoolValue();}}}});
// グループメンバーuser1を1分間ミュート[[V2TIMManager sharedInstance] muteGroupMember:@"groupA" member:@"user1" muteTime:60 succ:^{// グループメンバーのミュートに成功} fail:^(int code, NSString *desc) {// グループメンバーのミュートに失敗}];// 全員ミュートV2TIMGroupInfo *info = [[V2TIMGroupInfo alloc] init];info.groupID = @"groupA";info.allMuted = YES;[[V2TIMManager sharedInstance] muteGroupMember:@"groupA" member:@"user1" muteTime:60 succ:^{// 全員ミュートに成功} fail:^(int code, NSString *desc) {// 全員ミュートに失敗}];[[V2TIMManager sharedInstance] addGroupListener:self];- (void)onMemberInfoChanged:(NSString *)groupID changeInfoList:(NSArray <V2TIMGroupMemberChangeInfo *> *)changeInfoList {// グループメンバーミュートをリッスンfor (V2TIMGroupMemberChangeInfo *memberChangeInfo in changeInfoList) {// ミュートされたユーザーIDNSString *userID = memberChangeInfo.userID;// ミュート時間uint32_t muteTime = memberChangeInfo.muteTime;}}- (void)onGroupInfoChanged:(NSString *)groupID changeInfoList:(NSArray <V2TIMGroupChangeInfo *> *)changeInfoList {// 全員ミュートをリッスンfor (V2TIMGroupChangeInfo groupChangeInfo in changeInfoList) {if (groupChangeInfo.type == V2TIM_GROUP_INFO_CHANGE_TYPE_SHUT_UP_ALL) {// 全員ミュートされるかどうかBOOL isMuteAll = groupChangeInfo.boolValue;}}}
// グループメンバーuserBを10分間ミュートgroupManager.muteGroupMember(groupID: '',userID: 'userB',seconds: 10);// 全員ミュートgroupManager.setGroupInfo(info: V2TimGroupInfo(isAllMuted: true,groupID: '',groupType: 'Public'));TencentImSDKPlugin.v2TIMManager.addGroupListener(listener: V2TimGroupListener(onMemberInfoChanged: (groupID, v2TIMGroupMemberChangeInfoList) {//グループメンバー情報変更},onGroupInfoChanged: (groupID,info){// グループメッセージ変更}));
tim.setGroupMemberMuteTime(options);let promise = tim.setGroupMemberMuteTime({groupID: 'group1',userID: 'user1',muteTime: 600 // 10分間ミュート。ミュートを解除するには0を設定});promise.then(function(imResponse) {console.log(imResponse.data.group); // 変更後のグループデータconsole.log(imResponse.data.group); // 変更後のグループメンバーのデータ}).catch(function(imError) {console.warn('setGroupMemberMuteTime error:', imError); // ミュート失敗の関連情報});// トピック内のグループメンバーのミュート時間を設定let promise = tim.setGroupMemberMuteTime({groupID: 'topicID',userID: 'user1',muteTime: 600 // 10分間ミュート。ミュートを解除するには0を設定});promise.then(function(imResponse) {console.log(imResponse.data.group); // 変更後のグループデータconsole.log(imResponse.data.group); // 変更後のグループメンバーのデータ}).catch(function(imError) {console.warn('setGroupMemberMuteTime error:', imError); // ミュート失敗の関連情報});// v2.6.2からは、全員ミュートおよびミュート解除機能が利用できます。現在はグループ全員をミュートにすると、グループプロンプトメッセージの送信がサポートされません。let promise = tim.updateGroupProfile({groupID: 'group1',muteAllMembers: true, // trueは全員ミュート、falseは全員ミュートの解除を表します});promise.then(function(imResponse) {console.log(imResponse.data.group) // 変更後のグループの詳細データ}).catch(function(imError) {console.warn('updateGroupProfile error:', imError); // グループ情報変更失敗の関連情報});
List<String> userIDList = new ArrayList<>();userIDList.add("userB");V2TIMManager.getGroupManager().kickGroupMember("groupA", userIDList, "", new V2TIMValueCallback<List<V2TIMGroupMemberOperationResult>>() {@Overridepublic void onSuccess(List<V2TIMGroupMemberOperationResult> v2TIMGroupMemberOperationResults) {// 強制退室に成功}@Overridepublic void onError(int code, String desc) {// 強制退室に失敗}});V2TIMManager.getInstance().addGroupListener(new V2TIMGroupListener() {@Overridepublic void onMemberKicked(String groupID, V2TIMGroupMemberInfo opUser,List<V2TIMGroupMemberInfo> memberList) {// グループメンバー強制退室の通知}});
[[V2TIMManager sharedInstance] kickGroupMember:@"groupA" memberList:@[@"user1"] reason:@"" succ:^(NSArray<V2TIMGroupMemberOperationResult *> *resultList) {// 強制退室に成功} fail:^(int code, NSString *desc) {// 強制退室に失敗}];[[V2TIMManager sharedInstance] addGroupListener:self];- (void)onMemberKicked:(NSString *)groupID opUser:(V2TIMGroupMemberInfo *)opUser memberList:(NSArray<V2TIMGroupMemberInfo *>*)memberList {// グループメンバー強制退室の通知}
groupManager.kickGroupMember(groupID: '',memberList: []);
tim.deleteGroupMember(options);
{"CallbackCommand": "Group.CallbackBeforeSendMsg", // コールバックコマンド"GroupId": "@TGS#2J4SZEAEL", // グループID"Type": "Public", // グループタイプ"From_Account": "jared", // 送信者"Operator_Account":"admin", // リクエストの送信者"Random": 123456, // 乱数"OnlineOnlyFlag": 1, //オンラインメッセージは1、そうでない場合は0となります。ライブストリーミンググループの場合はこの属性を無視し、デフォルト値の0とします。"MsgBody": [ // メッセージボディです。TIMMessageのメッセージオブジェクトをご参照ください{"MsgType": "TIMTextElem", // テキスト"MsgContent": {"Text": "red packet"}}],"CloudCustomData": "your cloud custom data"}
{"ActionStatus": "OK","ErrorInfo": "","ErrorCode": 0 // ErrorCodeごとに意味が異なります}
ErrorCode | 意味 |
0 | 発言を許可し、メッセージは正常に送信されます |
1 | 発言を拒否し、クライアントは10016を返します |
2 | サイレントで破棄し、クライアントは正常を返します |
getGroupMemberList
インターフェースによってグループメンバーリストを取得することができますが、AVChatRoomでは人数が多いため、全量のメンバーリストを取得する機能は提供していません。機能はフラッグシップ版か非フラッグシップ版かによって異なります。getGroupMemberList
を呼び出して、直近でグループに参加した30名のグループメンバーを取得することができます。getGroupMemberList
を呼び出して、直近でグループに参加した1000名のグループメンバーを取得することができます。この機能はIMコンソールで有効化する必要があり、有効化しなければデフォルトで非フラッグシップ版と同様に、直近でグループに参加した30名のグループメンバーのみを取得します。getGroupMemberList
とグループ監視中のonGroupMemberEnterおよびonGroupMemberQuitコールバックによって、現在オンラインのグループメンバーリストをクライアントで保守することもできます。ただし、この方法では、ユーザーがライブルームから退出して入り直した場合も、最新の30名のグループメンバーしか取得できません。// filterパラメータを指定することで、グループ所有者のデータのみを取得しますint role = V2TIMGroupMemberFullInfo.V2TIM_GROUP_MEMBER_FILTER_OWNER;V2TIMManager.getGroupManager().getGroupMemberList("testGroup", role, 0,new V2TIMValueCallback<V2TIMGroupMemberInfoResult>() {@Overridepublic void onError(int code, String desc) {// 取得に失敗しました}@Overridepublic void onSuccess(V2TIMGroupMemberInfoResult v2TIMGroupMemberInfoResult) {// 取得に成功しました}});
[[V2TIMManager sharedInstance] getGroupMemberList:@"groupA" filter:V2TIM_GROUP_MEMBER_FILTER_OWNER nextSeq:0 succ:^(uint64_t nextSeq, NSArray<V2TIMGroupMemberFullInfo *> *memberList) {// 取得に成功しました} fail:^(int code, NSString *desc) {// 取得に失敗しました}];
// filterパラメータを指定することで、グループ所有者のデータのみを取得します。ALLを指定することで、すべてのグループメンバーを取得できますgroupManager.getGroupMemberList(count: 10,filter: GroupMemberFilterTypeEnum.V2TIM_GROUP_MEMBER_FILTER_ADMIN,nextSeq: '0',offset: 0,groupID: "",);
tim.getGroupMemberList(options);
Message.nick
と Message.avatar
フィールドがどちらも空である場合、インターフェース上でニックネームとプロフィール画像を正常に表示するにはどうすればよいですか?
この記事はお役に立ちましたか?