本文重点为如何教你使用QFAV快速搭建一个android一对一的demo,感觉没有必要每一步都上图,所以某些操作需要大家自己脑补。
服务器部署:我们同时提供了mac,Windows与Linux的服务器,只需要简单的./EXE即可运行,其中fvideo视频服务端口为固定10005,faudio固定端口为10006 我们会持续优化
Mac:
Windows:
Liunx:
1.首先新建项目,我们选择一个empty的Active,取名QFAVAndroidDemo,工作目录为workvideo
2.将jinlibs拷贝的到src/main目录下与java,res同级。
3.新建App.java做为程序入口,在Andriodmainifest.xml中增加权限以及APP声明
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="workvideo.fvideo">
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.NETWORK" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<application
android:name=".App"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
4.拷贝RealtimeSdk与当前包同级目录中,App.java中引入com.RealtimeSdk.*;并且对SDK初始化
package workvideo.fvideo;
import android.app.Application;
import android.util.Log;
import workvideo.RealtimeSdk.*;
public class App extends Application
{
public static final String TAG ="meeting.debug";
static App instance =null;
@Override
public void onCreate()
{
super.onCreate();
instance =this;
// 启动SDK
RealTime.init();
// 初始化声音
Sound.instance.Init(this);
// 设置空白视频画面
RealTime.set_blank(getAssets(), "blank");
}
void onExit()
{
RealTime.uninit();
Log.w(TAG, "onExit()");
System.exit(0);
}
}
5.我们的前面准备都已经完成,现在开始我们的大活儿
5.1我们先铺满整个应用,调起我们的摄像头,active_main.xml中配置摄像头,布局目前仅支持android.widget.RelativeLayout,对于带来不好的体验万分抱歉,我们会后续持续优化
<?xml version="1.0" encoding="utf-8"?>
<android.widget.RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<workvideo.RealtimeSdk.CameraView
android:id="@+id/cameraView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.widget.RelativeLayout>
MainActive.java中,继承RealtimeSDK.VideoActivity,方便后续调用桌面共享,高版本可能回提示onside的抽象,所以重载一下protected void onSize(int width, int height){},在初始化的时候检查一下用户权限
package workvideo.qfavandroiddemo;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import workvideo.RealtimeSdk.VideoActivity;
public class MainActivity extends VideoActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
checkPermission();
}
protected void onSize(int width, int height){}
}
5.2 我们现在集成播放器,同时布局好推流拉流按钮,所以我在relative里添加了一个线性布局,好让窗口自适应填充.在这里我重点解释一下,对了应对多人同时在线语音的场景,我们设计了Fvideo与Faudio两个服务器,fvideo可以同时推流音频与视频,faudio仅支持推流音频,房间内人数过多的时候,我们建议采用faudio走音频,faudio的推流方式是fauido://ip:10006/gourpid,拉流一样是fauido://ip:10006/gourpid,而fvideo推流方式是fvideo://ip:10005/userid,拉流同样,这里我们设置用户userid为1234,gourpid为1
所以我们安排了两个player,其中一个用于播放音频,应对多人情况
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<workvideo.RealtimeSdk.CameraView
android:id="@+id/cameraView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"/>
<EditText
android:id="@+id/editTextPush0"
android:layout_width="match_parent"
android:layout_height="40dp"
android:ems="10"
android:inputType="textUri"
android:text="fvideo://124.239.190.120:10005/1234" />
<EditText
android:id="@+id/editTextPush1"
android:layout_width="match_parent"
android:layout_height="40dp"
android:ems="10"
android:inputType="textUri"
android:text="faudio://124.239.190.120:10006/1" />
<Button
android:id="@+id/buttonPush"
android:layout_width="match_parent"
android:layout_height="40dp"
android:text="推送" />
<workvideo.RealtimeSdk.PlayerView
android:id="@+id/playerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1" />
<workvideo.RealtimeSdk.PlayerView
android:id="@+id/playerViewAudio"
android:layout_width="match_parent"
android:layout_height="1dp" />
<EditText
android:id="@+id/editTextPull0"
android:layout_width="match_parent"
android:layout_height="40dp"
android:ems="10"
android:inputType="textUri"
android:text="fvideo://124.239.190.120:10005/1234" />
<EditText
android:id="@+id/editTextPull1"
android:layout_width="match_parent"
android:layout_height="40dp"
android:ems="10"
android:inputType="textUri"
android:text="faudio://124.239.190.120:10006/1" />
<Button
android:id="@+id/buttonPull"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_alignTop="@+id/editText"
android:text="拉取" />
</androidx.appcompat.widget.LinearLayoutCompat>
5.3 开始集成java,代码,首先我们需要初始化,并且监听一下声音
Sound.instance.start(); //开启声音设备
findViewById(R.id.buttonPush).setOnClickListener(this);
findViewById(R.id.buttonPull).setOnClickListener(this);
监听推流按钮事件,开启两路推流 0 推流视频,1推流音频,同时设置userID
if( !Sound.mic_state() ) {
// 开始推送
EditText editpush0 =findViewById(R.id.editTextPush0);
RealTime.set_push_url(0,editpush0.getText().toString());
EditText editpush1 =findViewById(R.id.editTextPush1);
RealTime.set_push_url(1,editpush1.getText().toString());
RealTime.set_push_uid(12345); // any 64bit number
RealTime.set_video_source(RealTime.source_camera);
Sound.set_mic_state(true);
((Button)view).setText("停止推送");
}
else {
// 停止推送
Sound.set_mic_state(false);
RealTime.set_video_source(RealTime.source_none);
RealTime.set_push_url(0,null);
RealTime.set_push_url(1,null);
((Button)view).setText("开始推送");
}
监听拉流事件,一个播放器播放视频,一个播放器播放音频,注:一个房间只需要一个音频播放器即可,我们内部会处理大房间内所有的声音,所以,你不用担心一个房间里100甚至1000个人说话会受到影响。
PlayerView playerView =(PlayerView)findViewById(R.id.playerView);
PlayerView playerViewAudio =(PlayerView)findViewById(R.id.playerViewAudio);
if (isPlaying) {
// 停止播放
playerView.stop();
playerView.load(null);
playerViewAudio.stop();
playerViewAudio.load(null);
isPlaying =false;
((Button)view).setText("开始播放");
}
else {
// 开始播放
EditText editpull0 =findViewById(R.id.editTextPull0);
playerView.load(editpull0.getText().toString());
//playerView.play(RealTime.PLAY_BIT_AUDIO | RealTime.PLAY_BIT_VIDEO);
playerView.play(RealTime.PLAY_BIT_VIDEO);
EditText editpull1 =findViewById(R.id.editTextPull1);
playerViewAudio.load(editpull1.getText().toString());
playerViewAudio.play(RealTime.PLAY_BIT_AUDIO);
isPlaying =true;
((Button)view).setText("停止播放");
}
这样我们就完成了一个QFAV安卓的快速一对一集成,github源码地址为:
https://github.com/twomsoft/qfav/tree/master/android/QFAVAndroidDemo
有什么想法跟意见,欢迎随时评论