农村三个张 發表於 2022-6-2 15:37:00

记录:uni-app 开发原生组件视频通话的总结

<p>由于本人不会原生,因此原生的东西整起来十分费劲,但最终还是好了URTC视频通话,由于之前同事整的URTC版本较低 ,导致视频通过过程大多数情况是没有声音的,和客服沟通后让我升级sdk试试<br>
如下部分代码可见 Uni-app官网原生插件开发可见.<br>
一、Uni-app的配置如下:<br>
<img src="https://img2022.cnblogs.com/blog/490837/202206/490837-20220602150553790-1587835188.png"><br>
1、 图中common-2.12.4.arr,libuvccamera-release.arr,ucloudrtclib-2.1.4.arr这三个arr包 为URTC提供的android包,放进去就行,主要是uniplugin_urtc-release.aar 这个包 需要用android studio打包生存的<br>
2、关于package.json里的配置<br>
"plugins": [<br>
{<br>
"type": "module",<br>
"name": "chkj-urtc",//原生插件名称<br>
"class": "com.chkj.urtc.URTCModule"//原生插件代码里自己创建的类 具体参考Uni-app原生插件开发<br>
}<br>
],<br>
"hooksClass": "com.chkj.urtc.URTCAppHookProxy", //uni-app原生插件配置代理跳转入口<br>
"integrateType": "aar",<br>
3、引入原生插件<br>
<img src="https://img2022.cnblogs.com/blog/490837/202206/490837-20220602151343734-1982659668.png"><br>
二、android studio打开下载好的sdk代码<br>
1、创建Module uniplugin_urtc 将sdk里的代码剪切到这个module里<br>
<img src="https://img2022.cnblogs.com/blog/490837/202206/490837-20220602151707859-1298270199.jpg"><br>
2、lib文件夹<br>
<img src="https://img2022.cnblogs.com/blog/490837/202206/490837-20220602152237182-1342387332.png"></p>
<p>3、uniplugin_urtc的build.gradle配置<br>
//plugins {<br>
//    id 'com.android.application'<br>
//}<br>
apply plugin: 'com.android.library'   //代表是个插件</p>
<p>android {<br>
compileSdkVersion 26<br>
defaultConfig {<br>
minSdkVersion rootProject.minSdkVersion<br>
compileSdkVersion rootProject.compileSdkVersion<br>
buildToolsVersion rootProject.buildToolsVersion<br>
targetSdkVersion rootProject.targetSdkVersion<br>
versionName rootProject.versionName<br>
versionCode 44<br>
ndk {<br>
abiFilters"armeabi-v7a", "arm64-v8a"<br>
}<br>
}</p>
<pre><code>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'
}
</code></pre>
<p>}<br>
repositories {<br>
flatDir {<br>
dirs 'libs'<br>
}<br>
}<br>
dependencies {<br>
compileOnly fileTree(include: ['<em>.jar', '</em>.aar'], dir: 'libs')<br>
//    implementation 'com.android.support:appcompat-v7:28.0.0'<br>
implementation 'com.android.support.constraint:constraint-layout:2.0.4'<br>
testImplementation 'junit:junit:4.13.2'<br>
androidTestImplementation 'com.android.support.test🏃1.0.2'<br>
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'</p>
<p>//    compileOnly 'com.android.support:appcompat-v7:28.0.0'<br>
//    compileOnly 'com.android.support:recyclerview-v7:28.0.0'<br>
//    compileOnly 'com.android.support:support-v4:28.0.0'<br>
implementation var.SupportV7<br>
implementation var.SupportV4<br>
implementation var.SupportRecyclerviewV7<br>
implementation 'com.squareup.okhttp3:okhttp:3.9.1'<br>
//bugly<br>
implementation 'com.tencent.bugly:crashreport:latest.release'<br>
implementation 'com.tencent.bugly:nativecrashreport:latest.release'<br>
implementation 'tv.danmaku.ijk.media:ijkplayer-java:0.8.8'<br>
implementation 'tv.danmaku.ijk.media:ijkplayer-armv7a:0.8.8'<br>
implementation 'tv.danmaku.ijk.media:ijkplayer-exo:0.8.8'</p>
<pre><code>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')
</code></pre>
<p>}<br>
4、URTCAppHookProxy<br>
package com.chkj.urtc;</p>
<p>import android.app.ActivityManager;<br>
import android.app.Application;<br>
import android.content.Context;<br>
import android.text.TextUtils;</p>
<p>import com.ucloudrtclib.sdkengine.UCloudRtcSdkEnv;<br>
import com.ucloudrtclib.sdkengine.define.UCloudRtcSdkLogLevel;</p>
<p>import io.dcloud.feature.uniapp.UniAppHookProxy;</p>
<p>public class URTCAppHookProxy implements UniAppHookProxy {</p>
<pre><code>@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;
}
</code></pre>
<p>}<br>
5、URTCModule<br>
package com.chkj.urtc;</p>
<p>import android.Manifest;<br>
import android.content.Context;<br>
import android.content.Intent;<br>
import android.content.pm.PackageManager;<br>
import android.os.Build;<br>
import android.os.Handler;<br>
import android.os.Looper;<br>
import android.text.TextUtils;<br>
import android.util.DisplayMetrics;<br>
import android.view.WindowManager;</p>
<p>import com.alibaba.fastjson.JSONObject;<br>
import com.chkj.urtc.Application.UCloudRtcApplication;<br>
import com.chkj.urtc.activity.ConnectActivity;<br>
import com.chkj.urtc.activity.RoomActivity;<br>
import com.chkj.urtc.common.Config;<br>
import com.chkj.urtc.utils.CommonUtils;<br>
import com.chkj.urtc.utils.PermissionUtils;<br>
import com.taobao.weex.annotation.JSMethod;<br>
import com.taobao.weex.bridge.JSCallback;<br>
import com.ucloudrtclib.sdkengine.UCloudRtcSdkEnv;<br>
import com.ucloudrtclib.sdkengine.define.UCloudRtcSdkMode;<br>
import com.ucloudrtclib.sdkengine.define.UCloudRtcSdkPushEncode;</p>
<p>import java.util.ArrayList;<br>
import java.util.List;<br>
import java.util.UUID;</p>
<p>import io.dcloud.feature.uniapp.common.UniModule;</p>
<p>public class URTCModule extends UniModule {</p>
<pre><code>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", "插件需要权限,请申请!");
            callback.invokeAndKeepAlive(result);
      }
      return;
    }
    //检测是否拥有文件写入权限
    if (!checkPermissions(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
      if (callback != null) {
            result.put("code", -1);
            result.put("msg", "插件需要权限,请申请!");
            callback.invokeAndKeepAlive(result);
      }
      return;
    }
    //检测是否拥有录音权限
    if (!checkPermissions(Manifest.permission.RECORD_AUDIO)) {
      if (callback != null) {
            result.put("code", -1);
            result.put("msg", "插件需要权限,请申请!");
            callback.invokeAndKeepAlive(result);
      }
      return;
    }
</code></pre>
<p>//      List<string> needPermissions = new ArrayList&lt;&gt;();<br>
//      needPermissions.add(Manifest.permission.CAMERA);<br>
//      needPermissions.add(Manifest.permission.RECORD_AUDIO);<br>
//      needPermissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);<br>
//      needPermissions.add(Manifest.permission.READ_PHONE_STATE);<br>
//<br>
//      if(Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.S){<br>
//            needPermissions.add(Manifest.permission.BLUETOOTH_SCAN);<br>
//            needPermissions.add(Manifest.permission.BLUETOOTH_CONNECT);<br>
//      }<br>
//      String[] requestPermissions = new String;<br>
//      needPermissions.toArray(requestPermissions);<br>
//      PermissionUtils.needsPermissions(mContext, requestPermissions);<br>
//      Thread thread = new Thread(new RoomActivity.CopyMixFileTask(this));<br>
//      thread.start();</string></p>
<pre><code>    // 配置参数
    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;

    // 跳转房间页面
</code></pre>
<p>//      final Intent intent = new Intent(mContext, RoomActivity.class);<br>
final Intent intent = new Intent(mContext, ConnectActivity.class);<br>
//      final Intent intent = new Intent(mContext, UCloudRtcApplication.class);</p>
<pre><code>    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() {
</code></pre>
<p>//                startActivity(intent);<br>
//                finish();<br>
mContext.startActivity(intent);<br>
}<br>
}, 500);</p>
<p>//      mContext.startActivity(new Intent(mContext, RoomActivity.class));<br>
//      mContext.startActivity(new Intent(mContext, ConnectActivity.class));</p>
<pre><code>}

