unity3调用Android 封装的声网SDK
1、环境版本
unity3D 编辑器 2020
Android Studio 4.2
2、创建Android library 工程
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1vW64Rl0-1646983827610)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220225100316193.png)]](https://img-blog.csdnimg.cn/d8a7222911e84933a2a571ff5287bdd8.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6IuP5omT5rC06Kej5ri0,size_20,color_FFFFFF,t_70,g_se,x_16)
3、unity3D 依赖包添加到工程libs下
依赖包的位置(unity 安装目录下):E:\Unity_install\2020.3.28f1c1\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Release\Classes
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5E4y30WG-1646983827611)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220225101545907.png)]](https://img-blog.csdnimg.cn/d4e09bebba5a4288b715de536c7fe50e.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6IuP5omT5rC06Kej5ri0,size_18,color_FFFFFF,t_70,g_se,x_16)
4、UnityPlayerActivity 添加到项目中
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UHMUAk3k-1646983827612)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220225101641470.png)]](https://img-blog.csdnimg.cn/d2e008d627724d2f96bf17f67a135fc7.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6IuP5omT5rC06Kej5ri0,size_20,color_FFFFFF,t_70,g_se,x_16)
添加到项目中
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eXJbngHx-1646983827612)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220225101720756.png)]](https://img-blog.csdnimg.cn/24108c663b6742bab2ea271117beaa0b.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6IuP5omT5rC06Kej5ri0,size_18,color_FFFFFF,t_70,g_se,x_16)
5、自定义Activity 继承 UnityPlayerActivity
注销掉 设置布局方法
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HTYLpxXU-1646983827613)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220225101816429.png)]](https://img-blog.csdnimg.cn/3dc4244ae9f345d591da59a388501bc2.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6IuP5omT5rC06Kej5ri0,size_20,color_FFFFFF,t_70,g_se,x_16)
6、清单文件设置
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.xyx.astounity">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<application>
<activity android:name="com.xyx.astounity.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
</activity>
</application>
</manifest>
7、build.gradle 添加 jar 脚本
task deleteOldJar(type: Delete) {
delete 'release/AndroidPlugin.jar'
}
task exportJar(type: Copy) {
from('build/intermediates/aar_main_jar/release/')
into('release/')
include('classes.jar')
rename('classes.jar', 'AndroidPlugin.jar')
}
exportJar.dependsOn(deleteOldJar, build)
8、集成 声网sdk
8.1 so库 添加到项目中
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8H9jrOVH-1646983827613)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220225102511333.png)]](https://img-blog.csdnimg.cn/e2b23852f4d94ba49207cebbd6a98ce9.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6IuP5omT5rC06Kej5ri0,size_20,color_FFFFFF,t_70,g_se,x_16)
8.2 声网jar 添加 libs 目录下
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3rkTYje9-1646983827614)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220225102610872.png)]](https://img-blog.csdnimg.cn/9f662991909f40e7bdffff562e40f150.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6IuP5omT5rC06Kej5ri0,size_20,color_FFFFFF,t_70,g_se,x_16)
8.4 编写 集成声网sdk的工具类
package com.xyx.astounity;
import android.app.Activity;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;
import io.agora.rtc.Constants;
import io.agora.rtc.IRtcEngineEventHandler;
import io.agora.rtc.RtcEngine;
public class VoiceUtils {
private String appKey="5c203ec6100d4f1bbbc79265a81ef0f0";
private String token="0065c203ec6100d4f1bbbc79265a81ef0f0IABoJ4pt255quepmrqcN+P+MzHNWvu489IlD6C43eOajEKDfQtYAAAAAEAAn2yw6p4gZYgEAAQC/iBli";
private String channel="demo";
private RtcEngine mRtcEngine;
private Handler handler=new Handler(Looper.getMainLooper());
private Context context;
public boolean isIsSpeak(){
return isSpeak;
}
public void initializeAgoraEngine(Context context){
try {
mRtcEngine = RtcEngine.create(context, appKey, mRtcEventHandler);
this.context=context;
int i = mRtcEngine.enableDeepLearningDenoise(true);
mRtcEngine.enableAudioVolumeIndication(100,3,true);
Log.e("zyb", "initializeAgoraEngine: "+i );
} catch (Exception e) {
throw new RuntimeException("NEED TO check rtc sdk init fatal error\n" + Log.getStackTraceString(e));
}
}
public void joinChannel() {
String accessToken = token;
if (TextUtils.equals(accessToken, "") || TextUtils.equals(accessToken, "#YOUR ACCESS TOKEN#")) {
accessToken = null;
}
mRtcEngine.setChannelProfile(Constants.CHANNEL_PROFILE_COMMUNICATION);
mRtcEngine.joinChannel(accessToken, channel, "Extra Optional Data", 0);
mRtcEngine.enableAudioVolumeIndication(50,3,true);
}
private final IRtcEngineEventHandler mRtcEventHandler = new IRtcEngineEventHandler() {
@Override
public void onUserOffline(final int uid, final int reason) {
}
@Override
public void onAudioVolumeIndication(AudioVolumeInfo[] speakers, int totalVolume) {
super.onAudioVolumeIndication(speakers, totalVolume);
if (speakers.length == 1) {
int uid = speakers[0].uid;
int vad = speakers[0].vad;
Log.e("zyb", "onAudioVolumeIndication: "+uid );
if (uid != 0 ) {
if (vad == 1) {
try {
isSpeak = true;
} catch (Exception e) {
e.printStackTrace();
}
} else {
isSpeak = false;
}
}
}else {
isSpeak=false;
}
}
@Override
public void onUserMuteAudio(final int uid, final boolean muted) {
handler.post(() -> Toast.makeText(context,"用户:"+uid +" \t 加入房间 ",Toast.LENGTH_SHORT).show());
}
};
public static volatile boolean isSpeak = false;
}
8.5 MainActivity中 提供方法给 unity 调用
public boolean isIsSpeak(){
if (voiceUtils==null){
Toast.makeText(this,"对象没有初始化",Toast.LENGTH_SHORT).show();
return false;
}
return voiceUtils.isIsSpeak();
}
public void initializeAgoraEngine(){
voiceUtils.initializeAgoraEngine(this);
}
public void joinChannel(){
if (voiceUtils==null){
Toast.makeText(this,"对象没有初始化",Toast.LENGTH_SHORT).show();
return;
}
voiceUtils.joinChannel();
}
9、jar 生成
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2LL0SRHf-1646983827614)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220225104501120.png)]](https://img-blog.csdnimg.cn/ea5bd0d1f8964d228b5fdd3c2e38b24b.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6IuP5omT5rC06Kej5ri0,size_20,color_FFFFFF,t_70,g_se,x_16)
生成 目录
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-daKBHxyt-1646983827614)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220225104524324.png)]](https://img-blog.csdnimg.cn/4018caf952324e768f09cf59d70104da.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6IuP5omT5rC06Kej5ri0,size_20,color_FFFFFF,t_70,g_se,x_16)
10、 unity中集成‘
10.1Assets 文件下 新建 Plugins 目录
10.2 AndroidPlugin.jar 放在 bin 目录下
10.3 声网so 库和jar 放在 libs目录下
10.4 清单文件放在Android目录下
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DeVPhpcy-1646983827615)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220225104847437.png)]](https://img-blog.csdnimg.cn/4d0381688f364549a9f1bd1596088c7f.png)
11、 unity 脚本中调用 android 提供的方法
unity的包名和Android的版本设置的和jar包的一样
初始化 声网sdk的脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
#if(UNITY_2018_3_OR_NEWER)
using UnityEngine.Android;
#endif
public class CallAndroid : MonoBehaviour
{
void Start()
{
Permission.RequestUserPermission("android.permission.RECORD_AUDIO");
#if (UNITY_2018_3_OR_NEWER)
if (Permission.HasUserAuthorizedPermission(Permission.Microphone))
{
}
else
{
Permission.RequestUserPermission(Permission.Microphone);
}
#endif
}
void Update()
{
}
private AndroidJavaClass jc;
private AndroidJavaObject jo;
private void OnGUI()
{
if (GUILayout.Button("Call Android",GUILayout.Width(200), GUILayout.Height(100)))
{
jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
jo = jc.GetStatic<AndroidJavaObject>("currentActivity");
int result =jo.Call<int>("add",1,2);
jo.Call("UnityCallAndroid");
}
if (GUILayout.Button("init", GUILayout.Width(200), GUILayout.Height(100)))
{
jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
jo = jc.GetStatic<AndroidJavaObject>("currentActivity");
jo.Call("initializeAgoraEngine");
}
if (GUILayout.Button("join", GUILayout.Width(200), GUILayout.Height(100)))
{
jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
jo = jc.GetStatic<AndroidJavaObject>("currentActivity");
jo.Call("joinChannel");
}
}
public void UnityMethod(string str)
{
Debug.Log("UnityMethod被调用,参数:" + str);
}
}
判断声网sdk VAD 脚本
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using UnityEngine;
public class Switch : MonoBehaviour
{
private AndroidJavaClass jc;
private AndroidJavaObject jo;
long currentTime=0;
GameObject a;
GameObject b;
void Start()
{
a = GameObject.Find("a_demo");
b = GameObject.Find("b");
}
bool flag=false;
[System.Obsolete]
void Update()
{
jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
jo = jc.GetStatic<AndroidJavaObject>("currentActivity");
bool isSpeek = jo.Call<bool>("isIsSpeak");
Debug.Log("isSpeek::::====" + isSpeek);
Thread.Sleep(300);
if (isSpeek)
{
a.SetActive(flag);
b.SetActive(!flag);
flag = !flag;
Debug.Log("-----" + flag);
}
else {
if (b.active)
{
b.SetActive(false);
a.SetActive(true);
flag = !flag;
}
}
}
}
12、参考 资料
https://www.cnblogs.com/Jason-c/p/6743224.html
https://blog.csdn.net/u014361280/article/details/107692986
https://www.kancloud.cn/hujunjob/unity/139595
|