RongCallKit.java 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. package io.rong.callkit;
  2. import android.Manifest;
  3. import android.app.Activity;
  4. import android.content.Context;
  5. import android.content.Intent;
  6. import android.widget.Toast;
  7. import java.util.ArrayList;
  8. import io.rong.calllib.RongCallClient;
  9. import io.rong.calllib.RongCallCommon;
  10. import io.rong.calllib.RongCallSession;
  11. import io.rong.imkit.utilities.PermissionCheckUtil;
  12. import io.rong.imlib.RongIMClient;
  13. import io.rong.imlib.model.Conversation;
  14. public class RongCallKit {
  15. public enum CallMediaType {
  16. CALL_MEDIA_TYPE_AUDIO, CALL_MEDIA_TYPE_VIDEO
  17. }
  18. public interface ICallUsersProvider {
  19. void onGotUserList(ArrayList<String> userIds);
  20. }
  21. private static GroupMembersProvider mGroupMembersProvider;
  22. private static RongCallCustomerHandlerListener customerHandlerListener;
  23. /**
  24. * 发起单人通话。
  25. *
  26. * @param context 上下文
  27. * @param targetId 会话 id
  28. * @param mediaType 会话媒体类型
  29. */
  30. public static void startSingleCall(Context context, String targetId, CallMediaType mediaType) {
  31. if (checkEnvironment(context, mediaType)) {
  32. String action;
  33. if (mediaType.equals(CallMediaType.CALL_MEDIA_TYPE_AUDIO)) {
  34. action = RongVoIPIntent.RONG_INTENT_ACTION_VOIP_SINGLEAUDIO;
  35. } else {
  36. action = RongVoIPIntent.RONG_INTENT_ACTION_VOIP_SINGLEVIDEO;
  37. }
  38. Intent intent = new Intent(action);
  39. intent.putExtra("conversationType", Conversation.ConversationType.PRIVATE.getName().toLowerCase());
  40. intent.putExtra("targetId", targetId);
  41. intent.putExtra("callAction", RongCallAction.ACTION_OUTGOING_CALL.getName());
  42. intent.setPackage(context.getPackageName());
  43. context.startActivity(intent);
  44. }
  45. }
  46. /**
  47. * 发起多人通话
  48. *
  49. * @param context 上下文
  50. * @param conversationType 会话类型
  51. * @param targetId 会话 id
  52. * @param mediaType 会话媒体类型
  53. * @param userIds 参与者 id 列表
  54. */
  55. public static void startMultiCall(Context context, Conversation.ConversationType conversationType, String targetId, CallMediaType mediaType, ArrayList<String> userIds) {
  56. if (checkEnvironment(context, mediaType)) {
  57. String action;
  58. if (mediaType.equals(CallMediaType.CALL_MEDIA_TYPE_AUDIO)) {
  59. action = RongVoIPIntent.RONG_INTENT_ACTION_VOIP_MULTIAUDIO;
  60. } else {
  61. action = RongVoIPIntent.RONG_INTENT_ACTION_VOIP_MULTIVIDEO;
  62. }
  63. Intent intent = new Intent(action);
  64. userIds.add(RongIMClient.getInstance().getCurrentUserId());
  65. intent.putExtra("conversationType", conversationType.getName().toLowerCase());
  66. intent.putExtra("targetId", targetId);
  67. intent.putExtra("callAction", RongCallAction.ACTION_OUTGOING_CALL.getName());
  68. intent.setPackage(context.getPackageName());
  69. intent.putStringArrayListExtra("invitedUsers", userIds);
  70. context.startActivity(intent);
  71. }
  72. }
  73. /**
  74. * 开始多人通话。
  75. * 返回当前会话用户列表提供者对象,用户拿到该对象后,异步从服务器取出当前会话用户列表后,
  76. * 调用提供者中的 onGotUserList 方法,填充 ArrayList<String> userIds 后,就会自动发起多人通话。
  77. *
  78. * @param context 上下文
  79. * @param conversationType 会话类型
  80. * @param targetId 会话 id
  81. * @param mediaType 通话的媒体类型:CALL_MEDIA_TYPE_AUDIO, CALL_MEDIA_TYPE_VIDEO
  82. * @return 返回当前会话用户列表提供者对象
  83. */
  84. public static ICallUsersProvider startMultiCall(final Context context, final Conversation.ConversationType conversationType, final String targetId, final CallMediaType mediaType) {
  85. return new ICallUsersProvider() {
  86. @Override
  87. public void onGotUserList(ArrayList<String> userIds) {
  88. String action;
  89. if (mediaType.equals(CallMediaType.CALL_MEDIA_TYPE_AUDIO)) {
  90. action = RongVoIPIntent.RONG_INTENT_ACTION_VOIP_MULTIAUDIO;
  91. } else {
  92. action = RongVoIPIntent.RONG_INTENT_ACTION_VOIP_MULTIVIDEO;
  93. }
  94. Intent intent = new Intent(action);
  95. userIds.add(RongIMClient.getInstance().getCurrentUserId());
  96. intent.putExtra("conversationType", conversationType.getName().toLowerCase());
  97. intent.putExtra("targetId", targetId);
  98. intent.putExtra("callAction", RongCallAction.ACTION_OUTGOING_CALL.getName());
  99. intent.setPackage(context.getPackageName());
  100. intent.putStringArrayListExtra("invitedUsers", userIds);
  101. context.startActivity(intent);
  102. }
  103. };
  104. }
  105. /**
  106. * 发起的多人通话,不依赖群、讨论组等
  107. * @param context
  108. * @param userIds 邀请的成员
  109. * @param oberverIds 邀请的以观察者身份加入房间的成员
  110. * @param mediaType
  111. */
  112. public static void startMultiCall(final Context context, ArrayList<String> userIds, ArrayList<String> oberverIds, final CallMediaType mediaType) {
  113. String action;
  114. if (mediaType.equals(CallMediaType.CALL_MEDIA_TYPE_AUDIO)) {
  115. action = RongVoIPIntent.RONG_INTENT_ACTION_VOIP_MULTIAUDIO;
  116. } else {
  117. action = RongVoIPIntent.RONG_INTENT_ACTION_VOIP_MULTIVIDEO;
  118. }
  119. Intent intent = new Intent(action);
  120. userIds.add(RongIMClient.getInstance().getCurrentUserId());
  121. intent.putExtra("conversationType", Conversation.ConversationType.NONE.getName().toLowerCase());
  122. intent.putExtra("callAction", RongCallAction.ACTION_OUTGOING_CALL.getName());
  123. intent.putStringArrayListExtra("invitedUsers", userIds);
  124. intent.putStringArrayListExtra("observerUsers", oberverIds);
  125. intent.setPackage(context.getPackageName());
  126. context.startActivity(intent);
  127. }
  128. /**
  129. * 发起的多人通话,不依赖群、讨论组等
  130. * <p>
  131. * <a href="http://support.rongcloud.cn/kb/Njcy">如何实现不基于于群组的voip</a>
  132. *
  133. * @param context
  134. * @param mediaType
  135. * @return
  136. */
  137. public static void startMultiCall(final Context context, ArrayList<String> userIds, final CallMediaType mediaType) {
  138. String action;
  139. if (mediaType.equals(CallMediaType.CALL_MEDIA_TYPE_AUDIO)) {
  140. action = RongVoIPIntent.RONG_INTENT_ACTION_VOIP_MULTIAUDIO;
  141. } else {
  142. action = RongVoIPIntent.RONG_INTENT_ACTION_VOIP_MULTIVIDEO;
  143. }
  144. Intent intent = new Intent(action);
  145. userIds.add(RongIMClient.getInstance().getCurrentUserId());
  146. intent.putExtra("conversationType", Conversation.ConversationType.NONE.getName().toLowerCase());
  147. intent.putExtra("callAction", RongCallAction.ACTION_OUTGOING_CALL.getName());
  148. intent.putStringArrayListExtra("invitedUsers", userIds);
  149. intent.setPackage(context.getPackageName());
  150. context.startActivity(intent);
  151. }
  152. /**
  153. * 检查应用音视频授权信息
  154. * 检查网络连接状态
  155. * 检查是否在通话中
  156. *
  157. * @param context 启动的 activity
  158. * @param mediaType 启动音视频的媒体类型
  159. * @return 是否允许启动通话界面
  160. */
  161. private static boolean checkEnvironment(Context context, CallMediaType mediaType) {
  162. if (context instanceof Activity) {
  163. String[] permissions;
  164. if (mediaType.equals(CallMediaType.CALL_MEDIA_TYPE_AUDIO)) {
  165. permissions = new String[]{Manifest.permission.RECORD_AUDIO};
  166. } else {
  167. permissions = new String[]{Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO};
  168. }
  169. if (!PermissionCheckUtil.requestPermissions((Activity) context, permissions)) {
  170. return false;
  171. }
  172. }
  173. if (isInVoipCall(context)) {
  174. return false;
  175. }
  176. if (!RongIMClient.getInstance().getCurrentConnectionStatus().equals(RongIMClient.ConnectionStatusListener.ConnectionStatus.CONNECTED)) {
  177. Toast.makeText(context, context.getResources().getString(R.string.rc_voip_call_network_error), Toast.LENGTH_SHORT).show();
  178. return false;
  179. }
  180. return true;
  181. }
  182. /**
  183. * 是否在VOIP通话中
  184. *
  185. * @param context
  186. * @return 是否在VOIP通话中
  187. */
  188. public static boolean isInVoipCall(Context context) {
  189. RongCallSession callSession = RongCallClient.getInstance().getCallSession();
  190. if (callSession != null && callSession.getActiveTime() > 0) {
  191. Toast.makeText(context,
  192. callSession.getMediaType() == RongCallCommon.CallMediaType.AUDIO ?
  193. context.getResources().getString(R.string.rc_voip_call_audio_start_fail) :
  194. context.getResources().getString(R.string.rc_voip_call_video_start_fail),
  195. Toast.LENGTH_SHORT)
  196. .show();
  197. return true;
  198. }
  199. return false;
  200. }
  201. /**
  202. * 群组成员提供者。
  203. * CallKit 本身不保存群组成员,如果在聊天中需要使用群组成员,CallKit 将调用此 Provider 获取群组成员。
  204. */
  205. public interface GroupMembersProvider {
  206. /**
  207. * 获取群组成员列表,用户根据groupId返回对应的群组成员列表。
  208. *
  209. * @param groupId 群组id
  210. * @param result getMemberList可以同步返回,也可以异步返回。
  211. * 同步返回的情况下,直接返回成员列表。
  212. * 异步返回的情况下,需要在异步返回的时候调用{@link OnGroupMembersResult#onGotMemberList(ArrayList)}
  213. * 来通知CallKit刷新列表。
  214. * @return 同步返回的时候返回列表,异步返回直接返回null。
  215. */
  216. ArrayList<String> getMemberList(String groupId, OnGroupMembersResult result);
  217. }
  218. /**
  219. * 群组成员提供者的异步回调接口。
  220. */
  221. public interface OnGroupMembersResult {
  222. /**
  223. * 群组成员提供者的异步回调接口。
  224. *
  225. * @param members 成员列表。
  226. */
  227. void onGotMemberList(ArrayList<String> members);
  228. }
  229. /**
  230. * <p>设置群组成员的提供者。</p>
  231. * <p>设置后,当 {@link CallSelectMemberActivity} 界面展示群组成员时,会回调 {@link GroupMembersProvider#getMemberList(String, OnGroupMembersResult)},
  232. * 使用者只需要根据对应的 groupId 提供对应的群组成员。
  233. * 如果需要异步从服务器获取群组成员,使用者可以在此方法中发起异步请求,然后返回 null 信息。
  234. * 在异步请求结果返回后,根据返回的结果调用 {@link OnGroupMembersResult#onGotMemberList(ArrayList)} 刷新信息。</p>
  235. *
  236. * @param groupMembersProvider 群组成员提供者。
  237. */
  238. public static void setGroupMemberProvider(GroupMembersProvider groupMembersProvider) {
  239. mGroupMembersProvider = groupMembersProvider;
  240. }
  241. /**
  242. * 获取群组成员提供者。
  243. *
  244. * @return 群组成员提供者。
  245. */
  246. public static GroupMembersProvider getGroupMemberProvider() {
  247. return mGroupMembersProvider;
  248. }
  249. /**
  250. * <p>设置通话时用户自定义操作监听。</p>
  251. * <p>CallKit中的Activity是通过action隐式启动,如果用户想继承现有的Activity自定义操作,子类Activity在
  252. * AndroidManifest.xml声明后启动该Activity时会弹出提示框让用户选择,这个问题解决方式开发者可以直接把
  253. * callKit/AndroidManifest.xml中对应的Activity声明去掉,此Listener提供了另一种实现方案,
  254. * RongCallCustomerHandlerListener中并没有定义很多方法,开发者如果需要,可以新增自己的方法</p>
  255. */
  256. public static void setCustomerHandlerListener(RongCallCustomerHandlerListener callCustomerHandlerListener) {
  257. customerHandlerListener = callCustomerHandlerListener;
  258. }
  259. /**
  260. * 通话过程中用户自定义操作。
  261. */
  262. public static RongCallCustomerHandlerListener getCustomerHandlerListener() {
  263. return customerHandlerListener;
  264. }
  265. }