Unity Android App获取root权限

手机已经通过使用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 Library[1],我们命名为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.java[2]

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的参数:

<?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代码[1]

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中编写测试脚本:

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. https://blog.csdn.net/weixin_43271060/article/details/109512768

  2. https://blog.csdn.net/mChenys/article/details/86701272