private boolean checkPermissions(String permission) {
    boolean result = false;
    if (Build.VERSION.SDK_INT &gt;= 23) {
      int hasPer = mContext.checkSelfPermission(permission);
      if (hasPer == PackageManager.PERMISSION_GRANTED) {
            result = true;
      }
    } else {
      result = true;
    }
    return result;
}
</code></pre>
<p>}</p>
<p>三、sdk代码<br>
1、gradle配置<br>
apply plugin: 'com.android.application'//可运行app<br>
//apply plugin: 'com.android.library'</p>
<p>android {<br>
compileSdkVersion 26<br>
defaultConfig {<br>
applicationId "com.chkj.urtctest"<br>
minSdkVersion rootProject.minSdkVersion<br>
compileSdkVersion rootProject.compileSdkVersion<br>
buildToolsVersion rootProject.buildToolsVersion<br>
targetSdkVersion rootProject.targetSdkVersion<br>
versionName rootProject.versionName<br>
versionCode 44<br>
ndk {<br>
abiFilters"armeabi-v7a", "arm64-v8a"<br>
}<br>
}</p>
<p>//    lintOptions {<br>
//      checkReleaseBuilds false<br>
//      // Or, if you prefer, you can continue to check for errors in release builds,<br>
//      // but continue the build even when errors are found:<br>
//      abortOnError false<br>
//    }</p>
<pre><code>signingConfigs {
    config {
      storeFile file('****.jks')
      storePassword '****'
      keyAlias = '****'
      keyPassword '***'
    }
}


buildTypes {
</code></pre>
<p>//      release {<br>
//            minifyEnabled true<br>
//            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'<br>
//            signingConfig signingConfigs.release<br>
//      }<br>
//      debug {<br>
//            signingConfig signingConfigs.release<br>
//      }<br>
debug {<br>
signingConfig signingConfigs.config<br>
}<br>
release {<br>
signingConfig signingConfigs.config<br>
}<br>
}</p>
<p>//    sourceSets {<br>
//      main {<br>
//            jniLibs.srcDirs = ["/src/main/jniLibs"]<br>
//      }<br>
//    }<br>
//使用uniapp时,需复制下面代码<br>
/<em>代码开始</em>/<br>
aaptOptions {<br>
additionalParameters '--auto-add-overlay'<br>
//noCompress 'foo', 'bar'<br>
ignoreAssetsPattern "!.svn:!.git:.<em>:!CVS:!thumbs.db:!picasa.ini:!</em>.scc:<em>~"<br>
}<br>
/</em>代码结束*/<br>
compileOptions {<br>
sourceCompatibility = '1.8'<br>
targetCompatibility = '1.8'<br>
}<br>
repositories {<br>
flatDir {<br>
dirs 'libs'<br>
}<br>
}<br>
}</p>
<p>dependencies {<br>
//    implementation fileTree(include: ['*.jar'], dir: 'libs')<br>
//    implementation var.SupportV7<br>
//    implementation var.SupportV4<br>
//    implementation var.SupportRecyclerviewV7<br>
//    implementation 'com.squareup.okhttp3:okhttp:3.9.1'<br>
//    testImplementation 'junit:junit:4.12'<br>
//<br>
//    implementation (name: 'ucloudrtclib-2.1.4', ext: 'aar')<br>
//    implementation(name: 'libuvccamera-release', ext: 'aar')<br>
//    implementation(name: 'common-2.12.4', ext: 'aar')<br>
//    androidTestImplementation 'com.android.support.test🏃1.0.2'<br>
//    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'<br>
//    //bugly<br>
//    implementation 'com.tencent.bugly:crashreport:latest.release'<br>
//    implementation 'com.tencent.bugly:nativecrashreport:latest.release'<br>
//    implementation 'tv.danmaku.ijk.media:ijkplayer-java:0.8.8'<br>
//    implementation 'tv.danmaku.ijk.media:ijkplayer-armv7a:0.8.8'<br>
//    implementation 'tv.danmaku.ijk.media:ijkplayer-exo:0.8.8'</p>
<pre><code>implementation fileTree(include: ['*.jar', '*.aar'], dir: 'libs')
</code></pre>
<p>//    implementation 'com.android.support:support-v4:28.0.0'<br>
//    implementation 'com.android.support:appcompat-v7:28.0.0'<br>
//    implementation 'com.android.support:recyclerview-v7:28.0.0'<br>
implementation var.SupportV7<br>
implementation var.SupportV4<br>
implementation var.SupportRecyclerviewV7<br>
implementation 'com.facebook.fresco:fresco:1.13.0'<br>
implementation 'com.facebook.fresco:animated-gif:1.13.0'<br>
implementation 'com.github.bumptech.glide:glide:4.9.0'<br>
implementation 'com.alibaba:fastjson:1.1.46.android'</p>
<pre><code>implementation project(path: ':uniplugin_urtc')
</code></pre>
<p>}</p>
<p>2、创建主入口程序,继承 DCloudApplication<br>
<img src="https://img2022.cnblogs.com/blog/490837/202206/490837-20220602152702737-415735518.png"><br>
3、uni-app打包本地app资源,将代码放到app&gt;src&gt;main&gt;assets&gt;apps下,然后配置dcloud_uniplugins.json这个下面的<br>
<img src="https://img2022.cnblogs.com/blog/490837/202206/490837-20220602152942065-2084519063.png"><br>
四、测试运行app   可调试<br>
<img src="https://img2022.cnblogs.com/blog/490837/202206/490837-20220602153136278-1635151744.png"><br>
五、打包aar<br>
<img src="https://img2022.cnblogs.com/blog/490837/202206/490837-20220602153401038-1538997462.jpg"></p>
<p>以上记录只是成功后的总结记录,中间由于很多版本引用等问题非常痛苦,几经周折终于搞定,特此记录</p><br><br>
来源:https://www.cnblogs.com/frank2828/p/16337944.html
頁: [1]
查看完整版本: 记录:uni-app 开发原生组件视频通话的总结