userIds = new ArrayList<>();
+ userIds.add(targetId);
+ RongCallClient.getInstance().startCall(Conversation.ConversationType.PRIVATE, targetId, userIds, null, RongCallCommon.CallMediaType.VIDEO, null);
+ }
+
+ public void acceptCall(String callId) {
+ RongCallClient.getInstance().setVoIPCallListener(new CallStatusListener(new OnCallStatusListener() {
+ @Override
+ public void onCallWait(SurfaceView localVideo) {
+ for (OnCallStatusListener listener : listeners) {
+ listener.onCallWait(localVideo);
+ }
+ }
+
+ @Override
+ public void onCallStart(String userId, SurfaceView remoteVideo) {
+ for (OnCallStatusListener listener : listeners) {
+ listener.onCallStart(userId, remoteVideo);
+ }
+ }
+
+ @Override
+ public void onCallEnd() {
+ for (OnCallStatusListener listener : listeners) {
+ listener.onCallEnd();
+ }
+ }
+
+ @Override
+ public void onStartFirstFrame() {
+ for (OnCallStatusListener listener : listeners) {
+ listener.onStartFirstFrame();
+ }
+ }
+ }));
+ RongCallClient.getInstance().acceptCall(callId);
+ }
+
+ public void endCall() {
+ if (RongCallClient.getInstance() != null && RongCallClient.getInstance().getCallSession() != null) {
+ RongCallClient.getInstance().hangUpCall(RongCallClient.getInstance().getCallSession().getCallId());
+ }
+ }
+
+ public boolean isCalling() {
+ return RongCallClient.getInstance() != null && RongCallClient.getInstance().getCallSession() != null;
+ }
private static class CallMeListener implements IRongReceivedCallListener {
@Override
public void onReceivedCall(RongCallSession callSession) {
-
+ Bundle bundle = new Bundle();
+ bundle.putString("model", VIDEO_RECEIVED_CALL);
+ bundle.putString("targetId", callSession.getTargetId());
+ bundle.putString("callId", callSession.getCallId());
+ bundle.putString("sessionId", callSession.getSessionId());
+ RouteManager.forwardActivity(RouteManager.ACTIVITY_CALL_VIDEO, bundle);
}
@Override
public void onCheckPermission(RongCallSession callSession) {
- PermissionUtils.permission(Manifest.permission.CAMERA,Manifest.permission.RECORD_AUDIO).callback(new PermissionUtils.SimpleCallback() {
+ ToastUtil.show("权限申请");
+ PermissionUtils.permission(Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO).callback(new PermissionUtils.SimpleCallback() {
@Override
public void onGranted() {
RongCallClient.getInstance().onPermissionGranted();
@@ -64,21 +187,28 @@ public class CallClientManager {
public void onDenied() {
RongCallClient.getInstance().onPermissionDenied();
}
- });
+ }).request();
}
}
- private static class CallStatusListener implements IRongCallListener {
+ private class CallStatusListener implements IRongCallListener {
OnCallStatusListener statusListener;
+ private long time = 0;
public CallStatusListener(OnCallStatusListener statusListener) {
this.statusListener = statusListener;
}
+ public long getTime(long activeTime) {
+ long tmpTime = activeTime == 0 ? 0 : (System.currentTimeMillis() - activeTime) / 1000;
+ time = tmpTime == 0 ? time : tmpTime;
+ return time;
+ }
+
@Override
public void onCallIncoming(RongCallSession callSession, SurfaceView localVideo) {
-
+ System.out.println("CallStatusListener.onCallIncoming");
}
/**
@@ -90,7 +220,10 @@ public class CallClientManager {
*/
@Override
public void onCallOutgoing(RongCallSession callSession, SurfaceView localVideo) {
+ localVideo.setZOrderOnTop(true);
+ localVideo.setZOrderMediaOverlay(true);
statusListener.onCallWait(localVideo);
+ System.out.println("CallStatusListener.onCallOutgoing");
}
/**
@@ -102,7 +235,9 @@ public class CallClientManager {
*/
@Override
public void onCallConnected(RongCallSession callSession, SurfaceView localVideo) {
-
+ localVideo.setZOrderOnTop(true);
+ localVideo.setZOrderMediaOverlay(true);
+ statusListener.onCallWait(localVideo);
}
/**
@@ -114,17 +249,72 @@ public class CallClientManager {
*/
@Override
public void onCallDisconnected(RongCallSession callSession, RongCallCommon.CallDisconnectedReason reason) {
+ System.out.println("CallStatusListener.onCallDisconnected");
+
+ String senderId;
+ String extra = "";
+
+ if (callSession == null) {
+ RLog.e("CallStatusListener", "onCallDisconnected. callSession is null!");
+ statusListener.onCallEnd();
+ return;
+ }
+ senderId = callSession.getInviterUserId();
+ long time = getTime(callSession.getActiveTime());
+ if (time > 0) {
+ if (time >= 3600) {
+ extra =
+ String.format(
+ Locale.ROOT,
+ "%d:%02d:%02d",
+ time / 3600,
+ (time % 3600) / 60,
+ (time % 60));
+ } else {
+ extra = String.format(Locale.ROOT, "%02d:%02d", (time % 3600) / 60, (time % 60));
+ }
+ }
+ if (!TextUtils.isEmpty(senderId)) {
+ CallSTerminateMessage message = new CallSTerminateMessage();
+ message.setReason(reason);
+ message.setMediaType(callSession.getMediaType());
+ message.setExtra(extra);
+ long serverTime =
+ System.currentTimeMillis() - RongIMClient.getInstance().getDeltaTime();
+ if (senderId.equals(callSession.getSelfUserId())) {
+ message.setDirection("MO");
+ IMCenter.getInstance()
+ .insertOutgoingMessage(
+ Conversation.ConversationType.PRIVATE,
+ callSession.getTargetId(),
+ io.rong.imlib.model.Message.SentStatus.SENT,
+ message,
+ serverTime,
+ null);
+ } else {
+ message.setDirection("MT");
+ IMCenter.getInstance()
+ .insertIncomingMessage(
+ Conversation.ConversationType.PRIVATE,
+ callSession.getTargetId(),
+ senderId,
+ CallKitUtils.getReceivedStatus(reason),
+ message,
+ serverTime,
+ null);
+ }
+ }
statusListener.onCallEnd();
}
@Override
public void onRemoteUserRinging(String userId) {
-
+ System.out.println("CallStatusListener.onRemoteUserRinging");
}
@Override
public void onRemoteUserAccept(String userId, RongCallCommon.CallMediaType mediaType) {
-
+ System.out.println("CallStatusListener.onRemoteUserAccept");
}
/**
@@ -138,21 +328,24 @@ public class CallClientManager {
* 如果对端调用{@link RongCallClient#startCall(int, boolean, Conversation.ConversationType, String, List, List, RongCallCommon.CallMediaType, String, StartCameraCallback)} 或
* {@link RongCallClient#acceptCall(String, int, boolean, StartCameraCallback)}开始的音视频通话,则可以使用如下设置改变对端视频流的镜像显示:
*
- * public void onRemoteUserJoined(String userId, RongCallCommon.CallMediaType mediaType, int userType, SurfaceView remoteVideo) {
- * if (null != remoteVideo) {
- * ((RongRTCVideoView) remoteVideo).setMirror( boolean);//观看对方视频流是否镜像处理
- * }
- * }
- *
+ * public void onRemoteUserJoined(String userId, RongCallCommon.CallMediaType mediaType, int userType, SurfaceView remoteVideo) {
+ * if (null != remoteVideo) {
+ * ((RongRTCVideoView) remoteVideo).setMirror( boolean);//观看对方视频流是否镜像处理
+ * }
+ * }
+ *
*/
@Override
public void onRemoteUserJoined(String userId, RongCallCommon.CallMediaType mediaType, int userType, SurfaceView remoteVideo) {
- statusListener.onCallStart(userId,remoteVideo);
+ remoteVideo.setZOrderOnTop(false);
+ remoteVideo.setZOrderMediaOverlay(false);
+ statusListener.onCallStart(userId, remoteVideo);
+ System.out.println("CallStatusListener.onRemoteUserJoined");
}
@Override
public void onRemoteUserInvited(String userId, RongCallCommon.CallMediaType mediaType) {
-
+ System.out.println("CallStatusListener.onRemoteUserInvited");
}
/**
@@ -164,17 +357,23 @@ public class CallClientManager {
*/
@Override
public void onRemoteUserLeft(String userId, RongCallCommon.CallDisconnectedReason reason) {
-
+ System.out.println("CallStatusListener.onRemoteUserLeft");
+ if (statusListener != null) {
+ statusListener.onCallEnd();
+ }
}
@Override
public void onMediaTypeChanged(String userId, RongCallCommon.CallMediaType mediaType, SurfaceView video) {
-
+ System.out.println("CallStatusListener.onMediaTypeChanged");
}
@Override
public void onError(RongCallCommon.CallErrorCode errorCode) {
-
+ System.out.println("CallStatusListener.onError");
+ if (statusListener != null) {
+ statusListener.onCallEnd();
+ }
}
@Override
@@ -199,7 +398,9 @@ public class CallClientManager {
@Override
public void onFirstRemoteVideoFrame(String userId, int height, int width) {
-
+ if (statusListener != null) {
+ statusListener.onStartFirstFrame();
+ }
}
@Override
diff --git a/OneToOne/src/main/java/com/shayu/onetoone/provider/OTOCallEndMessageItemProvider.java b/OneToOne/src/main/java/com/shayu/onetoone/provider/OTOCallEndMessageItemProvider.java
new file mode 100644
index 000000000..733a97bdb
--- /dev/null
+++ b/OneToOne/src/main/java/com/shayu/onetoone/provider/OTOCallEndMessageItemProvider.java
@@ -0,0 +1,255 @@
+package com.shayu.onetoone.provider;
+
+
+import static io.rong.calllib.RongCallCommon.CallDisconnectedReason.HANGUP;
+import static io.rong.calllib.RongCallCommon.CallDisconnectedReason.OTHER_DEVICE_HAD_ACCEPTED;
+
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.drawable.Drawable;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.shayu.onetoone.R;
+import com.yunbao.common.utils.ToastUtil;
+
+import io.rong.callkit.RongCallAction;
+import io.rong.callkit.util.CallKitUtils;
+import io.rong.calllib.RongCallClient;
+import io.rong.calllib.RongCallCommon;
+import io.rong.calllib.RongCallSession;
+import io.rong.calllib.message.CallSTerminateMessage;
+import io.rong.imkit.conversation.messgelist.provider.BaseMessageItemProvider;
+import io.rong.imkit.model.UiMessage;
+import io.rong.imkit.widget.adapter.IViewProviderListener;
+import io.rong.imkit.widget.adapter.ViewHolder;
+import io.rong.imlib.model.Message;
+import io.rong.imlib.model.MessageContent;
+import java.util.List;
+import java.util.Locale;
+
+public class OTOCallEndMessageItemProvider extends BaseMessageItemProvider {
+ @Override
+ protected io.rong.imkit.widget.adapter.ViewHolder onCreateMessageContentViewHolder(
+ ViewGroup parent, int viewType) {
+ View textView =
+ LayoutInflater.from(parent.getContext())
+ .inflate(R.layout.rc_text_message_item, parent, false);
+ return new ViewHolder(parent.getContext(), textView);
+ }
+
+ @Override
+ protected void bindMessageContentViewHolder(
+ ViewHolder holder,
+ ViewHolder parentHolder,
+ CallSTerminateMessage callSTerminateMessage,
+ UiMessage uiMessage,
+ int position,
+ List list,
+ IViewProviderListener listener) {
+ Message message = uiMessage.getMessage();
+ final TextView view = holder.getView(io.rong.imkit.R.id.rc_text);
+ if (message.getMessageDirection() == Message.MessageDirection.SEND) {
+ view.setBackgroundResource(R.drawable.rc_ic_bubble_right);
+ } else {
+ view.setBackgroundResource(R.drawable.rc_ic_bubble_left);
+ }
+
+ RongCallCommon.CallMediaType mediaType = callSTerminateMessage.getMediaType();
+ String direction = callSTerminateMessage.getDirection();
+ Drawable drawable = null;
+
+ String msgContent = "";
+ switch (callSTerminateMessage.getReason()) {
+ case CANCEL:
+ msgContent = view.getResources().getString(R.string.rc_voip_mo_cancel);
+ break;
+ case REJECT:
+ msgContent = view.getResources().getString(R.string.rc_voip_mo_reject);
+ break;
+ case NO_RESPONSE:
+ case BUSY_LINE:
+ msgContent = view.getResources().getString(R.string.rc_voip_mo_no_response);
+ break;
+ case REMOTE_BUSY_LINE:
+ msgContent = view.getResources().getString(R.string.rc_voip_mt_busy);
+ break;
+ case REMOTE_CANCEL:
+ msgContent = view.getResources().getString(R.string.rc_voip_mt_cancel);
+ break;
+ case REMOTE_REJECT:
+ msgContent = view.getResources().getString(R.string.rc_voip_mt_reject);
+ break;
+ case REMOTE_NO_RESPONSE:
+ msgContent = view.getResources().getString(R.string.rc_voip_mt_no_response);
+ break;
+ case NETWORK_ERROR:
+ case REMOTE_NETWORK_ERROR:
+ case INIT_VIDEO_ERROR:
+ msgContent = view.getResources().getString(R.string.rc_voip_call_interrupt);
+ break;
+ case OTHER_DEVICE_HAD_ACCEPTED:
+ msgContent = view.getResources().getString(R.string.rc_voip_call_other);
+ break;
+ case SERVICE_NOT_OPENED:
+ case REMOTE_ENGINE_UNSUPPORTED:
+ msgContent = view.getResources().getString(R.string.rc_voip_engine_notfound);
+ break;
+ case REJECTED_BY_BLACKLIST:
+ msgContent =
+ view.getResources().getString(R.string.rc_voip_mo_rejected_by_blocklist);
+ break;
+ default:
+ String mo_reject = view.getResources().getString(R.string.rc_voip_mo_reject);
+ String mt_reject = view.getResources().getString(R.string.rc_voip_mt_reject);
+ String extra = callSTerminateMessage.getExtra();
+ String timeRegex = "([0-9]?[0-9]:)?([0-5][0-9]:)?([0-5][0-9])$";
+ if (!TextUtils.isEmpty(extra)) {
+ boolean val = extra.matches(timeRegex);
+ if (val) {
+ msgContent =
+ view.getResources().getString(R.string.rc_voip_call_time_length);
+ msgContent += extra;
+ } else {
+ msgContent =
+ view.getResources().getString(R.string.rc_voip_call_time_length);
+ }
+ } else {
+ msgContent =
+ callSTerminateMessage.getReason() == HANGUP ? mo_reject : mt_reject;
+ }
+ break;
+ }
+
+ view.setText(msgContent);
+ view.setCompoundDrawablePadding(15);
+
+ if (mediaType.equals(RongCallCommon.CallMediaType.VIDEO)) {
+ if (direction != null && direction.equals("MO")) {
+ drawable = view.getResources().getDrawable(R.drawable.rc_voip_video_right);
+ drawable.setBounds(
+ 0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
+ view.setCompoundDrawablesRelative(null, null, drawable, null);
+ view.setTextColor(view.getResources().getColor(R.color.rc_voip_color_right));
+ } else {
+ drawable = view.getResources().getDrawable(R.drawable.rc_voip_video_left);
+ drawable.setBounds(
+ 0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
+ view.setCompoundDrawablesRelative(drawable, null, null, null);
+ view.setTextColor(view.getResources().getColor(R.color.rc_voip_color_left));
+ }
+ } else {
+ if (direction != null && direction.equals("MO")) {
+ if (callSTerminateMessage.getReason().equals(HANGUP)
+ || callSTerminateMessage
+ .getReason()
+ .equals(RongCallCommon.CallDisconnectedReason.REMOTE_HANGUP)) {
+ drawable =
+ view.getResources()
+ .getDrawable(R.drawable.rc_voip_audio_right_connected);
+ } else {
+ drawable =
+ view.getResources().getDrawable(R.drawable.rc_voip_audio_right_cancel);
+ }
+ drawable.setBounds(
+ 0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
+ view.setCompoundDrawablesRelative(null, null, drawable, null);
+ view.setTextColor(view.getResources().getColor(R.color.rc_voip_color_right));
+ } else {
+ if (callSTerminateMessage.getReason().equals(HANGUP)
+ || callSTerminateMessage
+ .getReason()
+ .equals(RongCallCommon.CallDisconnectedReason.REMOTE_HANGUP)) {
+ drawable =
+ view.getResources()
+ .getDrawable(R.drawable.rc_voip_audio_left_connected);
+ } else {
+ drawable =
+ view.getResources().getDrawable(R.drawable.rc_voip_audio_left_cancel);
+ }
+ drawable.setBounds(
+ 0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
+ view.setCompoundDrawablesRelative(drawable, null, null, null);
+ view.setTextColor(view.getResources().getColor(R.color.rc_voip_color_left));
+ }
+ }
+ }
+
+ @Override
+ protected boolean onItemClick(
+ ViewHolder holder,
+ CallSTerminateMessage callSTerminateMessage,
+ UiMessage uiMessage,
+ int position,
+ List list,
+ IViewProviderListener listener) {
+ if (callSTerminateMessage.getReason() == OTHER_DEVICE_HAD_ACCEPTED) {
+ return true;
+ }
+ ToastUtil.show("点了");
+ Context context = holder.getContext();
+ RongCallSession profile = RongCallClient.getInstance().getCallSession();
+ if (profile != null && profile.getActiveTime() > 0) {
+ if (profile.getMediaType() == RongCallCommon.CallMediaType.AUDIO) {
+ Toast.makeText(
+ context,
+ context.getString(R.string.rc_voip_call_audio_start_fail),
+ Toast.LENGTH_SHORT)
+ .show();
+ } else {
+ Toast.makeText(
+ context,
+ context.getString(R.string.rc_voip_call_video_start_fail),
+ Toast.LENGTH_SHORT)
+ .show();
+ }
+ return true;
+ }
+ if (!CallKitUtils.isNetworkAvailable(context)) {
+ Toast.makeText(
+ context,
+ context.getString(R.string.rc_voip_call_network_error),
+ Toast.LENGTH_SHORT)
+ .show();
+ return true;
+ }
+ RongCallCommon.CallMediaType mediaType = callSTerminateMessage.getMediaType();
+ String action = null;
+ if (mediaType.equals(RongCallCommon.CallMediaType.VIDEO)) {
+ action = "io.rong.intent.action.voip.SINGLEVIDEO";
+ } else {
+ action = "io.rong.intent.action.voip.SINGLEAUDIO";
+ }
+ Intent intent = new Intent(action);
+ intent.setPackage(context.getPackageName());
+ intent.putExtra(
+ "conversationType",
+ uiMessage.getMessage().getConversationType().getName().toLowerCase(Locale.US));
+ intent.putExtra("targetId", uiMessage.getMessage().getTargetId());
+ intent.putExtra("callAction", RongCallAction.ACTION_OUTGOING_CALL.getName());
+ context.startActivity(intent);
+ return true;
+ }
+
+ @Override
+ protected boolean isMessageViewType(MessageContent messageContent) {
+ return messageContent instanceof CallSTerminateMessage;
+ }
+
+ @Override
+ public Spannable getSummarySpannable(
+ Context context, CallSTerminateMessage callSTerminateMessage) {
+ RongCallCommon.CallMediaType mediaType = callSTerminateMessage.getMediaType();
+ if (mediaType.equals(RongCallCommon.CallMediaType.AUDIO)) {
+ return new SpannableString(context.getString(R.string.rc_voip_message_audio));
+ } else {
+ return new SpannableString(context.getString(R.string.rc_voip_message_video));
+ }
+ }
+}
diff --git a/OneToOne/src/main/res/layout/activity_call_video.xml b/OneToOne/src/main/res/layout/activity_call_video.xml
index 92b34aba1..3d0714f08 100644
--- a/OneToOne/src/main/res/layout/activity_call_video.xml
+++ b/OneToOne/src/main/res/layout/activity_call_video.xml
@@ -2,13 +2,15 @@
-
-
-
+ app:layout_constraintEnd_toEndOf="parent">
+
-
+
-
+
-
+
+
-
+
-
+
-
+
+
-
+
-
-
-
-
-
\ No newline at end of file
diff --git a/OneToOne/src/main/res/layout/view_call_video_item.xml b/OneToOne/src/main/res/layout/view_call_video_item.xml
new file mode 100644
index 000000000..d36c6a597
--- /dev/null
+++ b/OneToOne/src/main/res/layout/view_call_video_item.xml
@@ -0,0 +1,125 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OneToOne/src/main/res/layout/view_message_input_gift.xml b/OneToOne/src/main/res/layout/view_message_input_gift.xml
index 26d8cacfb..768884700 100644
--- a/OneToOne/src/main/res/layout/view_message_input_gift.xml
+++ b/OneToOne/src/main/res/layout/view_message_input_gift.xml
@@ -11,6 +11,7 @@
android:layout_width="0dp"
android:layout_height="165dp"
android:layout_marginStart="16dp"
+ android:layout_marginTop="15dp"
android:layout_marginEnd="16dp"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:layout_constraintEnd_toEndOf="parent"
diff --git a/OneToOne/src/main/res/mipmap-xxhdpi/ic_call_msg.png b/OneToOne/src/main/res/mipmap-xxhdpi/ic_call_msg.png
index e0490a479..50436a7a4 100644
Binary files a/OneToOne/src/main/res/mipmap-xxhdpi/ic_call_msg.png and b/OneToOne/src/main/res/mipmap-xxhdpi/ic_call_msg.png differ