Hanjie's Blog

一只有理想的羊驼

AR系统中存在虚拟影像空间和现实世界空间两个空间。在实际使用中,我们要求虚拟影像空间与现实世界空间能够对齐,使得虚拟物体与实际物体能够正确地叠加在一起。这需要我们对AR眼镜进行标定,获得传感器与光学屏幕,人眼之间的几何关系1

ar_glasses_calibration1

手机已经通过使用Magisk为App提供超级用户的权限,但是需要App主动向系统索求权限。下面我们通过使用一个Java Jar包,使得Unity生成的Android App能够获得root权限。

系统:Ubuntu Unity: 2020.3.13f1 Android Studio 3.6.1

首先,Android Studio中,菜单栏选择File->New->NewProject创建一个Empty Activity项目,Package nameMinimum SDK与Unity中的一致:

android_unity_root1
android_unity_root2

在菜单栏选择File->Project Structure->Modules->New Module,新建一个Android Library1,我们命名为GetRoot。注意Package nameMinimum SDK与Unity中的一致:

android_unity_root3

/home/luohanjie/Unity/Hub/Editor/2019.4.15f1/Editor/Data/PlaybackEngines/AndroidPlayer/Variations/il2cpp/Development/Classes下的classes.jar复制到Android项目Module文件下的libs文件夹下,如/home/luohanjie/Documents/Android Projects/Unity2Android/getroot/libs

/home/luohanjie/Unity/Hub/Editor/2019.4.15f1/Editor/Data/PlaybackEngines/AndroidPlayer/Source/com/unity3d下的UnityPlayerActivity.java复制到Android Studio中,Project栏目下Module name/src/main/java/Package name下:

android_unity_root4

Android Studio中,Project栏目下Module name/src/main/java/Package name新建一个Empty Activity

android_unity_root5
android_unity_root6

修改MainActivity.java2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package com.cvte.imagetracker;

import android.os.Bundle;

import java.io.DataOutputStream;

public class MainActivity extends UnityPlayerActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}

public void GetRoot() {
try {
//通过执行su产生一个具有root权限的进程
Process p = Runtime.getRuntime().exec("su");
//然后,在向这个进程的写入要执行的命令,即可达到以root权限执行命令:
DataOutputStream dos = new DataOutputStream(p.getOutputStream());
dos.writeBytes( "\n");//cmd命令可为空
dos.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
}

通过Android Studio中Project栏目下Module name/src/main/下打开AndroidManifest.xml文件并且修改,注意packageandroid:name的参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.cvte.imagetracker">

<application>
<!-- 这个android:name的值必须为包名+类名-->
<activity android:name="com.cvte.imagetracker.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>

通过Android Studio中Project栏目下Module name下打开build.gradle文件,修改minSdkVersiontargetSdkVersion,并在后面添加exportJar代码3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
apply plugin: 'com.android.library'

android {
compileSdkVersion 30
buildToolsVersion "30.0.2"

defaultConfig {
minSdkVersion 27
targetSdkVersion 27
versionCode 1
versionName "1.0"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles 'consumer-rules.pro'
}

buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}

}

dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'androidx.appcompat:appcompat:1.3.1'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
implementation files('libs/classes.jar')
}


task deleteOldJar(type: Delete) {
delete 'release/AndroidPlugin.jar'
}

//task to export contents as jar
task exportJar(type: Copy) {
from('build/intermediates/aar_main_jar/release/')
into('release/')
include('classes.jar')
///Rename the jar
rename('classes.jar', 'AndroidPlugin.jar')
}

exportJar.dependsOn(deleteOldJar, build)

Android Studio中执行Sync Project with Gradle Files,然后在右上角Gradle中Module name/Task/other/下执行exportJar

android_unity_root7

Project栏目下Module name/release中放有build生成的AndroidPlugin.jar。将AndroidPlugin.jarAndroidManifest.xml复制到Unity项目的Assets/Plugins/Android/目录下。使用解压缩软件打开AndroidPlugin.jar,并且删除BuildConfig.class

android_unity_root8

Unity中编写测试脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class test : MonoBehaviour
{
// Start is called before the first frame update
void Awake()
{
Debug.Log("==================");
AndroidJavaObject activity = new AndroidJavaObject ("com.cvte.imagetracker.MainActivity");
Debug.Log("GetRoot");
activity.Call("GetRoot");
Debug.Log("==================");
}

// Update is called once per frame
void Update()
{

}

}

Scripting Backend使用IL2CPP,并且注意Package Name和API Level与Java项目中一致。

android_unity_root2

打包,放到装有Magisk的手机上执行,启动的时候就会提示APP授予超级用户权限。

android_unity_root9

1
git clone https://github.com/saki4510t/UVCCamera.git

打开Android Studio,File->Open打开UVCCamera文件夹。

修改Project/build.gradle文件,修改以下部分:

1
2
3
4
5
6
7
8
9
10
ext {
supportLibVersion = '27.1.1' // variable that can be referenced to keep support libs consistent
commonLibVersion= '2.12.4'
versionBuildTool = '27.0.3'
versionCompiler = 27
versionTarget = 27
versionNameString = '1.0.0'
javaSourceCompatibility = JavaVersion.VERSION_1_8
javaTargetCompatibility = JavaVersion.VERSION_1_8
}

File->Project Structure,修改Android SDK location和Android NDK location,例如Android SDK location: /home/luohanjie/Android/SdkAndroid NDK location: /home/luohanjie/Android/Sdk/ndk/android-ndk-r21

修改Project/libuvccamera/src/main/jni/Application.mk,

1
2
3
4
APP_PLATFORM := android-21
APP_ABI := armeabi-v7a arm64-v8a x86_64
#APP_OPTIM := debug
APP_OPTIM := release

然后Build->Make Project。

0%