Unity2020以后版本调用aar包安装Apk
2022-01-12 本文已影响0人
Walk_In_Jar
由于unity调整,已经无法继承UnityPlayerActivity
已过时
所以更新一下以前的文章
使用as,新建工程Empty Activity 包名com.join.testar
image.png
修改MainActivity:
继承Activity,测试方法add
package com.join.testar;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.widget.Toast;
import androidx.core.content.FileProvider;
import java.io.File;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
}
public int Add(int a,int b){
return a+b;
}public void InstallApk(Context context, String apkPath){
File file = new File(apkPath);
Intent intent = new Intent(Intent.ACTION_VIEW);
if(Build.VERSION.SDK_INT>=24) { //Android 7.0及以上
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Uri apkUri = FileProvider.getUriForFile(context, context.getPackageName()+".fileprovider", file);
//对目标应用临时授权该Uri所代表的文件
intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
}else{
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
context.startActivity(intent);
}
/***
* 安装apk
* @param
* @param apkPath
*/
public void InstallApk2(String apkPath){
File file = new File(apkPath);
Intent intent = new Intent(Intent.ACTION_VIEW);
if(Build.VERSION.SDK_INT>=24) { //Android 7.0及以上
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Uri apkUri = FileProvider.getUriForFile(getActivity(), getActivity().getPackageName()+".fileprovider", file);
//对目标应用临时授权该Uri所代表的文件
intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
}else{
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
getActivity().startActivity(intent);
}
//也可以通过安卓方法获取context,此MainActivity没能生效
private Activity _unityActivity;
/**
* 获取unity项目的上下文
* @return
*/
Activity getActivity() {
if(null == _unityActivity) {
try {
Class<?> classtype = Class.forName("com.unity3d.player.UnityPlayer");
Activity activity = (Activity) classtype.getDeclaredField("currentActivity").get(classtype);
_unityActivity = activity;
} catch (ClassNotFoundException e) {
Log.d("Unity2Android", "getActivity: "+e);
} catch (IllegalAccessException e) {
Log.d("Unity2Android", "getActivity: "+e);
} catch (NoSuchFieldException e) {
Log.d("Unity2Android", "getActivity: "+e);
}
}
return _unityActivity;
}
/**
* 调用Unity的方法
* @param gameObjectName 调用的GameObject的名称
* @param functionName 方法名
* @param args 参数
* @return 调用是否成功
*/
public boolean callUnity(String gameObjectName, String functionName, String args){
try {
Class<?> classtype = Class.forName("com.unity3d.player.UnityPlayer");
Method method =classtype.getMethod("UnitySendMessage", String.class,String.class,String.class);
method.invoke(classtype,gameObjectName,functionName,args);
return true;
} catch (ClassNotFoundException e) {
Log.d("Unity2Android", "callUnity: "+e);
} catch (NoSuchMethodException e) {
Log.d("Unity2Android", "callUnity: "+e);
} catch (IllegalAccessException e) {
Log.d("Unity2Android", "callUnity: "+e);
} catch (InvocationTargetException e) {
Log.d("Unity2Android", "callUnity: "+e);
}
return false;
}
}
project视图下删除选中文件夹,
image.png
values文件夹下的xml内容都可以删除
image.png
image.png
image.png
res文件夹下新建xml目录、filepaths.xml
image.png
filepaths文件内容
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name="external_storage_root"
path="." />
<files-path
name="files-path"
path="." />
<cache-path
name="cache-path"
path="." />
<!--/storage/emulated/0/Android/data/...-->
<external-files-path
name="external_file_path"
path="." />
<!--代表app 外部存储区域根目录下的文件 Context.getExternalCacheDir目录下的目录-->
<external-cache-path
name="external_cache_path"
path="." />
<!--配置root-path。这样子可以读取到sd卡和一些应用分身的目录,否则微信分身保存的图片,就会导致 java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/999/tencent/MicroMsg/WeiXin/export1544062754693.jpg,在小米6的手机上微信分身有这个crash,华为没有
-->
<root-path
name="root-path"
path="" />
</paths>
修改AndroidManifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.join.testar">
<application
android:allowBackup="true">
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
</provider>
</application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.REPLACE_EXISTING_PACKAGE"/>
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
</manifest>
目的是添加fileprovider 声明读写目录、相关权限
修改build.grade
plugins {
id 'com.android.library'//改为library输出
}
android {
compileSdk 30
defaultConfig {
// applicationId "com.join.testar"//注释
minSdk 21
targetSdk 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.3.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
// testImplementation 'junit:junit:4.+'
// androidTestImplementation 'androidx.test.ext:junit:1.1.2'
// androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}
新建class第三方类
image.png
JavaCTest.java
package com.join.testar;
import android.content.Context;
public class JavaCTest {
private static JavaCTest instance;
public static JavaCTest Instance(){
if(instance==null)
instance=new JavaCTest();
return instance;
}
public int Sub(int a,int b){
return a-b;
}
}
as工程施工完毕
sync一下,就可以build输出了
image.png
找到输出arr文件app-debug.aar
image.png
image.png
复制到Unity的 Assets/Plugins/Android目录下
unity中设置自定义gradle
image.png
如下修改添加androidx支持
android.useAndroidX=true
android.enableJetifier=true
image.png
image.png
allprojects { repositories { mavenCentral() }}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.2.0'
**DEPS**}
unity代码部分
新建mono脚本
编写代码调用MainActivity中的方法
AndroidJavaObject Main = new AndroidJavaObject("com.join.testar.MainActivity");
int s = Main.Call<int>("Add", 2, 8);
调用javactest中的方法
AndroidJavaObject jc = new AndroidJavaObject("com.join.testar.JavaCTest");
var jo = jc.CallStatic<AndroidJavaObject>("Instance");
int s = jo.Call<int>("Sub", 3, 2);
可以打包运行看是否调用到了
安装apk
首先是下载apk到Application.persistentDataPath 目录
string remote = "http://192.168.1.1:5569/Root/3.apk";
string down = Application.persistentDataPath + "/3.apk";
UnityWebRequest request = UnityWebRequest.Get(remote);
yield return request.SendWebRequest();
byte[] d = request.downloadHandler.data;
File.WriteAllBytes(down, d);
//调用安卓方法
AndroidJavaObject activity = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject context = activity.GetStatic<AndroidJavaObject>("currentActivity");
string downapk = Application.persistentDataPath + "/3.apk";
AndroidJavaObject Main = new AndroidJavaObject("com.join.testar.MainActivity");
Main.Call("InstallApk", context, downapk);
或
Main.Call("InstallApk2", downapk);
至此完毕
区别就是需要传入获取到的context