package io.rong.callkit; import android.content.Context; import android.content.Intent; import android.graphics.PixelFormat; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.text.TextUtils; import android.view.Gravity; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.SurfaceView; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import java.util.Timer; import java.util.TimerTask; import io.rong.calllib.IRongCallListener; import io.rong.calllib.RongCallClient; import io.rong.calllib.RongCallCommon; import io.rong.calllib.RongCallSession; import io.rong.calllib.message.CallSTerminateMessage; import io.rong.common.RLog; import io.rong.imkit.RongIM; import io.rong.imkit.utils.NotificationUtil; import io.rong.imlib.model.Conversation; /** * Created by weiqinxiao on 16/3/17. */ public class CallFloatBoxView { private static Context mContext; private static Timer timer; private static int mTime; private static View mView; private static Boolean isShown = false; private static WindowManager wm; private static Bundle mBundle; private static final String TAG = "CallFloatBoxView"; public static void showFloatBox(Context context, Bundle bundle, int time) { if (isShown) { return; } mContext = context; isShown = true; mTime = time; mBundle = bundle; wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); final WindowManager.LayoutParams params = new WindowManager.LayoutParams(); int type; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { type = WindowManager.LayoutParams.TYPE_TOAST; } else { type = WindowManager.LayoutParams.TYPE_PHONE; } params.type = type; params.flags = WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; params.format = PixelFormat.TRANSLUCENT; params.width = ViewGroup.LayoutParams.WRAP_CONTENT; params.height = ViewGroup.LayoutParams.WRAP_CONTENT; params.gravity = Gravity.CENTER; params.x = context.getResources().getDisplayMetrics().widthPixels; params.y = 0; mView = LayoutInflater.from(context).inflate(R.layout.rc_voip_float_box, null); mView.setOnTouchListener(new View.OnTouchListener() { float lastX, lastY; int oldOffsetX, oldOffsetY; int tag = 0; @Override public boolean onTouch(View v, MotionEvent event) { final int action = event.getAction(); float x = event.getX(); float y = event.getY(); if (tag == 0) { oldOffsetX = params.x; oldOffsetY = params.y; } if (action == MotionEvent.ACTION_DOWN) { lastX = x; lastY = y; } else if (action == MotionEvent.ACTION_MOVE) { // 减小偏移量,防止过度抖动 params.x += (int) (x - lastX) / 3; params.y += (int) (y - lastY) / 3; tag = 1; if (mView != null) wm.updateViewLayout(mView, params); } else if (action == MotionEvent.ACTION_UP) { int newOffsetX = params.x; int newOffsetY = params.y; if (Math.abs(oldOffsetX - newOffsetX) <= 20 && Math.abs(oldOffsetY - newOffsetY) <= 20) { onClickToResume(); } else { tag = 0; } } return true; } }); wm.addView(mView, params); TextView timeV = (TextView) mView.findViewById(R.id.rc_time); setupTime(timeV); ImageView mediaIconV = (ImageView) mView.findViewById(R.id.rc_voip_media_type); RongCallCommon.CallMediaType mediaType = RongCallCommon.CallMediaType.valueOf(bundle.getInt("mediaType")); if (mediaType.equals(RongCallCommon.CallMediaType.AUDIO)) { mediaIconV.setImageResource(R.drawable.rc_voip_float_audio); } else { mediaIconV.setImageResource(R.drawable.rc_voip_float_video); } RongCallClient.getInstance().setVoIPCallListener(new IRongCallListener() { @Override public void onCallOutgoing(RongCallSession callInfo, SurfaceView localVideo) { } @Override public void onRemoteUserRinging(String userId) { } @Override public void onCallDisconnected(RongCallSession callProfile, RongCallCommon.CallDisconnectedReason reason) { String senderId; String extra = ""; senderId = callProfile.getInviterUserId(); switch (reason) { case HANGUP: case REMOTE_HANGUP: if (mTime >= 3600) { extra = String.format("%d:%02d:%02d", mTime / 3600, (mTime % 3600) / 60, (mTime % 60)); } else { extra = String.format("%02d:%02d", (mTime % 3600) / 60, (mTime % 60)); } break; } if (!TextUtils.isEmpty(senderId)) { CallSTerminateMessage message = new CallSTerminateMessage(); message.setReason(reason); message.setMediaType(callProfile.getMediaType()); message.setExtra(extra); if (senderId.equals(callProfile.getSelfUserId())) { message.setDirection("MO"); } else { message.setDirection("MT"); } RongIM.getInstance().insertMessage(Conversation.ConversationType.PRIVATE, callProfile.getTargetId(), senderId, message, null); } Toast.makeText(mContext, mContext.getString(R.string.rc_voip_call_terminalted), Toast.LENGTH_SHORT).show(); if (wm != null && mView != null) { wm.removeView(mView); timer.cancel(); timer = null; isShown = false; mView = null; mTime = 0; } NotificationUtil.clearNotification(mContext, BaseCallActivity.CALL_NOTIFICATION_ID); RongCallClient.getInstance().setVoIPCallListener(RongCallProxy.getInstance()); } @Override public void onRemoteUserInvited(String userId, RongCallCommon.CallMediaType mediaType) { } @Override public void onRemoteUserJoined(String userId, RongCallCommon.CallMediaType mediaType, SurfaceView remoteVideo) { } @Override public void onRemoteUserLeft(String userId, RongCallCommon.CallDisconnectedReason reason) { } @Override public void onMediaTypeChanged(String userId, RongCallCommon.CallMediaType mediaType, SurfaceView video) { } @Override public void onError(RongCallCommon.CallErrorCode errorCode) { } @Override public void onCallConnected(RongCallSession callInfo, SurfaceView localVideo) { } @Override public void onRemoteCameraDisabled(String userId, boolean muted) { } }); } public static int hideFloatBox() { int t = mTime; RongCallClient.getInstance().setVoIPCallListener(RongCallProxy.getInstance()); if (isShown && null != mView) { wm.removeView(mView); timer.cancel(); timer = null; isShown = false; mView = null; mTime = 0; mBundle = null; } return t; } public static Intent getResumeIntent() { if (mBundle == null) { return null; } RongCallClient.getInstance().setVoIPCallListener(RongCallProxy.getInstance()); Intent intent = new Intent(mBundle.getString("action")); intent.putExtra("floatbox", mBundle); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.putExtra("callAction", RongCallAction.ACTION_RESUME_CALL.getName()); return intent; } public static void onClickToResume() { //当快速双击悬浮窗时,第一次点击之后会把mBundle置为空,第二次点击的时候出现NPE if (mBundle == null) { RLog.d(TAG, "onClickToResume mBundle is null"); return; } RongCallClient.getInstance().setVoIPCallListener(RongCallProxy.getInstance()); Intent intent = new Intent(mBundle.getString("action")); intent.putExtra("floatbox", mBundle); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.putExtra("callAction", RongCallAction.ACTION_RESUME_CALL.getName()); mContext.startActivity(intent); mBundle = null; } private static void setupTime(final TextView timeView) { final Handler handler = new Handler(Looper.getMainLooper()); TimerTask task = new TimerTask() { @Override public void run() { handler.post(new Runnable() { @Override public void run() { mTime++; if (mTime >= 3600) { timeView.setText(String.format("%d:%02d:%02d", mTime / 3600, (mTime % 3600) / 60, (mTime % 60))); } else { timeView.setText(String.format("%02d:%02d", (mTime % 3600) / 60, (mTime % 60))); } } }); } }; timer = new Timer(); timer.schedule(task, 0, 1000); } }