本文实例为大家分享了Android实现类似微信视频接听的具体代码,供大家参考,具体内容如下
1、背景需求:业务需要接入视频审核功能,在PC 端发起视频通话,移动端显示通话界面点击接听后进行1对1视频通话。
2、解决方案:因为项目没有IM功能。只集成了极光消息推送(极光消息推送接入参考官方文档,经过跟需求沟通,采用消息推送调起通话接听界面。再集成腾讯实时音视频SDK(具体集成方式参考官方文档)。最终实现类似微信1对1通话功能。
3、技术实现:
A:编写一个广播接收器,并且在 AndroidManifest中注册,这就是一个全局的广播接收器。应用退到后台或者应用进程被kill,只要极光的push进程是Live,就能接受到消息,启动通话接听界面。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
/** * Created on 2018/3/29 16:19 * @author baokang.jia * 极光推送广播接收器 */ public class JiGuangPushReceiver extends BroadcastReceiver { private static final String TAG = "JPushReceiver" ; @Override public void onReceive(Context context, Intent intent) { Bundle bundle = intent.getExtras(); if (bundle == null ) { return ; } //拿到锁屏管理者 KeyguardManager km = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE); if (km != null && km.isKeyguardLocked()) { //为true就是锁屏状态下 startLoginOrCallActivity(context,bundle); } else { if (JPushInterface.ACTION_REGISTRATION_ID.equals(intent.getAction())) { String regId = bundle.getString(JPushInterface.EXTRA_REGISTRATION_ID); LogUtil.d(TAG, "[MyReceiver] 接收Registration Id : " + regId); //send the Registration Id to yours server... } else if (JPushInterface.ACTION_MESSAGE_RECEIVED.equals(intent.getAction())) { LogUtil.d(TAG, "[MyReceiver] 接收到推送下来的自定义消息: " + bundle.getString(JPushInterface.EXTRA_MESSAGE)); } else if (JPushInterface.ACTION_NOTIFICATION_RECEIVED.equals(intent.getAction())) { //接收到推送下来的通知 //启动通话界面 startLoginOrCallActivity(context, bundle); } else if (JPushInterface.ACTION_NOTIFICATION_OPENED.equals(intent.getAction())) { //点击通知栏 //启动通话界面 startLoginOrCallActivity(context, bundle); //清除所有状态的通知 JPushInterface.clearAllNotifications(context); } else if (JPushInterface.ACTION_RICHPUSH_CALLBACK.equals(intent.getAction())) { LogUtil.d(TAG, "[MyReceiver] 用户收到到RICH PUSH CALLBACK: " + bundle.getString(JPushInterface.EXTRA_EXTRA)); //在这里根据 JPushInterface.EXTRA_EXTRA 的内容处理代码,比如打开新的Activity, 打开一个网页等.. } } } /** * 未登录跳转登录界面, * else 启动通话接听界面 */ private void startLoginOrCallActivity(Context context, Bundle bundle) { //EXTRA_EXTRA String extras = bundle.getString(JPushInterface.EXTRA_EXTRA); String userID = SPUtil.getString(context, Constants.LOGIN_USER_ID); if (TextUtils.isEmpty(userID)) { //启动登录界面 Intent intent = new Intent(context, LoginActivity. class ); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intent); } else { //启动通话接听界面 int notifyId = bundle.getInt(JPushInterface.EXTRA_NOTIFICATION_ID); if (!TextUtils.isEmpty(extras) && extras.contains( "androidNotification extras key" )){ ReceiveTalkActivity.startReceiveTalkActivity(context, extras,notifyId); } } } } //在AndroidManifest注册全局自定义广播接收器 <receiver android:name= ".event.JiGuangP`在这里插入代码片`ushReceiver" android:enabled= "true" android:exported= "false" > <intent-filter> <action android:name= "cn.jpush.android.intent.REGISTRATION" /> <!-- Required 用户注册SDK的intent --> <action android:name= "cn.jpush.android.intent.MESSAGE_RECEIVED" /> <!-- Required 用户接收SDK消息的intent --> <action android:name= "cn.jpush.android.intent.NOTIFICATION_RECEIVED" /> <!-- Required 用户接收SDK通知栏信息的intent --> <action android:name= "cn.jpush.android.intent.NOTIFICATION_OPENED" /> <!-- Required 用户打开自定义通知栏的intent --> <action android:name= "cn.jpush.android.intent.CONNECTION" /> <!-- 接收网络变化 连接/断开 since 1.6 . 3 --> <category android:name= "${PACKAGE_NAME}" /> </intent-filter> </receiver> |
B:启动通话接听界面,启动接听界面后获取当前手机模式
1
2
3
|
AudioManager audio = (AudioManager) this .getSystemService(Context.AUDIO_SERVICE); //手机模式,振动,精英、响铃,更具不同模式振动或者响铃,具体可参考以下的实现代码。 //点击接听按钮后跳转腾讯视频通话界面 |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
|
/** * Created on 2019/4/28 16:19 * @author baokang.jia * 视频预审接听界面 */ public class ReceiveTalkActivity extends BaseActivity { private static String PUSH_MSG_KEY = "push_msg_key" ; private static String NOTIFICATION_ID_KEY = "notification_id_key" ; /** * 腾讯云注册分配的appId */ private int sdkAppId = /** * 检查运行时权限 */ private boolean mCheckPermissionResult = false ; private PushMsgBean mPushMsgBean; /** * 媒体播放 */ private MediaPlayer mMediaPlayer; /** * 震动 */ private Vibrator mVibrator; @Override protected void onCreate(Bundle savedInstanceState) { Window window = getWindow(); //悬浮窗 WindowViewUtil.setWindowFloatAndScreenOn(window, this ); super .onCreate(savedInstanceState); //初始化倒计时器 initCountDownTimer(); //请求权限 requestMustPermission(); initViews(); //根据通知Id清除状态栏对应的通知 JPushInterface.clearAllNotifications( this ); //持续震动和响铃 continuedVibratorAndMediaPlayer(); } /** * 60秒后关闭activity */ private void initCountDownTimer() { long time = 30000 ; long countDownInterval = 1000 ; CountDownTimer downTimer = new CountDownTimer(time, countDownInterval) { @Override public void onTick( long millisUntilFinished) { } @Override public void onFinish() { finish(); } }; downTimer.start(); } @Override protected int getLayoutId() { return R.layout.activity_receive_talk; } @Override protected boolean initToolbar() { return false ; } @Override protected void getIntent(Intent intent) { String pushMsg = getIntent().getStringExtra(PUSH_MSG_KEY); //notificationId = getIntent().getIntExtra(NOTIFICATION_ID_KEY, 0); parsePushMsg(pushMsg); } @Override protected void initViews() { Button btnCancel = findViewById(R.id.btn_cancel_call); Button btnAnswer = findViewById(R.id.btn_answer_call); btnCancel.setOnClickListener(v ->{ mVibrator.cancel(); mMediaPlayer.stop(); finish(); }); btnAnswer.setOnClickListener(v -> { mVibrator.cancel(); mMediaPlayer.stop(); if (mCheckPermissionResult) { Intent intent = new Intent( this , TRTCMainActivity. class ); intent.putExtra( "roomId" , Integer.valueOf(mPushMsgBean.getRoomId())); intent.putExtra( "userId" , mPushMsgBean.getUserId()); intent.putExtra( "sdkAppId" , sdkAppId); intent.putExtra( "userSig" , mPushMsgBean.getUserSig()); startActivity(intent); finish(); } else { ToastUtil.longToast( "需要的权限被拒绝,无法开启视频审核" ); } }); } /** * 持续响铃和震动 */ private void continuedVibratorAndMediaPlayer() { //获取媒体播放器 mMediaPlayer = new MediaPlayer(); try { mMediaPlayer.setDataSource( this , RingtoneManager .getDefaultUri(RingtoneManager.TYPE_RINGTONE)); //这里我用的通知声音,还有其他的,大家可以点进去看 mMediaPlayer.prepare(); } catch (IOException e) { e.printStackTrace(); } //取得震动服务的句柄 mVibrator = (Vibrator) this . getSystemService(VIBRATOR_SERVICE); //获取当前手机模式 AudioManager audio = (AudioManager) this .getSystemService(Context.AUDIO_SERVICE); if (audio != null ) { switch (audio.getRingerMode()) { case AudioManager.RINGER_MODE_SILENT: //静音 //do sth break ; case AudioManager.RINGER_MODE_NORMAL: //响铃 mMediaPlayer.start(); mMediaPlayer.setLooping( true ); //循环播放 break ; case AudioManager.RINGER_MODE_VIBRATE: //震动 //数组参数意义:第一个参数为等待指定时间后开始震动, //震动时间为第二个参数。后边的参数依次为等待震动和震动的时间 //第二个参数为重复次数,-1为不重复,0为一直震动 if (mVibrator != null ) { mVibrator.vibrate( new long []{ 1000 , 1000 }, 0 ); } break ; } } } private void parsePushMsg(String pushMsg) { if (!TextUtils.isEmpty(pushMsg)) { CustomerMsg customerMsg = GsonUtil.fromJson(pushMsg, CustomerMsg. class ); String pushMsgContent = customerMsg.getPushMsgContent(); pushMsgContent = pushMsgContent.replace( "\\" , "" ); LogUtil.d(Constants.LOG, "pushMsgContent=" +pushMsgContent); mPushMsgBean = GsonUtil.fromJson(pushMsgContent, PushMsgBean. class ); } } /** * 申请应用必须的权限 */ private void requestMustPermission() { AndPermission.with( this ) .requestCode(Constants.REQUEST_CODE_PERMISSION) .permission( Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.VIBRATE, Manifest.permission.DISABLE_KEYGUARD, Manifest.permission.WAKE_LOCK ) .rationale((requestCode, rationale) -> //再次申请被拒绝的权限 AlertDialog.newBuilder( this ) .setTitle(R.string.title_dialog) .setMessage(R.string.message_permission_failed) .setPositiveButton(R.string.ok, (dialog, which) -> { dialog.cancel(); rationale.resume(); }) .setNegativeButton(R.string.no, (dialog, which) -> { dialog.cancel(); rationale.cancel(); }).show()) .callback( new PermissionListener() { @Override public void onSucceed( int requestCode, @NonNull List<String> grantPermissions) { mCheckPermissionResult = true ; } @Override public void onFailed( int requestCode, @NonNull List<String> deniedPermissions) { mCheckPermissionResult = false ; } }) .start(); } /** * 界面未销毁,启动此界面时回调 */ @Override protected void onNewIntent(Intent intent) { super .onNewIntent(intent); String pushMsg = intent.getStringExtra(PUSH_MSG_KEY); //notificationId = intent.getIntExtra(NOTIFICATION_ID_KEY, 0); parsePushMsg(pushMsg); } /** * 提供给外部调用启动接听界面的activity * * @param cex 上下文对象 * @param pushMsg 消息内容 * @param notifyId 通知id */ public static void startReceiveTalkActivity(Context cex, String pushMsg, int notifyId) { Intent calIntent = new Intent(cex, ReceiveTalkActivity. class ); //携带数据 calIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); calIntent.putExtra(PUSH_MSG_KEY, pushMsg); calIntent.putExtra(NOTIFICATION_ID_KEY, notifyId); cex.startActivity(calIntent); } @Override protected void onDestroy() { super .onDestroy(); mMediaPlayer.stop(); mVibrator.cancel(); } } //注册ReceiveTalkActivity, android:launchMode="singleTask" <activity android:name= ".trtc.view.ReceiveTalkActivity" android:launchMode= "singleTask" android:screenOrientation= "portrait" /> |
总结:项目中考虑时间和成本问题。没有接入IM功能。消息推送不可靠,极光的push进程被杀,是收不到消息。当打开app后,会蹦出很多通知。这只是简易的实现了在pc调起移动端进行视频通话。这有很多因素是没有考虑进去的,在此先记录下吧。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/jiabaokang/article/details/91371123