android視訊通話
阿新 • • 發佈:2019-02-16
最近學習Android平臺下跨平臺音視訊通訊開發,雖然網上有很多開源專案供我們參考學習,但音視訊效果很一般,還有很多不穩定的因素,畢竟是開源嘛。在國內我找到了一個比較好音視訊通訊解決方案(點選下載官方demo),該案例提供了純Java語言介面供我們呼叫,隨後我參照官方android demo程式和開發文件並結合自己的見解寫了一個android音訊通訊軟體,200行以內程式碼就搞定了(難以相信吧)。其實我只是呼叫其相關API即可實現。以下是我自己寫的Java程式碼,以備大家互相學習:
Java程式碼- /**
- * Android視訊聊天
- * 1、初始化SDK 2、連線伺服器、 3、使用者登入;4、進入房間;5、開啟本地視訊;6、請求對方視訊
- */
- publicclass VideoChatActivity extends Activity implements AnyChatBaseEvent
- {
- private AnyChatCoreSDK anychat; // 核心SDK
- private SurfaceView remoteSurfaceView; // 對方視訊
- private SurfaceView localSurfaceView; // 本地視訊
- private ConfigEntity configEntity;
- privateboolean bSelfVideoOpened = false;
- privateboolean bOtherVideoOpened = false; // 對方視訊是否已開啟
- private TimerTask mTimerTask; // 定時器
- private Timer mTimer = new Timer(true);
- private Handler handler; // 用Handler來不間斷重新整理即時視訊
- private List<String> userlist = new ArrayList<String>();//儲存線上使用者列表
- private
- @Override
- publicvoid 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(){
- publicvoid run(){
- Message mesasge = new Message();
- handler.sendMessage(mesasge);
- }
- };
- mTimer.schedule(mTimerTask, 1000, 100);
- handler = new Handler(){
- @Override
- publicvoid handleMessage(Message msg){
- VideoChat();// 不間斷顯示即時視訊通話畫面
- super.handleMessage(msg);
- }
- };
- }
- // 初始化SDK 連線伺服器
- privatevoid 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);// 連線伺服器
- }
- // 顯示即時視訊通話畫面
- publicvoid 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;
- }
- }
- }
- publicvoid OnAnyChatConnectMessage(boolean bSuccess){
- if (!bSuccess){
- Toast.makeText(VideoChatActivity.this, "連線伺服器失敗,自動重連,請稍後...", Toast.LENGTH_SHORT).show();
- }
- anychat.Login("android", ""); // 伺服器連線成功 使用者登入
- }
- publicvoid 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();
- }
- }
- publicvoid 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();
- }
- }
- publicvoid 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();
- }
- }
- }
- publicvoid 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+""); //移除該使用者
- }
- }
- }
- publicvoid OnAnyChatLinkCloseMessage(int dwErrorCode){
- Toast.makeText(VideoChatActivity.this, "連線關閉,error:" + dwErrorCode, Toast.LENGTH_SHORT).show();
- }
- @Override
- protectedvoid onDestroy(){ //程式退出
- anychat.LeaveRoom(-1); //離開房間
- anychat.Logout(); //登出登入
- anychat.Release(); //釋放資源
- mTimer.cancel();
- super.onDestroy();
- }
- // 根據配置檔案配置視訊引數
- privatevoid 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程式供參考學習,效果圖檢視圖片附件