diff --git a/OneToOne/src/main/AndroidManifest.xml b/OneToOne/src/main/AndroidManifest.xml index 02276256e..5c79f1afb 100644 --- a/OneToOne/src/main/AndroidManifest.xml +++ b/OneToOne/src/main/AndroidManifest.xml @@ -147,6 +147,11 @@ + + + { + SurfaceView surfaceView = CallClientManager.getManager().getRemoteVideo(targetId); + surfaceView.setLayoutParams(new ViewGroup.LayoutParams(-1, -1)); + myView.addView(surfaceView); + myView.addView(buttonView); + targetView.addView(CallClientManager.getManager().getLocalVideo()); + }, 300); + + } } private void initView() { + rootView = findViewById(R.id.rootView); myView = findViewById(R.id.my_view); targetView = findViewById(R.id.target_view); - callStop = findViewById(R.id.call_stop); - gift = findViewById(R.id.gift); - message = findViewById(R.id.message); - cameraCloseSwitch = findViewById(R.id.camera_close_switch); - cameraSwitch = findViewById(R.id.camera_switch); - micSwitch = findViewById(R.id.mic_switch); - money = findViewById(R.id.money); - avatar = findViewById(R.id.avatar); - close = findViewById(R.id.close); - follow = findViewById(R.id.follow); - followText = findViewById(R.id.follow_text); + callLayout = findViewById(R.id.rc_voip_two_btn); + buttonView = LayoutInflater.from(mContext).inflate(R.layout.view_call_video_item, rootView, false); + initButton(buttonView); + // 为所有View设置点击事件监听器 + setClickListeners(); + } + + private void initButton(View itemView) { + callStop = itemView.findViewById(R.id.call_stop); + gift = itemView.findViewById(R.id.gift); + message = itemView.findViewById(R.id.message); + cameraCloseSwitch = itemView.findViewById(R.id.camera_close_switch); + cameraSwitch = itemView.findViewById(R.id.camera_switch); + micSwitch = itemView.findViewById(R.id.mic_switch); + money = itemView.findViewById(R.id.money); + avatar = itemView.findViewById(R.id.avatar); + close = itemView.findViewById(R.id.close); + follow = itemView.findViewById(R.id.follow); + followText = itemView.findViewById(R.id.follow_text); // 为所有View设置点击事件监听器 setClickListeners(); } @@ -78,14 +180,191 @@ public class CallVideoActivity extends AbsOTOActivity { avatar.setOnClickListener(onClickListener); close.setOnClickListener(onClickListener); follow.setOnClickListener(onClickListener); + findViewById(R.id.rc_voip_call_answer_btn).setOnClickListener(onClickListener); + findViewById(R.id.rc_voip_call_hang_up).setOnClickListener(onClickListener); } - private View.OnClickListener onClickListener = new View.OnClickListener() { + private void accept() { + callLayout.setVisibility(View.GONE); + CallClientManager.getManager().acceptCall(targetId); + } + + private void closeCamera() { + RongCallClient.getInstance().setEnableLocalVideo(!RongCallClient.getInstance().isLocalVideoEnabled()); + cameraCloseSwitch.setImageResource(RongCallClient.getInstance().isLocalAudioEnabled() ? R.mipmap.ic_call_video_select : R.mipmap.ic_call_video); + if (RongCallClient.getInstance().isLocalVideoEnabled()) { + targetView.setVisibility(View.VISIBLE); + } else { + targetView.setVisibility(View.INVISIBLE); + } + } + + private void switchCamera() { + RongCallClient.getInstance().switchCamera(); + } + + private void switchAudio() { + RongCallClient.getInstance().setEnableLocalAudio(!RongCallClient.getInstance().isLocalAudioEnabled()); + ToastUtil.show("麦克风状态:" + RongCallClient.getInstance().isLocalAudioEnabled()); + micSwitch.setImageResource(RongCallClient.getInstance().isLocalAudioEnabled() ? R.mipmap.ic_call_audio_select : R.mipmap.ic_call_audio); + } + + private void showWindow(boolean toChatView) { + CallClientManager.getManager().getRemoteVideo(targetId).setTag(getIntent().getBundleExtra("bundle")); + myView.removeAllViews(); + targetView.removeAllViews(); + finish(); + CallClientManager.getManager().getRemoteVideo(targetId).setLayoutParams(new ViewGroup.LayoutParams(DpUtil.dp2px(114), DpUtil.dp2px(164))); + EasyFloat.with(this) + .setLayout(CallClientManager.getManager().getRemoteVideo(targetId)) + .setShowPattern(ShowPattern.FOREGROUND) + .setTag("call") + .setDragEnable(true) + .setBorder() + .registerCallbacks(new OnFloatCallbacks() { + OnCallStatusListener windowListener; + + @Override + public void createdResult(boolean b, @Nullable String s, @Nullable View view) { + + } + + @Override + public void show(@NonNull View view) { + view.setOnClickListener(v -> { + RouteManager.forwardActivity(RouteManager.ACTIVITY_CALL_VIDEO, (Bundle) v.getTag()); + }); + windowListener = new WindowCallStatusListener(); + CallClientManager.getManager().addOnVoIPCallListener(windowListener); + } + + @Override + public void hide(@NonNull View view) { + + } + + @Override + public void dismiss() { + CallClientManager.getManager().removeOnVoIPCallListener(windowListener); + } + + @Override + public void touchEvent(@NonNull View view, @NonNull MotionEvent motionEvent) { + + } + + @Override + public void drag(@NonNull View view, @NonNull MotionEvent motionEvent) { + + } + + @Override + public void dragEnd(@NonNull View view) { + + } + }).show(); + if (toChatView) { + ConversationUtils.startConversation(mContext, targetId); + } + + + } + + private final View.OnClickListener onClickListener = new View.OnClickListener() { @Override public void onClick(View v) { // 在这里编写点击事件的处理逻辑 int id = v.getId(); - + if (id == R.id.rc_voip_call_answer_btn) { + accept(); + } else if (id == R.id.call_stop || id == R.id.rc_voip_call_hang_up) { + CallClientManager.getManager().endCall(); + } else if (id == R.id.gift) { + new GiftDialog(mContext) + .setTargetId(targetId) + .showDialog(); + } else if (id == R.id.camera_close_switch) { + closeCamera(); + } else if (id == R.id.camera_switch) { + switchCamera(); + } else if (id == R.id.mic_switch) { + switchAudio(); + } else if (id == R.id.close) { + showWindow(false); + } else if (id == R.id.message) { + showWindow(true); + } } }; + + private class CallStatusListener extends OnCallStatusListener { + @Override + public void onCallWait(SurfaceView surfaceView) { + myView.removeAllViews(); + myView.addView(surfaceView); + } + + @Override + public void onCallStart(String userId, SurfaceView surfaceView) { + surfaceView.setZOrderOnTop(false); + surfaceView.setZOrderMediaOverlay(false); + surfaceView.invalidate(); + surfaceView.setOnClickListener(v -> { + surfaceView.setZOrderOnTop(false); + surfaceView.setZOrderMediaOverlay(false); + surfaceView.invalidate(); + }); + if (model.equals(CallClientManager.VIDEO_CALL)) { + targetView.removeAllViews(); + targetView.addView(surfaceView); + myView.removeAllViews(); + myView.addView(CallClientManager.getManager().getLocalVideo()); + } else { + myView.removeAllViews(); + myView.addView(surfaceView); + targetView.removeAllViews(); + targetView.addView(CallClientManager.getManager().getLocalVideo()); + myView.addView(buttonView); + } + } + + @Override + public void onCallEnd() { + finish(); + } + + @Override + public void onStartFirstFrame() { + /* CallClientManager.getManager().getRemoteVideo(targetId).setZOrderOnTop(false); + CallClientManager.getManager().getRemoteVideo(targetId).setZOrderMediaOverlay(false); + CallClientManager.getManager().getRemoteVideo(targetId).invalidate();*/ + } + } + + private class WindowCallStatusListener extends OnCallStatusListener { + @Override + public void onCallWait(SurfaceView surfaceView) { + + } + + @Override + public void onCallStart(String userId, SurfaceView surfaceView) { + + } + + @Override + public void onCallEnd() { + EasyFloat.dismiss("call"); + } + + @Override + public void onStartFirstFrame() { + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + CallClientManager.getManager().removeOnVoIPCallListener(onCallStatusListener); + } } diff --git a/OneToOne/src/main/java/com/shayu/onetoone/dialog/GiftDialog.java b/OneToOne/src/main/java/com/shayu/onetoone/dialog/GiftDialog.java index 715787dda..7dea7e46b 100644 --- a/OneToOne/src/main/java/com/shayu/onetoone/dialog/GiftDialog.java +++ b/OneToOne/src/main/java/com/shayu/onetoone/dialog/GiftDialog.java @@ -7,26 +7,44 @@ import android.widget.TextView; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; +import com.alibaba.fastjson.JSONObject; import com.lxj.xpopup.XPopup; import com.shayu.onetoone.R; import com.shayu.onetoone.adapter.GiftListAdapter; import com.shayu.onetoone.bean.GiftBean; +import com.shayu.onetoone.bean.MessageChatGiftContent; +import com.shayu.onetoone.bean.PurseBean; +import com.shayu.onetoone.listener.OnSendMessageListener; import com.shayu.onetoone.manager.OTONetManager; +import com.shayu.onetoone.manager.SendMessageManager; +import com.shayu.onetoone.view.MsgInputPanelForGift; import com.shayu.onetoone.widget.PagerConfig; import com.shayu.onetoone.widget.PagerGridLayoutManager; import com.shayu.onetoone.widget.PagerGridSnapHelper; import com.yunbao.common.dialog.AbsDialogPopupWindow; import com.yunbao.common.http.base.HttpCallback; +import com.yunbao.common.interfaces.OnItemClickListener; +import com.yunbao.common.manager.IMLoginManager; +import com.yunbao.common.utils.ToastUtil; import java.util.ArrayList; import java.util.List; +import io.rong.imkit.IMCenter; +import io.rong.imlib.IRongCallback; +import io.rong.imlib.RongIMClient; +import io.rong.imlib.model.Conversation; +import io.rong.imlib.model.Message; + public class GiftDialog extends AbsDialogPopupWindow { RecyclerView gifList; GiftListAdapter mAdapter; TextView money; Button topUpBtn; Button sendBtn; + String token; + String targetId; + OnItemClickListener onItemClickListener; public GiftDialog(@NonNull Context context) { @@ -38,6 +56,16 @@ public class GiftDialog extends AbsDialogPopupWindow { } + public GiftDialog setTargetId(String targetId) { + this.targetId = targetId; + return this; + } + + public GiftDialog setOnItemClickListener(OnItemClickListener onItemClickListener) { + this.onItemClickListener = onItemClickListener; + return this; + } + @Override public int bindLayoutId() { return R.layout.view_message_input_gift; @@ -59,18 +87,79 @@ public class GiftDialog extends AbsDialogPopupWindow { PagerConfig.setMillisecondsPreInch(150); gifList.setAdapter(mAdapter); initData(); + sendBtn.setOnClickListener(v -> { + SendMessageManager.sendMessageForGift(targetId, mAdapter.getItem().getId() + "", new OnSendMessageListener() { + @Override + public void onSuccess(String token) { + super.onSuccess(token); + GiftDialog.this.token = token; + sendGift(mAdapter.getItem()); + + } + + @Override + public void onError(int status, String msg) { + super.onError(status, msg); + } + }); + }); + } + + private void sendGift(GiftBean item) { + MessageChatGiftContent bean = MessageChatGiftContent.obtain(JSONObject.toJSONString(item), "1", IMLoginManager.get(mContext).getUserInfo().getId() + ""); + bean.setExtra(JSONObject.toJSONString(item)); + IMCenter.getInstance().sendMessage(Message.obtain(targetId, Conversation.ConversationType.PRIVATE, bean), + null, + null, + new IRongCallback.ISendMessageCallback() { + @Override + public void onAttached(Message message) { + + } + + @Override + public void onSuccess(Message message) { + iniPurse(); + SendMessageManager.onCallSuccess(token, new OnSendMessageListener() { + @Override + public void onError(int status, String msg) { + super.onError(status, msg); + ToastUtil.show(msg); + } + }); + } + + @Override + public void onError(Message message, RongIMClient.ErrorCode errorCode) { + System.out.println("失败:" + errorCode.getMessage()); + System.out.println("失败:" + errorCode.getValue()); + } + } + ); } private void initData() { + iniPurse(); OTONetManager.getInstance(mContext) .getGiftList(new HttpCallback>() { @Override public void onSuccess(List data) { - List list=new ArrayList<>(); - for (int i = 0; i < 10; i++) { - list.addAll(data); - } - mAdapter.setList(list); + mAdapter.setList(data); + } + + @Override + public void onError(String error) { + + } + }); + } + + private void iniPurse() { + OTONetManager.getInstance(mContext) + .getPurseInfo(new HttpCallback() { + @Override + public void onSuccess(PurseBean data) { + money.setText(data.getStart() + ""); } @Override diff --git a/OneToOne/src/main/java/com/shayu/onetoone/listener/OnCallStatusListener.java b/OneToOne/src/main/java/com/shayu/onetoone/listener/OnCallStatusListener.java index 7960e6614..837d60301 100644 --- a/OneToOne/src/main/java/com/shayu/onetoone/listener/OnCallStatusListener.java +++ b/OneToOne/src/main/java/com/shayu/onetoone/listener/OnCallStatusListener.java @@ -8,4 +8,6 @@ public abstract class OnCallStatusListener { public abstract void onCallStart(String userId, SurfaceView remoteVideo); public abstract void onCallEnd(); + + public abstract void onStartFirstFrame(); } diff --git a/OneToOne/src/main/java/com/shayu/onetoone/manager/CallClientManager.java b/OneToOne/src/main/java/com/shayu/onetoone/manager/CallClientManager.java index 664e0a1ba..73182e797 100644 --- a/OneToOne/src/main/java/com/shayu/onetoone/manager/CallClientManager.java +++ b/OneToOne/src/main/java/com/shayu/onetoone/manager/CallClientManager.java @@ -1,26 +1,41 @@ package com.shayu.onetoone.manager; import android.Manifest; +import android.os.Bundle; +import android.text.TextUtils; import android.view.SurfaceView; import com.blankj.utilcode.util.PermissionUtils; import com.shayu.onetoone.listener.OnCallStatusListener; +import com.yunbao.common.CommonAppContext; import com.yunbao.common.manager.IMLoginManager; +import com.yunbao.common.utils.ToastUtil; import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.Locale; +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 CallClientManager manager; + public static final String VIDEO_RECEIVED_CALL = "receivedCall"; + public static final String VIDEO_CALL = "call"; + private static CallClientManager manager; + // private SurfaceView localVideo, remoteVideo; + private List listeners; public static CallClientManager getManager() { if (manager == null) { @@ -30,31 +45,139 @@ public class CallClientManager { } private CallClientManager() { + listeners = new ArrayList<>(); init(); } + public SurfaceView getLocalVideo() { + RongCallSession session = RongCallClient.getInstance().getCallSession(); + String userId= IMLoginManager.get(CommonAppContext.getTopActivity()).getUserInfo().getId()+""; + for (CallUserProfile profile : session.getParticipantProfileList()) { + if(profile.getUserId().equals(userId)){ + return profile.getVideoView(); + } + + } + return null; + } + + public SurfaceView getRemoteVideo(String id) { + RongCallSession session = RongCallClient.getInstance().getCallSession(); + for (CallUserProfile profile : session.getParticipantProfileList()) { + if(profile.getUserId().equals(id)){ + return profile.getVideoView(); + } + + } + return null; + } + private void init() { RongCallClient.setReceivedCallListener(new CallMeListener()); } - public void callVideo(String targetId, OnCallStatusListener statusListener) { - List userIds = new ArrayList<>(); - userIds.add(targetId); - RongCallClient.getInstance().setVoIPCallListener(new CallStatusListener(statusListener)); - RongCallClient.getInstance().startCall(Conversation.ConversationType.PRIVATE,targetId,userIds,null, RongCallCommon.CallMediaType.VIDEO,null); + + public void addOnVoIPCallListener(OnCallStatusListener statusListener) { + listeners.add(statusListener); } + public void removeOnVoIPCallListener(OnCallStatusListener statusListener) { + listeners.remove(statusListener); + } + 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); + } + } + + @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(); + } + } + })); + List 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