手机已经通过使用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 name
和Minimum SDK
与Unity中的一致:
android_unity_root1
android_unity_root2
在菜单栏选择File->Project Structure->Modules->New Module
,新建一个Android Library
,我们命名为GetRoot。注意Package name
和Minimum 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.java:
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
文件并且修改,注意package
和android: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
文件,修改minSdkVersion
和targetSdkVersion
,并在后面添加exportJar
代码:
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.jar
和AndroidManifest.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