记录:uni-app 开发原生组件视频通话的总结
由于本人不会原生,因此原生的东西整起来十分费劲,但最终还是好了 URTC视频通话,由于之前同事整的URTC版本较低 ,导致视频通过过程大多数情况是没有声音的,和客服沟通后让我升级sdk试试
如下部分代码可见 Uni-app官网原生插件开发可见.
一、Uni-app的配置如下:
1、 图中common-2.12.4.arr,libuvccamera-release.arr,ucloudrtclib-2.1.4.arr 这三个arr包 为URTC提供的android包,放进去就行,主要是uniplugin_urtc-release.aar 这个包 需要用android studio打包生存的
2、关于package.json里的配置
"plugins": [
{
"type": "module",
"name": "chkj-urtc", //原生插件名称
"class": "com.chkj.urtc.URTCModule" //原生插件代码里自己创建的类 具体参考Uni-app原生插件开发
}
],
"hooksClass": "com.chkj.urtc.URTCAppHookProxy", //uni-app原生插件配置代理跳转入口
"integrateType": "aar",
3、引入原生插件
二、android studio打开下载好的sdk代码
1、创建Module uniplugin_urtc 将sdk里的代码剪切到这个module里
2、lib文件夹
3、uniplugin_urtc的build.gradle配置
//plugins {
// id 'com.android.application'
//}
apply plugin: 'com.android.library' //代表是个插件
android {
compileSdkVersion 26
defaultConfig {
minSdkVersion rootProject.minSdkVersion
compileSdkVersion rootProject.compileSdkVersion
buildToolsVersion rootProject.buildToolsVersion
targetSdkVersion rootProject.targetSdkVersion
versionName rootProject.versionName
versionCode 44
ndk {
abiFilters "armeabi-v7a", "arm64-v8a"
}
}
lintOptions {
checkReleaseBuilds false
// Or, if you prefer, you can continue to check for errors in release builds,
// but continue the build even when errors are found:
abortOnError false
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
compileOptions {
sourceCompatibility = '1.8'
targetCompatibility = '1.8'
}
}
repositories {
flatDir {
dirs 'libs'
}
}
dependencies {
compileOnly fileTree(include: ['.jar', '.aar'], dir: 'libs')
// implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:2.0.4'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'com.android.support.test🏃1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
// compileOnly 'com.android.support:appcompat-v7:28.0.0'
// compileOnly 'com.android.support:recyclerview-v7:28.0.0'
// compileOnly 'com.android.support:support-v4:28.0.0'
implementation var.SupportV7
implementation var.SupportV4
implementation var.SupportRecyclerviewV7
implementation 'com.squareup.okhttp3:okhttp:3.9.1'
//bugly
implementation 'com.tencent.bugly:crashreport:latest.release'
implementation 'com.tencent.bugly:nativecrashreport:latest.release'
implementation 'tv.danmaku.ijk.media:ijkplayer-java:0.8.8'
implementation 'tv.danmaku.ijk.media:ijkplayer-armv7a:0.8.8'
implementation 'tv.danmaku.ijk.media:ijkplayer-exo:0.8.8'
compileOnly 'com.alibaba:fastjson:1.1.46.android'
compileOnly fileTree(include: ['uniapp-v8-release.aar'], dir: '../app/libs')
compileOnly(name: 'ucloudrtclib-2.1.4', ext: 'aar')
compileOnly(name: 'libuvccamera-release', ext: 'aar')
compileOnly(name: 'common-2.12.4', ext: 'aar')
}
4、URTCAppHookProxy
package com.chkj.urtc;
import android.app.ActivityManager;
import android.app.Application;
import android.content.Context;
import android.text.TextUtils;
import com.ucloudrtclib.sdkengine.UCloudRtcSdkEnv;
import com.ucloudrtclib.sdkengine.define.UCloudRtcSdkLogLevel;
import io.dcloud.feature.uniapp.UniAppHookProxy;
public class URTCAppHookProxy implements UniAppHookProxy {
@Override
public void onCreate(Application application) {
if (TextUtils.equals(getCurrentProcessName(application), application.getPackageName())) {
init(application);
}
}
@Override
public void onSubProcessCreate(Application application) {
if (TextUtils.equals(getCurrentProcessName(application), application.getPackageName())) {
init(application);
}
}
private void init(Application application) {
// 初始化SDK
UCloudRtcSdkEnv.initEnv(application);
// 打印日志到logcat
UCloudRtcSdkEnv.setWriteToLogCat(true);
// 开启日志上报
UCloudRtcSdkEnv.setLogReport(true);
// logo日志等级
UCloudRtcSdkEnv.setLogLevel(UCloudRtcSdkLogLevel.UCLOUD_RTC_SDK_LogLevelNone);
}
private String getCurrentProcessName(Context context) {
int pid = android.os.Process.myPid();
ActivityManager mActivityManager = (ActivityManager) context
.getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningAppProcessInfo appProcess : mActivityManager
.getRunningAppProcesses()) {
if (appProcess.pid == pid) {
return appProcess.processName;
}
}
return null;
}
}
5、URTCModule
package com.chkj.urtc;
import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.view.WindowManager;
import com.alibaba.fastjson.JSONObject;
import com.chkj.urtc.Application.UCloudRtcApplication;
import com.chkj.urtc.activity.ConnectActivity;
import com.chkj.urtc.activity.RoomActivity;
import com.chkj.urtc.common.Config;
import com.chkj.urtc.utils.CommonUtils;
import com.chkj.urtc.utils.PermissionUtils;
import com.taobao.weex.annotation.JSMethod;
import com.taobao.weex.bridge.JSCallback;
import com.ucloudrtclib.sdkengine.UCloudRtcSdkEnv;
import com.ucloudrtclib.sdkengine.define.UCloudRtcSdkMode;
import com.ucloudrtclib.sdkengine.define.UCloudRtcSdkPushEncode;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import io.dcloud.feature.uniapp.common.UniModule;
public class URTCModule extends UniModule {
private Handler mMainHandler = new Handler(Looper.getMainLooper());
private Context mContext = null;
private final JSONObject result = new JSONObject();
@JSMethod(uiThread = false)
public void join(JSONObject params, final JSCallback callback) {
if (params == null) {
result.put("code", -1);
result.put("msg", "请填写参数配置");
callback.invokeAndKeepAlive(result);
return;
}
if (mWXSDKInstance != null) mContext = mWXSDKInstance.getContext();
int openCamera = params.getIntValue("openCamera");
String appKey = params.getString("appKey");
String appId = params.getString("appId");
String roomId = params.getString("roomId");
String uerId = params.getString("uerId");
String token = params.getString("token");
int connect = params.getIntValue("connect");
boolean debugModel = params.getBooleanValue("debugModel");
if (TextUtils.isEmpty(appKey)) {
result.put("code", -1);
result.put("msg", "请填写appKey");
callback.invokeAndKeepAlive(result);
return;
}
if (TextUtils.isEmpty(appId)) {
result.put("code", -1);
result.put("msg", "请填写appId");
callback.invokeAndKeepAlive(result);
return;
}
if (TextUtils.isEmpty(roomId)) {
result.put("code", -1);
result.put("msg", "请填写roomId");
callback.invokeAndKeepAlive(result);
return;
}
if (TextUtils.isEmpty(uerId)) {
result.put("code", -1);
result.put("msg", "请填写uerId");
callback.invokeAndKeepAlive(result);
return;
}
if (TextUtils.isEmpty(token)) {
result.put("code", -1);
result.put("msg", "请填写token");
callback.invokeAndKeepAlive(result);
return;
}
//检测是否拥有camera权限
if (!checkPermissions(Manifest.permission.CAMERA)) {
if (callback != null) {
result.put("code", -1);
result.put("msg", "插件需要[Manifest.permission.CAMERA]权限,请申请!");
callback.invokeAndKeepAlive(result);
}
return;
}
//检测是否拥有文件写入权限
if (!checkPermissions(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
if (callback != null) {
result.put("code", -1);
result.put("msg", "插件需要[Manifest.permission.WRITE_EXTERNAL_STORAGE]权限,请申请!");
callback.invokeAndKeepAlive(result);
}
return;
}
//检测是否拥有录音权限
if (!checkPermissions(Manifest.permission.RECORD_AUDIO)) {
if (callback != null) {
result.put("code", -1);
result.put("msg", "插件需要[Manifest.permission.RECORD_AUDIO]权限,请申请!");
callback.invokeAndKeepAlive(result);
}
return;
}
// List
// needPermissions.add(Manifest.permission.CAMERA);
// needPermissions.add(Manifest.permission.RECORD_AUDIO);
// needPermissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
// needPermissions.add(Manifest.permission.READ_PHONE_STATE);
//
// if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.S){
// needPermissions.add(Manifest.permission.BLUETOOTH_SCAN);
// needPermissions.add(Manifest.permission.BLUETOOTH_CONNECT);
// }
// String[] requestPermissions = new String[needPermissions.size()];
// needPermissions.toArray(requestPermissions);
// PermissionUtils.needsPermissions(mContext, requestPermissions);
// Thread thread = new Thread(new RoomActivity.CopyMixFileTask(this));
// thread.start();
// 配置参数
Config config = Config.getInstance();
config.setOpenCamera(openCamera);
config.setAppId(appId);
config.setAppKey(appKey);
config.setRoomId(roomId);
config.setUerId(uerId);
config.setToken(token);
if (connect == 0) {
connect = 60;
}
config.setConnect(connect);
config.setDebugModel(debugModel);
UCloudRtcSdkEnv.setEncodeMode(UCloudRtcSdkPushEncode.UCLOUD_RTC_PUSH_ENCODE_MODE_H264);
/**
* 设置SDK模式
* UCLOUD_RTC_SDK_MODE_TRIVAL: 测试模式
* UCLOUD_RTC_SDK_MODE_NORMAL: 正式模式
*/
UCloudRtcSdkEnv.setSdkMode(config.isDebugModel() ? UCloudRtcSdkMode.UCLOUD_RTC_SDK_MODE_TRIAL : UCloudRtcSdkMode.UCLOUD_RTC_SDK_MODE_NORMAL);
// 设置重连次数,-1为无限重连
UCloudRtcSdkEnv.setReConnectTimes(config.getConnect());
UCloudRtcSdkEnv.setTokenSecKey(config.getAppKey());
WindowManager windowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
if (windowManager != null) {
windowManager.getDefaultDisplay().getMetrics(outMetrics);
}
CommonUtils.mItemWidth = outMetrics.widthPixels / 3;
CommonUtils.mItemHeight = CommonUtils.mItemWidth;
// 跳转房间页面
// final Intent intent = new Intent(mContext, RoomActivity.class);
final Intent intent = new Intent(mContext, ConnectActivity.class);
// final Intent intent = new Intent(mContext, UCloudRtcApplication.class);
intent.putExtra("room_id", roomId);
intent.putExtra("user_id", uerId);
intent.putExtra("app_id", appId);
intent.putExtra("token", token);
intent.putExtra("join_channel", true);
mMainHandler.postDelayed(new Runnable() {
@Override
public void run() {
// startActivity(intent);
// finish();
mContext.startActivity(intent);
}
}, 500);
// mContext.startActivity(new Intent(mContext, RoomActivity.class));
// mContext.startActivity(new Intent(mContext, ConnectActivity.class));
}
private boolean checkPermissions(String permission) {
boolean result = false;
if (Build.VERSION.SDK_INT >= 23) {
int hasPer = mContext.checkSelfPermission(permission);
if (hasPer == PackageManager.PERMISSION_GRANTED) {
result = true;
}
} else {
result = true;
}
return result;
}
}
三、sdk代码
1、gradle配置
apply plugin: 'com.android.application' //可运行app
//apply plugin: 'com.android.library'
android {
compileSdkVersion 26
defaultConfig {
applicationId "com.chkj.urtctest"
minSdkVersion rootProject.minSdkVersion
compileSdkVersion rootProject.compileSdkVersion
buildToolsVersion rootProject.buildToolsVersion
targetSdkVersion rootProject.targetSdkVersion
versionName rootProject.versionName
versionCode 44
ndk {
abiFilters "armeabi-v7a", "arm64-v8a"
}
}
// lintOptions {
// checkReleaseBuilds false
// // Or, if you prefer, you can continue to check for errors in release builds,
// // but continue the build even when errors are found:
// abortOnError false
// }
signingConfigs {
config {
storeFile file('****.jks')
storePassword '****'
keyAlias = '****'
keyPassword '***'
}
}
buildTypes {
// release {
// minifyEnabled true
// proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
// signingConfig signingConfigs.release
// }
// debug {
// signingConfig signingConfigs.release
// }
debug {
signingConfig signingConfigs.config
}
release {
signingConfig signingConfigs.config
}
}
// sourceSets {
// main {
// jniLibs.srcDirs = ["/src/main/jniLibs"]
// }
// }
//使用uniapp时,需复制下面代码
/代码开始/
aaptOptions {
additionalParameters '--auto-add-overlay'
//noCompress 'foo', 'bar'
ignoreAssetsPattern "!.svn:!.git:.:!CVS:!thumbs.db:!picasa.ini:!.scc:~"
}
/代码结束*/
compileOptions {
sourceCompatibility = '1.8'
targetCompatibility = '1.8'
}
repositories {
flatDir {
dirs 'libs'
}
}
}
dependencies {
// implementation fileTree(include: ['*.jar'], dir: 'libs')
// implementation var.SupportV7
// implementation var.SupportV4
// implementation var.SupportRecyclerviewV7
// implementation 'com.squareup.okhttp3:okhttp:3.9.1'
// testImplementation 'junit:junit:4.12'
//
// implementation (name: 'ucloudrtclib-2.1.4', ext: 'aar')
// implementation(name: 'libuvccamera-release', ext: 'aar')
// implementation(name: 'common-2.12.4', ext: 'aar')
// androidTestImplementation 'com.android.support.test🏃1.0.2'
// androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
// //bugly
// implementation 'com.tencent.bugly:crashreport:latest.release'
// implementation 'com.tencent.bugly:nativecrashreport:latest.release'
// implementation 'tv.danmaku.ijk.media:ijkplayer-java:0.8.8'
// implementation 'tv.danmaku.ijk.media:ijkplayer-armv7a:0.8.8'
// implementation 'tv.danmaku.ijk.media:ijkplayer-exo:0.8.8'
implementation fileTree(include: ['*.jar', '*.aar'], dir: 'libs')
// implementation 'com.android.support:support-v4:28.0.0'
// implementation 'com.android.support:appcompat-v7:28.0.0'
// implementation 'com.android.support:recyclerview-v7:28.0.0'
implementation var.SupportV7
implementation var.SupportV4
implementation var.SupportRecyclerviewV7
implementation 'com.facebook.fresco:fresco:1.13.0'
implementation 'com.facebook.fresco:animated-gif:1.13.0'
implementation 'com.github.bumptech.glide:glide:4.9.0'
implementation 'com.alibaba:fastjson:1.1.46.android'
implementation project(path: ':uniplugin_urtc')
}
2、创建主入口程序,继承 DCloudApplication
3、uni-app打包本地app资源,将代码放到app>src>main>assets>apps下,然后配置dcloud_uniplugins.json 这个下面的
四、测试运行app 可调试
五、打包aar
以上记录只是成功后的总结记录,中间由于很多版本引用等问题非常痛苦,几经周折终于搞定,特此记录