最近学习Android平台下跨平台音视频通信开发,虽然网上有很多开源项目供我们参考学习,但音视频效果很一般,还有很多不稳定的因素,毕竟是开源嘛。在国内我找到了一个比较好音视频通信解决方案(点击下载官方demo),该案例提供了纯Java语言接口供我们调用,随后我参照官方android demo程序和开发文档并结合自己的见解写了一个android音频通信软件,200行以内代码就搞定了(难以相信吧)。其实我只是调用其相关API即可实现。以下是我自己写的Java代码,以备大家互相学习:
/** * Android视频聊天 * 1、初始化SDK 2、连接服务器、 3、用户登录;4、进入房间;5、打开本地视频;6、请求对方视频 */ public class VideoChatActivity extends Activity implements AnyChatBaseEvent { private AnyChatCoreSDK anychat; // 核心SDK private SurfaceView remoteSurfaceView; // 对方视频 private SurfaceView localSurfaceView; // 本地视频 private ConfigEntity configEntity; private boolean bSelfVideoOpened = false; // 本地视频是否已打开 private boolean bOtherVideoOpened = false; // 对方视频是否已打开 private TimerTask mTimerTask; // 定时器 private Timer mTimer = new Timer(true); private Handler handler; // 用Handler来不间断刷新即时视频 private List<String> userlist = new ArrayList<String>();//保存在线用户列表 private int userid; // 用户ID @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_video_chat); remoteSurfaceView = (SurfaceView) findViewById(R.id.surface_remote); localSurfaceView = (SurfaceView) findViewById(R.id.surface_local); configEntity = ConfigService.LoadConfig(this);//加载视频通话设置 loginSystem();// 初始化SDK 连接服务器 mTimerTask = new TimerTask(){ public void run(){ Message mesasge = new Message(); handler.sendMessage(mesasge); } }; mTimer.schedule(mTimerTask, 1000, 100); handler = new Handler(){ @Override public void handleMessage(Message msg){ VideoChat();// 不间断显示即时视频通话画面 super.handleMessage(msg); } }; } // 初始化SDK 连接服务器 private void loginSystem(){ if (anychat == null){ anychat = new AnyChatCoreSDK(); anychat.SetBaseEvent(this); // 设置基本事件回调函数 if (configEntity.useARMv6Lib != 0) // 使用ARMv6指令集 anychat.SetSDKOptionInt(AnyChatDefine. BRAC_SO_CORESDK_USEARMV6LIB, 1); anychat.InitSDK(android.os.Build.VERSION.SDK_INT, 0); // 初始化SDK } anychat.Connect("demo.anychat.cn", 8906);// 连接服务器 } // 显示即时视频通话画面 public void VideoChat(){ if (!bOtherVideoOpened){ if (anychat.GetCameraState(userid) == 2 && anychat.GetUserVideoWidth(userid) != 0){ SurfaceHolder holder = remoteSurfaceView.getHolder(); holder.setFormat(PixelFormat.RGB_565); holder.setFixedSize(anychat.GetUserVideoWidth(userid), anychat.GetUserVideoHeight(userid)); Surface s = holder.getSurface(); // 获得视频画面 anychat.SetVideoPos(userid, s, 0, 0, 0, 0); // 调用API显示视频画面 bOtherVideoOpened = true; } } if (!bSelfVideoOpened){ if (anychat.GetCameraState(-1) == 2 && anychat.GetUserVideoWidth(-1) != 0){ SurfaceHolder holder = localSurfaceView.getHolder(); holder.setFormat(PixelFormat.RGB_565); holder.setFixedSize(anychat.GetUserVideoWidth(-1), anychat.GetUserVideoHeight(-1)); Surface s = holder.getSurface(); anychat.SetVideoPos(-1, s, 0, 0, 0, 0); bSelfVideoOpened = true; } } } public void OnAnyChatConnectMessage(boolean bSuccess){ if (!bSuccess){ Toast.makeText(VideoChatActivity.this, "连接服务器失败,自动重连,请稍后...", Toast.LENGTH_SHORT).show(); } anychat.Login("android", ""); // 服务器连接成功 用户登录 } public void OnAnyChatLoginMessage(int dwUserId, int dwErrorCode){ if (dwErrorCode == 0) { Toast.makeText(this, "登录成功!", Toast.LENGTH_SHORT).show(); anychat.EnterRoom(1, ""); // 用户登录成功 进入房间 ApplyVideoConfig(); } else { Toast.makeText(this, "登录失败,错误代码:" + dwErrorCode, Toast.LENGTH_SHORT).show(); } } public void OnAnyChatEnterRoomMessage(int dwRoomId, int dwErrorCode){ if (dwErrorCode == 0) { // 进入房间成功 打开本地音视频 Toast.makeText(this, "进入房间成功", Toast.LENGTH_SHORT).show(); anychat.UserCameraControl(-1, 1); // 打开本地视频 anychat.UserSpeakControl(-1, 1); // 打开本地音频 } else { Toast.makeText(this, "进入房间失败,错误代码:" + dwErrorCode, Toast.LENGTH_SHORT).show(); } } public void OnAnyChatOnlineUserMessage(int dwUserNum, int dwRoomId){ if (dwRoomId == 1){ int user[] = anychat.GetOnlineUser(); if (user.length != 0){ for (int i = 0; i < user.length; i++){ userlist.add(user[i]+""); } String temp =userlist.get(0); userid = Integer.parseInt(temp); anychat.UserCameraControl(userid, 1);// 请求用户视频 anychat.UserSpeakControl(userid, 1); // 请求用户音频 } else { Toast.makeText(VideoChatActivity.this, "当前没有在线用户", Toast.LENGTH_SHORT).show(); } } } public void OnAnyChatUserAtRoomMessage(int dwUserId, boolean bEnter){ if (bEnter) {//新用户进入房间 userlist.add(dwUserId+""); } else { //用户离开房间 if (dwUserId == userid) { Toast.makeText(VideoChatActivity.this, "视频用户已下线", Toast.LENGTH_SHORT).show(); anychat.UserCameraControl(userid, 0);// 关闭用户视频 anychat.UserSpeakControl(userid, 0); // 关闭用户音频 userlist.remove(userid+""); //移除该用户 if (userlist.size() != 0) { String temp =userlist.get(0); userid = Integer.parseInt(temp); anychat.UserCameraControl(userid, 1);// 请求其他用户视频 anychat.UserSpeakControl(userid, 1); // 请求其他用户音频 } } else { userlist.remove(dwUserId+""); //移除该用户 } } } public void OnAnyChatLinkCloseMessage(int dwErrorCode){ Toast.makeText(VideoChatActivity.this, "连接关闭,error:" + dwErrorCode, Toast.LENGTH_SHORT).show(); } @Override protected void onDestroy(){ //程序退出 anychat.LeaveRoom(-1); //离开房间 anychat.Logout(); //注销登录 anychat.Release(); //释放资源 mTimer.cancel(); super.onDestroy(); } // 根据配置文件配置视频参数 private void ApplyVideoConfig(){ if (configEntity.configMode == 1) // 自定义视频参数配置 { // 设置本地视频编码的码率(如果码率为0,则表示使用质量优先模式) anychat.SetSDKOptionInt(AnyChatDefine.BRAC_SO_LOCALVIDEO_BITRATECTRL,configEntity.videoBitrate); if (configEntity.videoBitrate == 0) { // 设置本地视频编码的质量 anychat.SetSDKOptionInt(AnyChatDefine.BRAC_SO_LOCALVIDEO_QUALITYCTRL,configEntity.videoQuality); } // 设置本地视频编码的帧率 anychat.SetSDKOptionInt(AnyChatDefine.BRAC_SO_LOCALVIDEO_FPSCTRL,configEntity.videoFps); // 设置本地视频编码的关键帧间隔 anychat.SetSDKOptionInt(AnyChatDefine.BRAC_SO_LOCALVIDEO_GOPCTRL,configEntity.videoFps * 4); // 设置本地视频采集分辨率 anychat.SetSDKOptionInt(AnyChatDefine.BRAC_SO_LOCALVIDEO_WIDTHCTRL,configEntity.resolution_width); anychat.SetSDKOptionInt(AnyChatDefine.BRAC_SO_LOCALVIDEO_HEIGHTCTRL,configEntity.resolution_height); // 设置视频编码预设参数(值越大,编码质量越高,占用CPU资源也会越高) anychat.SetSDKOptionInt(AnyChatDefine.BRAC_SO_LOCALVIDEO_PRESETCTRL,configEntity.videoPreset); } // 让视频参数生效 anychat.SetSDKOptionInt(AnyChatDefine.BRAC_SO_LOCALVIDEO_APPLYPARAM,configEntity.configMode); // P2P设置 anychat.SetSDKOptionInt(AnyChatDefine.BRAC_SO_NETWORK_P2PPOLITIC,configEntity.enableP2P); // 本地视频Overlay模式设置 anychat.SetSDKOptionInt(AnyChatDefine.BRAC_SO_LOCALVIDEO_OVERLAY,configEntity.videoOverlay); // 回音消除设置 anychat.SetSDKOptionInt(AnyChatDefine.BRAC_SO_AUDIO_ECHOCTRL,configEntity.enableAEC); // 平台硬件编码设置 anychat.SetSDKOptionInt(AnyChatDefine.BRAC_SO_CORESDK_USEHWCODEC,configEntity.useHWCodec); // 视频旋转模式设置 anychat.SetSDKOptionInt(AnyChatDefine.BRAC_SO_LOCALVIDEO_ROTATECTRL,configEntity.videorotatemode); // 视频平滑播放模式设置 anychat.SetSDKOptionInt(AnyChatDefine.BRAC_SO_STREAM_SMOOTHPLAYMODE,configEntity.smoothPlayMode); // 视频采集驱动设置 anychat.SetSDKOptionInt(AnyChatDefine.BRAC_SO_LOCALVIDEO_CAPDRIVER,configEntity.videoCapDriver); // 本地视频采集偏色修正设置 anychat.SetSDKOptionInt(AnyChatDefine.BRAC_SO_LOCALVIDEO_FIXCOLORDEVIA,configEntity.fixcolordeviation); // 视频显示驱动设置 anychat.SetSDKOptionInt(AnyChatDefine.BRAC_SO_VIDEOSHOW_DRIVERCTRL,configEntity.videoShowDriver); } }
详细看了官方的开发文档你会发现,该Android音视频解决方案还有文字聊天、发送文件、P2P连接等非常实用的功能。对于开发者来说,能快速实现类似QQ聊天和音视频通信是令人振奋的事情。如有不懂可以加QQ讨论:992139738;附上我写的demo程序供参考学习,效果图查看图片附件
相关推荐
在这个案例中,开发者使用了纯Java语言接口的SDK,使得200行代码内就完成了基本的音视频通话功能。 首先,从给出的代码片段来看,`VideoChatActivity`类是实现音视频通话的主要载体,它继承自`Activity`并实现了`...
在Android平台上实现基于Google WebRTC的视频通话,开发者需要对WebRTC、Android编程以及WebSocket通信有深入的理解。本文将详细探讨这些关键知识点。 首先,WebRTC(Web Real-Time Communication)是谷歌开发的一...
【描述】"android语音视频通话源码.rar"描述简洁,表明这是一份关于Android系统的语音和视频通话功能的源代码文件。它可能是开源的,允许开发者深入研究其工作原理,并可作为开发类似应用的基础。 【标签】"android...
通过分析和调试这些代码,你可以更好地掌握Android通话录音的实现细节,并解决可能遇到的问题。 总的来说,实现Android通话录音涉及多个环节,包括权限申请、音频源设置、输出格式和编码的选择,以及文件存储路径的...
本文将围绕“从小白到入门WebRTC音视频通话,Android端WebRTC客户端代码”这一主题,详细介绍如何在Android平台上构建一个基本的WebRTC音视频通话应用程序。 首先,理解WebRTC的基本架构至关重要。WebRTC包括了三个...
基于Java WebSocket 做信令服务器,使用webrtc浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。从而实现音视频通话。下载启动 输入http://localhost 就可使用
在Android系统中,实现语音通话时的自动息屏与亮屏功能是一项涉及到传感器管理、电源管理以及用户界面交互的重要技术。这项技术的核心是利用设备上的距离传感器和Android系统的API来检测手机与用户耳朵的距离,从而...
【Android项目通话记录源代码详解】 在Android平台上,通话记录是手机系统中不可或缺的一部分,它允许用户查看、管理他们的通话历史,包括未接电话、已接电话和已拨电话。这个"android项目通话记录源代码"正是针对...
【Android 开源 Messenger 应用】是一个专为 Android 平台设计的开源应用程序,它提供了实时的消息收发、语音和视频通话功能。这个项目对于开发者来说是一个宝贵的资源,因为它展示了如何构建一个完整的、功能丰富的...
以上就是实现Android通话双向录音的主要技术点。在实际开发中,你可能还需要处理各种异常情况,优化性能,以及考虑用户体验,如提示用户录音正在进行等。通过这些知识点,你应该能够构建一个基本的通话录音解决方案...
理解XML布局文件和Java代码如何配合,实现动态交互和响应式设计,是提升用户体验的关键。 7. 安全与隐私保护 在进行局域网视频聊天时,数据的安全性和用户隐私保护不容忽视。源码可能包含了加密算法的使用,如SSL/...
以下是一段基本的代码示例,展示了如何在Android Studio 3.2中读取通话记录: ```java ContentResolver resolver = getContentResolver(); String[] projection = {CallLog.Calls._ID, CallLog.Calls.NUMBER, ...
sipdroid语音及视频通话实例源码,为Android客户端而开发,以前写过Java的应该对此代码很熟悉,这个开源项目在国外也是受到认可的,很多视频通话应用也是在此基础上扩展修改而来,你可借鉴本源码实例包。
本文将深入探讨Jitsi和Openfire的集成,以及如何在Android平台上实现视频通话功能。 **Jitsi概述** Jitsi是一个开放源码的通信平台,提供了丰富的VoIP(Voice over Internet Protocol)和视频会议功能。它支持多种...
综上所述,"android下面的IMS代码"涉及到的知识点包括Java编程、Android SDK的使用、网络编程、IMS协议栈理解、RCS服务的实现、权限管理、安全隐私、调试测试以及性能优化等多个方面。通过深入学习这些知识,可以更...
至此,你就成功地实现了在Android应用中获取通话状态的功能。需要注意的是,在实际应用中,你还应该考虑权限请求的处理,确保用户同意授予相应的权限,否则应用将无法正常获取通话状态。此外,根据Google Play的政策...
在IT行业中,实现音视频通话功能是许多应用的核心需求,特别是在即时通讯(IM)和在线会议领域。本项目中,开发者使用了环信(Easemob)的SDK来构建这一功能,这是一个专为实时通信设计的开源平台,提供了丰富的API...
源码可能包含了大量的animator XML文件和Java或Kotlin代码段,用于实现这些动态效果。 交互逻辑是另一个关键部分。在通话界面,可能有接听、挂断、静音、免提等操作。在Android上,这涉及监听触摸事件、处理...