custom server, r1 support finally works

This commit is contained in:
Meowster 2024-08-14 18:46:00 +02:00
parent 62258ee387
commit 71e41094eb
4 changed files with 66 additions and 33 deletions

View file

@ -1,13 +1,14 @@
# r1-apk-patcher # r1-apk-patcher
tool to patch a clean rabbit apk into a working one tool to patch a clean rabbit apk into a working one
To use this repo you need to download [nodeJS](https://nodejs.org/en/download/package-manager/current) and java. \
If anyone wants to make a fix for vision mode not working for many people, DM me on Discord, @meowstercatel (smali / java knowledge recommended ofc)
how to run: how to run:
1. download nodejs [here](https://nodejs.org/en/download/package-manager/current) 1. download nodeJS [here](https://nodejs.org/en/download/package-manager/current), and Java.
2. if you have your own apk that you want to patch, change it in settings.json 2. changing the settings
4. finally run `node index.js` 2.1 if you want to use the patched app with your r1, set "r1_mode" to true.
5. your patched apk will have the original filename and "_Patched" added to it. 2.2 if you have your own r1 IMEI that you'd want to use, put it in the imei value.
2.3 if you have your own rabbit backend set up, you can set the URL of it in the server_ip value. Example value: `ws://192.168.0.110:3000`
to run the apk you need to execute this command first (adb): `adb shell pm grant tech.rabbit.r1launcher.r1 android.permission.WRITE_SECURE_SETTINGS` 3. finally run `node index.js`
or in termux `pm grant tech.rabbit.r1launcher.r1 android.permission.WRITE_SECURE_SETTINGS` 4. your patched apk will have the original filename and "_Patched" added to it.
5. run a command to grant the r1 app the secure settings permission
5.1. adb command: `adb shell pm grant tech.rabbit.r1launcher.r1 android.permission.WRITE_SECURE_SETTINGS`
5.2 termux: (needs root in order to work): `pm grant tech.rabbit.r1launcher.r1 android.permission.WRITE_SECURE_SETTINGS`

View file

@ -3,18 +3,44 @@ const {functions} = require("./functions");
const {decomp, modifyFunc, replaceLib, build, replaceStringInManifest} = require("./utils"); const {decomp, modifyFunc, replaceLib, build, replaceStringInManifest} = require("./utils");
const settings = require("./settings.json"); const settings = require("./settings.json");
const decompName = settings.apkFileName; const decompName = "RabbitLauncher0517";
const base = `${decompName}_decompile_xml`; const base = `${decompName}_decompile_xml`;
const appVersion = "20240615.10-dirty"; const appVersion = "20240615.10-dirty";
decomp(); decomp();
if(settings.server_ip !== "") {
functions.functions.push({
location: "smali/classes/tech/rabbit/r1launcher/RLApp.smali",
code: [
"sget-object v0, Ltech/rabbit/r1launcher/wss/WebSocketManager;->INSTANCE:Ltech/rabbit/r1launcher/wss/WebSocketManager;",
`const-string v2, "${settings.serverIP}"`,
"invoke-virtual {v0, v2}, Ltech/rabbit/r1launcher/wss/WebSocketManager;->setRabbitServiceUrl(Ljava/lang/String;)V"
]
})
let file = fs.readFileSync(`./${base}/AndroidManifest.xml`).toString();
file = file.split("\n");
file.forEach(line => {
if(line.includes("<application")) {
const lineIndex = file.indexOf(line);
// +2 because 0 makes it so that it's behind the <application> tag
file.splice(lineIndex+2, 0, `android:usesCleartextTraffic="true"`);
}
})
fs.writeFileSync(`./${base}/AndroidManifest.xml`, file.join("\n"));
}
if(settings.r1_mode === true) {
functions.functions[3].code[5] = "const/16 p0, 0x50"
functions.functions[4].code[2] = "const/16 p0, 0x50"
}
functions.functions.forEach(func => { functions.functions.forEach(func => {
modifyFunc(`./${base}/`+func.location, func.code) modifyFunc(`./${base}/`+func.location, func.code)
}) })
replaceStringInManifest("android:versionName", `"${appVersion}"`) replaceStringInManifest("android:versionName", `${appVersion}`)
replaceLib("./libbase.so", "libbase.so"); replaceLib("./libbase.so", "libbase.so");
if(fs.existsSync(`./${decompName}_out.apk`)) fs.rmSync(`./${decompName}_out.apk`); if(fs.existsSync(`./${decompName}_out.apk`)) fs.rmSync(`./${decompName}_out.apk`);
@ -27,5 +53,7 @@ fs.renameSync(
`${decompName}_Patched.apk` `${decompName}_Patched.apk`
); );
fs.rmSync(`./${base}`, { recursive: true, force: true }); fs.rmdirSync(base, { force: true, recursive: true});
fs.rmSync(`${base}_out.apk`); fs.rmSync(`${base}_out.apk`);
console.log(`Your patched apk filename is: ${decompName}_Patched.apk !`)

View file

@ -1,4 +1,5 @@
{ {
"apkFileName": "RabbitLauncher0517", "r1_mode": false,
"imei": "" "imei": "",
"server_ip": ""
} }

View file

@ -1,7 +1,7 @@
const { execSync } = require("child_process"); const { execSync } = require("child_process");
const fs = require("fs"); const fs = require("fs");
const settings = require("./settings.json"); const decompName = "RabbitLauncher0517";
const decompName = settings.apkFileName; const base = `${decompName}_decompile_xml`;
//these next 2 functions are taken from //these next 2 functions are taken from
//https://annabelsandford.github.io/rabbit-r1-imeigen/imei_check_v1.html //https://annabelsandford.github.io/rabbit-r1-imeigen/imei_check_v1.html
@ -87,31 +87,34 @@ function modifyFunc(path, modifyWith) {
function replaceLib(newLibLocation, oldLib) { function replaceLib(newLibLocation, oldLib) {
fs.copyFileSync( fs.copyFileSync(
newLibLocation, newLibLocation,
`./${decompName}_decompile_xml/root/lib/arm64-v8a/${oldLib}` `./${base}/root/lib/arm64-v8a/${oldLib}`
); );
} }
function replaceStringInManifest(name, value) { function replaceStringInManifest(name, value) {
//replaces every instance of the "name" keyword const file = fs.readFileSync(`${base}/AndroidManifest.xml`);
const manifest = `./${decompName}_decompile_xml/AndroidManifest.xml`; let content = file.toString()
const data = fs.readFileSync(manifest, "utf-8") content = content.split("\n");
let arr = data.split(" "); content.forEach((line) => {
for (let i = 0; i < arr.length; i++) { const lineIndex = content.indexOf(line);
let line = arr[i]; if (line.includes(name)) {
if(line.includes(name)) { console.log(line)
line = `${name}=${value}` line = line.split(`"`);
} line[1] = value;
} line = line.join(`"`);
fs.writeFileSync(manifest, arr.join(" "), "utf-8") content[lineIndex] = line;
}
});
content = content.join("\n");
fs.writeFileSync(`${base}/AndroidManifest.xml`, content);
} }
function build() { function build() {
execSync(`java -jar APKEditor.jar b -i ${decompName}_decompile_xml`); execSync(`java -jar APKEditor.jar b -i ${base}`);
execSync( execSync(
`java -jar uber-apk-signer-1.2.1.jar -a ${decompName}_decompile_xml_out.apk` `java -jar uber-apk-signer-1.2.1.jar -a ${base}_out.apk`
); );
} }
module.exports = {generateIMEI, decomp, modifyFunc, replaceLib, build, replaceStringInManifest} module.exports = { generateIMEI, decomp, modifyFunc, replaceLib, build, replaceStringInManifest }