2023-10-28 18:13:23 +08:00

661 lines
26 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.shayu.onetoone.manager;
import android.Manifest;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.view.SurfaceView;
import com.blankj.utilcode.util.PermissionUtils;
import com.shayu.onetoone.AppContext;
import com.shayu.onetoone.R;
import com.shayu.onetoone.bean.SendConsumeBean;
import com.shayu.onetoone.listener.OnCallStatusListener;
import com.shayu.onetoone.listener.OnSendMessageListener;
import com.yunbao.common.CommonAppContext;
import com.yunbao.common.manager.IMLoginManager;
import com.yunbao.common.utils.StringUtil;
import com.yunbao.common.utils.ToastUtil;
import com.yunbao.faceunity.FaceManager;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Timer;
import java.util.TimerTask;
import io.rong.callkit.util.CallKitUtils;
import io.rong.calllib.CallUserProfile;
import io.rong.calllib.IRongCallListener;
import io.rong.calllib.IRongReceivedCallListener;
import io.rong.calllib.RongCallClient;
import io.rong.calllib.RongCallCommon;
import io.rong.calllib.RongCallSession;
import io.rong.calllib.StartCameraCallback;
import io.rong.calllib.message.CallSTerminateMessage;
import io.rong.common.RLog;
import io.rong.imkit.IMCenter;
import io.rong.imlib.RongIMClient;
import io.rong.imlib.model.Conversation;
public class CallClientManager {
public static final String VIDEO_RECEIVED_CALL = "receivedVideoCall";//接听
public static final String VIDEO_CALL = "callVideo";//拨打
public static final String VIDEO_FLOAT = "videoFloatWindow";//浮窗
public static final String AUDIO_RECEIVED_CALL = "receivedAudioCall";//接听
public static final String AUDIO_CALL = "callAudio";//拨打
public static final String AUDIO_FLOAT = "audioFloatWindow";//浮窗
private static CallClientManager manager;
private SurfaceView localVideo, remoteVideo;
private List<OnCallStatusListener> listeners;
private CallTimeTask timeTask = null;
public static CallClientManager getManager() {
if (manager == null) {
manager = new CallClientManager();
}
return manager;
}
private CallClientManager() {
listeners = new ArrayList<>();
init();
}
public SurfaceView getLocalVideo() {
return localVideo;
}
public SurfaceView getRemoteVideo() {
if (RongCallClient.getInstance() != null) {
for (CallUserProfile profile : RongCallClient.getInstance().getCallSession().getParticipantProfileList()) {
if (!profile.getUserId().equals(IMLoginManager.get(AppContext.getTopActivity()).getUserInfo().getId() + "")) {
return profile.getVideoView();
}
}
}
return remoteVideo;
}
private void init() {
RongCallClient.setReceivedCallListener(new CallMeListener());
}
public void addOnVoIPCallListener(OnCallStatusListener statusListener) {
listeners.add(statusListener);
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);
}
startTimer(null);
}
@Override
public void onCallEnd() {
for (OnCallStatusListener listener : listeners) {
listener.onCallEnd();
}
endTimer();
}
@Override
public void onStartFirstFrame() {
for (OnCallStatusListener listener : listeners) {
listener.onStartFirstFrame();
}
}
}));
}
public void removeOnVoIPCallListener(OnCallStatusListener statusListener) {
listeners.remove(statusListener);
}
public void checkMoney(String targetId, boolean video, OnSendMessageListener listener) {
if (video) {
SendMessageManager.checkVideoMessage(targetId, "1", listener);
} else {
SendMessageManager.checkAudioMessage(targetId, "1", listener);
}
}
private void startTimer(String targetId) {
if (timeTask != null) {
timeTask.cancel();
}
timeTask = new CallTimeTask(targetId);
new Timer().schedule(timeTask, 0, 1000);
}
private void endTimer() {
if (timeTask != null) {
timeTask.cancel();
}
timeTask = null;
}
public void callVideo(String targetId) {
RongCallClient.getInstance().setVoIPCallListener(new CallStatusListener(new OnCallStatusListener() {
@Override
public void onCallWait(SurfaceView localVideo) {
for (OnCallStatusListener listener : listeners) {
listener.onCallWait(localVideo);
}
ToastUtil.show(R.string.call_tips1);
}
@Override
public void onCallStart(String userId, SurfaceView remoteVideo) {
for (OnCallStatusListener listener : listeners) {
listener.onCallStart(userId, remoteVideo);
}
ToastUtil.show(R.string.call_tips2);
startTimer(targetId);
}
@Override
public void onCallEnd() {
for (OnCallStatusListener listener : listeners) {
listener.onCallEnd();
}
endTimer();
}
@Override
public void onStartFirstFrame() {
for (OnCallStatusListener listener : listeners) {
listener.onStartFirstFrame();
}
}
}));
List<String> userIds = new ArrayList<>();
userIds.add(targetId);
RongCallClient.getInstance().startCall(Conversation.ConversationType.PRIVATE, targetId, userIds, null, RongCallCommon.CallMediaType.VIDEO, null);
}
public void callAudio(String targetId) {
RongCallClient.getInstance().setVoIPCallListener(new CallStatusListener(new OnCallStatusListener() {
@Override
public void onCallWait(SurfaceView localVideo) {
for (OnCallStatusListener listener : listeners) {
listener.onCallWait(localVideo);
}
ToastUtil.show(R.string.call_tips1);
}
@Override
public void onCallStart(String userId, SurfaceView remoteVideo) {
for (OnCallStatusListener listener : listeners) {
listener.onCallStart(userId, remoteVideo);
}
ToastUtil.show(R.string.call_tips2);
startTimer(targetId);
}
@Override
public void onCallEnd() {
for (OnCallStatusListener listener : listeners) {
listener.onCallEnd();
}
endTimer();
}
@Override
public void onStartFirstFrame() {
for (OnCallStatusListener listener : listeners) {
listener.onStartFirstFrame();
}
}
}));
List<String> userIds = new ArrayList<>();
userIds.add(targetId);
RongCallClient.getInstance().startCall(Conversation.ConversationType.PRIVATE, targetId, userIds, null, RongCallCommon.CallMediaType.AUDIO, null);
}
public void acceptCall(String callId) {
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;
}
public boolean isCallVideo(RongCallSession callSession) {
return callSession.getMediaType().equals(RongCallCommon.CallMediaType.VIDEO);
}
public long getTime(long activeTime) {
return activeTime == 0 ? 0 : (System.currentTimeMillis() - activeTime) / 1000;
}
private class CallTimeTask extends TimerTask {
Handler handler = new Handler(Looper.getMainLooper());
private String targetId;
private String sessionId;
private boolean isCallVideo = false;
long warningTime;
long activeTime;
public CallTimeTask(String targetId) {
this.targetId = targetId;
}
@Override
public boolean cancel() {
if(sessionId.equals(targetId)){
System.err.println("接听方不计费 结束");
return super.cancel();
}
long time = getTime(activeTime);
time = time % 10;
if (time == 0) {
time = 10;
}
if (isCallVideo) {
SendMessageManager.pingVideoMessage(targetId, time + "", new SendMessageListener());
} else {
SendMessageManager.pingAudioMessage(targetId, time + "", new SendMessageListener());
}
return super.cancel();
}
@Override
public void run() {
RongCallSession callSession = RongCallClient.getInstance().getCallSession();
if (callSession == null) {
cancel();
timeTask = null;
return;
}
isCallVideo = callSession.getMediaType() == RongCallCommon.CallMediaType.VIDEO;
activeTime = callSession.getActiveTime();
sessionId=callSession.getCallerUserId();
long time = getTime(activeTime);
checkTime(time);
String extra;
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));
}
handler.post(() -> {
for (OnCallStatusListener listener : listeners) {
listener.onTime(extra);
if (warningTime <= 60) {
listener.onTimeWarning(warningTime--);
}
}
});
}
}
private void checkTime(long time) {
if (StringUtil.isEmpty(targetId)) {
return;
}
if(sessionId.equals(targetId)){
System.err.println("接听方不计费");
return;
}
if(time==0){
return;
}
time = time % 10;
if (time == 0) {
time = 10;
} else {
return;
}
if (isCallVideo) {
SendMessageManager.pingVideoMessage(targetId, time + "", new SendMessageListener());
} else {
SendMessageManager.pingAudioMessage(targetId, time + "", new SendMessageListener());
}
}
private class SendMessageListener extends OnSendMessageListener {
@Override
public void onSuccess(String token, SendConsumeBean bean) {
super.onSuccess(token, bean);
if (isCallVideo) {
warningTime = bean.getVideoTime();
} else {
warningTime = bean.getMp3Time();
}
if (warningTime <= 60) {
for (OnCallStatusListener listener : listeners) {
listener.onTimeWarning(warningTime);
}
}
}
@Override
public void onError(int status, String msg) {
super.onError(status, msg);
if (status == OnSendMessageListener.STATUS_NOT_PRICE) {
for (OnCallStatusListener listener : listeners) {
listener.onErrorNotPrice(msg);
}
endCall();
}
}
}
}
private static class CallMeListener implements IRongReceivedCallListener {
@Override
public void onReceivedCall(RongCallSession callSession) {
Bundle bundle = new Bundle();
bundle.putString("targetId", callSession.getTargetId());
bundle.putString("callId", callSession.getCallId());
bundle.putString("sessionId", callSession.getSessionId());
if (callSession.getMediaType() == RongCallCommon.CallMediaType.VIDEO) {
bundle.putString("model", VIDEO_RECEIVED_CALL);
RouteManager.forwardActivity(RouteManager.ACTIVITY_CALL_VIDEO, bundle);
} else {
bundle.putString("model", AUDIO_RECEIVED_CALL);
RouteManager.forwardActivity(RouteManager.ACTIVITY_CALL_AUDIO, bundle);
}
}
@Override
public void onCheckPermission(RongCallSession callSession) {
ToastUtil.show(R.string.permission_request_title);
PermissionUtils.permission(Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO).callback(new PermissionUtils.SimpleCallback() {
@Override
public void onGranted() {
RongCallClient.getInstance().onPermissionGranted();
}
@Override
public void onDenied() {
RongCallClient.getInstance().onPermissionDenied();
}
}).request();
}
}
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");
}
/**
* 电话已拨出。
* 主叫端拨出电话后,通过回调 onCallOutgoing 通知当前 call 的详细信息。
*
* @param callSession 通话实体。
* @param localVideo 本地 camera 信息。
*/
@Override
public void onCallOutgoing(RongCallSession callSession, SurfaceView localVideo) {
if (isCallVideo(callSession)) {
localVideo.setZOrderOnTop(true);
localVideo.setZOrderMediaOverlay(true);
CallClientManager.this.localVideo = localVideo;
}
statusListener.onCallWait(localVideo);
System.out.println("CallStatusListener.onCallOutgoing");
}
/**
* 已建立通话。
* 通话接通时,通过回调 onCallConnected 通知当前 call 的详细信息。
*
* @param callSession 通话实体。
* @param localVideo 本地 camera 信息。
*/
@Override
public void onCallConnected(RongCallSession callSession, SurfaceView localVideo) {
if (isCallVideo(callSession)) {
localVideo.setZOrderOnTop(true);
localVideo.setZOrderMediaOverlay(true);
CallClientManager.this.localVideo = localVideo;
}
statusListener.onCallWait(localVideo);
}
/**
* 通话结束。
* 通话中,对方挂断,己方挂断,或者通话过程网络异常造成的通话中断,都会回调 onCallDisconnected。
*
* @param callSession 通话实体。
* @param reason 通话中断原因。
*/
@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();
CallClientManager.this.remoteVideo = null;
CallClientManager.this.localVideo = null;
}
@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");
}
/**
* 被叫端加入通话。
* 主叫端拨出电话,被叫端收到请求后,加入通话,回调 onRemoteUserJoined。
*
* @param userId 加入用户的 id。<br />
* @param mediaType 加入用户的媒体类型audio or video。<br />
* @param userType 加入用户的类型1:正常用户,2:观察者。<br />
* @param remoteVideo 加入用户者的 camera 信息。如果 userType为2remoteVideo对象为空<br />
* 如果对端调用{@link RongCallClient#startCall(int, boolean, Conversation.ConversationType, String, List, List, RongCallCommon.CallMediaType, String, StartCameraCallback)} 或
* {@link RongCallClient#acceptCall(String, int, boolean, StartCameraCallback)}开始的音视频通话,则可以使用如下设置改变对端视频流的镜像显示:<br />
* <pre class="prettyprint">
* public void onRemoteUserJoined(String userId, RongCallCommon.CallMediaType mediaType, int userType, SurfaceView remoteVideo) {
* if (null != remoteVideo) {
* ((RongRTCVideoView) remoteVideo).setMirror( boolean);//观看对方视频流是否镜像处理
* }
* }
* </pre>
*/
@Override
public void onRemoteUserJoined(String userId, RongCallCommon.CallMediaType mediaType, int userType, SurfaceView remoteVideo) {
if (mediaType == RongCallCommon.CallMediaType.AUDIO) {
statusListener.onCallStart(userId, null);
return;
}
if (CallClientManager.this.remoteVideo != null) {
statusListener.onCallStart(userId, CallClientManager.this.remoteVideo);
return;
}
remoteVideo.setZOrderOnTop(false);
remoteVideo.setZOrderMediaOverlay(false);
CallClientManager.this.remoteVideo = remoteVideo;
statusListener.onCallStart(userId, remoteVideo);
System.out.println("CallStatusListener.onRemoteUserJoined");
}
@Override
public void onRemoteUserInvited(String userId, RongCallCommon.CallMediaType mediaType) {
System.out.println("CallStatusListener.onRemoteUserInvited");
}
/**
* 通话中的远端参与者离开。
* 回调 onRemoteUserLeft 通知状态更新。
*
* @param userId 远端参与者的 id。
* @param reason 远端参与者离开原因。
*/
@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
public void onRemoteCameraDisabled(String userId, boolean disabled) {
}
@Override
public void onRemoteMicrophoneDisabled(String userId, boolean disabled) {
}
@Override
public void onNetworkReceiveLost(String userId, int lossRate) {
}
@Override
public void onNetworkSendLost(int lossRate, int delay) {
}
@Override
public void onFirstRemoteVideoFrame(String userId, int height, int width) {
if (statusListener != null) {
statusListener.onStartFirstFrame();
}
}
@Override
public void onFirstRemoteAudioFrame(String userId) {
}
@Override
public void onAudioLevelSend(String audioLevel) {
}
@Override
public void onAudioLevelReceive(HashMap<String, String> audioLevel) {
}
@Override
public void onRemoteUserPublishVideoStream(String userId, String streamId, String tag, SurfaceView surfaceView) {
}
@Override
public void onRemoteUserUnpublishVideoStream(String userId, String streamId, String tag) {
}
}
}