refactor name
This commit is contained in:
parent
a1c05b78ec
commit
9b43aaac5d
|
|
@ -1,18 +1,18 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.storm.wind.xposed">
|
||||
package="com.storm.wind.tester">
|
||||
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
|
||||
<application
|
||||
android:name=".XposedTestApplication"
|
||||
android:name="org.lsposed.lspatch.tester.XposedTestApplication"
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/sample_app_title"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true">
|
||||
<activity android:name=".MainActivity">
|
||||
<activity android:name="org.lsposed.lspatch.tester.MainActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package com.wind.xposed.entry;
|
||||
package org.lsposed.lspatch.loader;
|
||||
|
||||
import static android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE;
|
||||
import static com.wind.xposed.entry.LSPLoader.initAndLoadModules;
|
||||
import static org.lsposed.lspatch.loader.LSPLoader.initAndLoadModules;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
|
|
@ -11,9 +11,9 @@ import android.os.Build;
|
|||
import android.os.IBinder;
|
||||
import android.os.Parcel;
|
||||
|
||||
import com.wind.xposed.entry.util.FileUtils;
|
||||
import com.wind.xposed.entry.util.XLog;
|
||||
import com.wind.xposed.entry.util.XpatchUtils;
|
||||
import org.lsposed.lspatch.loader.util.FileUtils;
|
||||
import org.lsposed.lspatch.loader.util.XLog;
|
||||
import org.lsposed.lspatch.loader.util.XpatchUtils;
|
||||
|
||||
import org.lsposed.lspd.yahfa.hooker.YahfaHooker;
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.wind.xposed.entry;
|
||||
package org.lsposed.lspatch.loader;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
|
|
@ -11,9 +11,9 @@ import android.text.TextUtils;
|
|||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
|
||||
import com.wind.xposed.entry.util.FileUtils;
|
||||
import com.wind.xposed.entry.util.XLog;
|
||||
import com.wind.xposed.entry.util.XpatchUtils;
|
||||
import org.lsposed.lspatch.loader.util.FileUtils;
|
||||
import org.lsposed.lspatch.loader.util.XLog;
|
||||
import org.lsposed.lspatch.loader.util.XpatchUtils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.wind.xposed.entry.util;
|
||||
package org.lsposed.lspatch.loader.util;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.Context;
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
package com.wind.xposed.entry.util;
|
||||
package org.lsposed.lspatch.loader.util;
|
||||
|
||||
|
||||
import com.storm.wind.xposed.BuildConfig;
|
||||
import com.storm.wind.tester.BuildConfig;
|
||||
|
||||
public class XLog {
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.wind.xposed.entry.util;
|
||||
package org.lsposed.lspatch.loader.util;
|
||||
|
||||
import android.app.ActivityThread;
|
||||
import android.content.Context;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.storm.wind.xposed;
|
||||
package org.lsposed.lspatch.tester;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
|
|
@ -6,6 +6,8 @@ import android.os.Bundle;
|
|||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.storm.wind.tester.R;
|
||||
|
||||
import de.robv.android.xposed.XC_MethodHook;
|
||||
import de.robv.android.xposed.XposedHelpers;
|
||||
|
||||
|
|
@ -1,10 +1,9 @@
|
|||
package com.storm.wind.xposed;
|
||||
|
||||
import static com.wind.xposed.entry.LSPLoader.initAndLoadModules;
|
||||
package org.lsposed.lspatch.tester;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
|
||||
import org.lsposed.lspatch.loader.LSPLoader;
|
||||
import org.lsposed.lspd.yahfa.hooker.YahfaHooker;
|
||||
|
||||
import de.robv.android.xposed.XposedInit;
|
||||
|
|
@ -20,6 +19,6 @@ public class XposedTestApplication extends Application {
|
|||
System.loadLibrary("lspd");
|
||||
YahfaHooker.init();
|
||||
XposedInit.startsSystemServer = false;
|
||||
initAndLoadModules();
|
||||
LSPLoader.initAndLoadModules();
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".MainActivity">
|
||||
tools:context="org.lsposed.lspatch.tester.MainActivity">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/msg"
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ jar {
|
|||
baseName = "lspatch"
|
||||
destinationDirectory = new File("$rootProject.projectDir/out")
|
||||
manifest {
|
||||
attributes 'Main-Class': 'com.storm.wind.xpatch.MainCommand'
|
||||
attributes 'Main-Class': 'org.lsposed.patch.LSPatch'
|
||||
}
|
||||
dependsOn configurations.runtimeClasspath
|
||||
from {
|
||||
|
|
|
|||
|
|
@ -1,241 +0,0 @@
|
|||
package com.storm.wind.xpatch;
|
||||
|
||||
import static org.apache.commons.io.FileUtils.copyFile;
|
||||
|
||||
import com.storm.wind.xpatch.base.BaseCommand;
|
||||
import com.storm.wind.xpatch.task.BuildAndSignApkTask;
|
||||
import com.storm.wind.xpatch.task.SaveApkSignatureTask;
|
||||
import com.storm.wind.xpatch.task.SaveOriginalApplicationNameTask;
|
||||
import com.storm.wind.xpatch.task.SoAndDexCopyTask;
|
||||
import com.storm.wind.xpatch.util.FileUtils;
|
||||
import com.storm.wind.xpatch.util.ManifestParser;
|
||||
import com.wind.meditor.core.FileProcesser;
|
||||
import com.wind.meditor.property.AttributeItem;
|
||||
import com.wind.meditor.property.ModificationProperty;
|
||||
import com.wind.meditor.utils.NodeValue;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class MainCommand extends BaseCommand {
|
||||
|
||||
private String apkPath;
|
||||
|
||||
private String unzipApkFilePath;
|
||||
|
||||
@Opt(opt = "o", longOpt = "output", description = "output .apk file, default is " +
|
||||
"$source_apk_dir/[file-name]-xposed-signed.apk", argName = "out-apk-file")
|
||||
private String output;
|
||||
|
||||
@Opt(opt = "f", longOpt = "force", hasArg = false, description = "force overwrite")
|
||||
private boolean forceOverwrite = false;
|
||||
|
||||
@Opt(opt = "pn", longOpt = "proxyname", description = "special proxy app name with full dot path", argName = "proxy app name")
|
||||
private String proxyname = "com.wind.xposed.entry.LSPApplication";
|
||||
|
||||
@Opt(opt = "d", longOpt = "debuggable", description = "set 1 to make the app debuggable = true, " +
|
||||
"set 0 to make the app debuggable = false", argName = "0 or 1")
|
||||
private int debuggable = -1; // 0: debuggable = false 1: debuggable = true
|
||||
|
||||
private int dexFileCount = 0;
|
||||
|
||||
private static final String UNZIP_APK_FILE_NAME = "apk-unzip-files";
|
||||
|
||||
private List<Runnable> mXpatchTasks = new ArrayList<>();
|
||||
|
||||
public static void main(String... args) {
|
||||
new MainCommand().doMain(args);
|
||||
}
|
||||
|
||||
static public void fuckIfFail(boolean b) {
|
||||
if (!b) {
|
||||
throw new IllegalStateException("wtf", new Throwable("DUMPBT"));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doCommandLine() throws IOException {
|
||||
if (remainingArgs.length != 1) {
|
||||
if (remainingArgs.length == 0) {
|
||||
System.out.println("Please choose one apk file you want to process. ");
|
||||
}
|
||||
if (remainingArgs.length > 1) {
|
||||
System.out.println("This tool can only used with one apk file.");
|
||||
}
|
||||
usage();
|
||||
return;
|
||||
}
|
||||
|
||||
apkPath = remainingArgs[0];
|
||||
|
||||
File srcApkFile = new File(apkPath);
|
||||
|
||||
if (!srcApkFile.exists()) {
|
||||
System.out.println("The source apk file not exsit, please choose another one. " +
|
||||
"current apk file is = " + apkPath);
|
||||
return;
|
||||
}
|
||||
|
||||
String currentDir = new File(".").getAbsolutePath();
|
||||
System.out.println("currentDir: " + currentDir);
|
||||
System.out.println("apkPath: " + apkPath);
|
||||
|
||||
if (output == null || output.length() == 0) {
|
||||
output = getBaseName(apkPath) + "-xposed-signed.apk";
|
||||
}
|
||||
|
||||
File outputFile = new File(output);
|
||||
if (outputFile.exists() && !forceOverwrite) {
|
||||
System.err.println(output + " exists, use --force to overwrite");
|
||||
usage();
|
||||
return;
|
||||
}
|
||||
|
||||
String outputApkFileParentPath = outputFile.getParent();
|
||||
if (outputApkFileParentPath == null) {
|
||||
String absPath = outputFile.getAbsolutePath();
|
||||
int index = absPath.lastIndexOf(File.separatorChar);
|
||||
outputApkFileParentPath = absPath.substring(0, index);
|
||||
}
|
||||
|
||||
System.out.println("output apk path: " + output);
|
||||
|
||||
String apkFileName = getBaseName(srcApkFile);
|
||||
|
||||
String tempFilePath = outputApkFileParentPath + File.separator +
|
||||
currentTimeStr() + "-tmp" + File.separator;
|
||||
|
||||
unzipApkFilePath = tempFilePath + apkFileName + "-" + UNZIP_APK_FILE_NAME + File.separator;
|
||||
|
||||
System.out.println("outputApkFileParentPath: " + outputApkFileParentPath);
|
||||
System.out.println("unzipApkFilePath = " + unzipApkFilePath);
|
||||
|
||||
// save the apk original signature info, to support crach signature.
|
||||
new SaveApkSignatureTask(apkPath, unzipApkFilePath).run();
|
||||
|
||||
long currentTime = System.currentTimeMillis();
|
||||
FileUtils.decompressZip(apkPath, unzipApkFilePath);
|
||||
|
||||
System.out.println("decompress apk cost time: " + (System.currentTimeMillis() - currentTime) + "ms");
|
||||
|
||||
// Get the dex count in the apk zip file
|
||||
dexFileCount = findDexFileCount(unzipApkFilePath);
|
||||
|
||||
System.out.println("dexFileCount: " + dexFileCount);
|
||||
|
||||
String manifestFilePath = unzipApkFilePath + "AndroidManifest.xml";
|
||||
|
||||
currentTime = System.currentTimeMillis();
|
||||
|
||||
// parse the app main application full name from the manifest file
|
||||
ManifestParser.Pair pair = ManifestParser.parseManifestFile(manifestFilePath);
|
||||
String applicationName = null;
|
||||
if (pair != null && pair.applicationName != null) {
|
||||
applicationName = pair.applicationName;
|
||||
}
|
||||
|
||||
System.out.println("Get application name cost time: " + (System.currentTimeMillis() - currentTime) + "ms");
|
||||
System.out.println("Get the application name: " + applicationName);
|
||||
|
||||
// modify manifest
|
||||
File manifestFile = new File(manifestFilePath);
|
||||
String manifestFilePathNew = unzipApkFilePath + "AndroidManifest" + "-" + currentTimeStr() + ".xml";
|
||||
File manifestFileNew = new File(manifestFilePathNew);
|
||||
fuckIfFail(manifestFile.renameTo(manifestFileNew));
|
||||
|
||||
modifyManifestFile(manifestFilePathNew, manifestFilePath, applicationName);
|
||||
|
||||
// new manifest may not exist
|
||||
if (manifestFile.exists() && manifestFile.length() > 0) {
|
||||
fuckIfFail(manifestFileNew.delete());
|
||||
}
|
||||
else {
|
||||
fuckIfFail(manifestFileNew.renameTo(manifestFile));
|
||||
}
|
||||
|
||||
// save original main application name to asset file
|
||||
if (isNotEmpty(applicationName)) {
|
||||
mXpatchTasks.add(new SaveOriginalApplicationNameTask(applicationName, unzipApkFilePath));
|
||||
}
|
||||
|
||||
// copy xposed so and dex files into the unzipped apk
|
||||
mXpatchTasks.add(new SoAndDexCopyTask(dexFileCount, unzipApkFilePath));
|
||||
|
||||
// compress all files into an apk and then sign it.
|
||||
mXpatchTasks.add(new BuildAndSignApkTask(true, unzipApkFilePath, output));
|
||||
|
||||
// copy origin apk to assets
|
||||
// convenient to bypass some check like CRC
|
||||
copyFile(srcApkFile, new File(unzipApkFilePath, "assets/origin_apk.bin"));
|
||||
|
||||
// excute these tasks
|
||||
for (Runnable executor : mXpatchTasks) {
|
||||
currentTime = System.currentTimeMillis();
|
||||
executor.run();
|
||||
|
||||
System.out.println(executor.getClass().getSimpleName() + " cost time: "
|
||||
+ (System.currentTimeMillis() - currentTime) + "ms");
|
||||
}
|
||||
|
||||
System.out.println("Output APK: " + output);
|
||||
}
|
||||
|
||||
private void modifyManifestFile(String filePath, String dstFilePath, String originalApplicationName) {
|
||||
ModificationProperty property = new ModificationProperty();
|
||||
boolean modifyEnabled = false;
|
||||
|
||||
if (debuggable >= 0) {
|
||||
modifyEnabled = true;
|
||||
property.addApplicationAttribute(new AttributeItem(NodeValue.Application.DEBUGGABLE, debuggable != 0));
|
||||
}
|
||||
|
||||
property.addApplicationAttribute(new AttributeItem("extractNativeLibs", true));
|
||||
|
||||
modifyEnabled = true;
|
||||
property.addApplicationAttribute(new AttributeItem(NodeValue.Application.NAME, proxyname));
|
||||
|
||||
FileProcesser.processManifestFile(filePath, dstFilePath, property);
|
||||
}
|
||||
|
||||
private int findDexFileCount(String unzipApkFilePath) {
|
||||
File zipfileRoot = new File(unzipApkFilePath);
|
||||
if (!zipfileRoot.exists()) {
|
||||
return 0;
|
||||
}
|
||||
File[] childFiles = zipfileRoot.listFiles();
|
||||
if (childFiles == null || childFiles.length == 0) {
|
||||
return 0;
|
||||
}
|
||||
int count = 0;
|
||||
for (File file : childFiles) {
|
||||
String fileName = file.getName();
|
||||
if (Pattern.matches("classes.*\\.dex", fileName)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
// Use the current timestamp as the name of the build file
|
||||
@SuppressWarnings("SimpleDateFormat")
|
||||
private String currentTimeStr() {
|
||||
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
|
||||
return df.format(new Date());
|
||||
}
|
||||
|
||||
private String[] getXposedModules(String modules) {
|
||||
if (modules == null || modules.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return modules.split(File.pathSeparator);
|
||||
}
|
||||
|
||||
private static boolean isNotEmpty(String str) {
|
||||
return str != null && !str.isEmpty();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,241 @@
|
|||
package org.lsposed.patch;
|
||||
|
||||
public class LSPatch {
|
||||
import static org.apache.commons.io.FileUtils.copyFile;
|
||||
|
||||
import com.wind.meditor.core.FileProcesser;
|
||||
import com.wind.meditor.property.AttributeItem;
|
||||
import com.wind.meditor.property.ModificationProperty;
|
||||
import com.wind.meditor.utils.NodeValue;
|
||||
|
||||
import org.lsposed.patch.base.BaseCommand;
|
||||
import org.lsposed.patch.task.BuildAndSignApkTask;
|
||||
import org.lsposed.patch.task.SaveApkSignatureTask;
|
||||
import org.lsposed.patch.task.SaveOriginalApplicationNameTask;
|
||||
import org.lsposed.patch.task.SoAndDexCopyTask;
|
||||
import org.lsposed.patch.util.FileUtils;
|
||||
import org.lsposed.patch.util.ManifestParser;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class LSPatch extends BaseCommand {
|
||||
private String apkPath;
|
||||
|
||||
private String unzipApkFilePath;
|
||||
|
||||
@Opt(opt = "o", longOpt = "output", description = "output .apk file, default is " +
|
||||
"$source_apk_dir/[file-name]-xposed-signed.apk", argName = "out-apk-file")
|
||||
private String output;
|
||||
|
||||
@Opt(opt = "f", longOpt = "force", hasArg = false, description = "force overwrite")
|
||||
private boolean forceOverwrite = false;
|
||||
|
||||
@Opt(opt = "pn", longOpt = "proxyname", description = "special proxy app name with full dot path", argName = "proxy app name")
|
||||
private String proxyname = "com.wind.xposed.entry.LSPApplication";
|
||||
|
||||
@Opt(opt = "d", longOpt = "debuggable", description = "set 1 to make the app debuggable = true, " +
|
||||
"set 0 to make the app debuggable = false", argName = "0 or 1")
|
||||
private int debuggable = -1; // 0: debuggable = false 1: debuggable = true
|
||||
|
||||
private int dexFileCount = 0;
|
||||
|
||||
private static final String UNZIP_APK_FILE_NAME = "apk-unzip-files";
|
||||
|
||||
private List<Runnable> mXpatchTasks = new ArrayList<>();
|
||||
|
||||
public static void main(String... args) {
|
||||
new LSPatch().doMain(args);
|
||||
}
|
||||
|
||||
static public void fuckIfFail(boolean b) {
|
||||
if (!b) {
|
||||
throw new IllegalStateException("wtf", new Throwable("DUMPBT"));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doCommandLine() throws IOException {
|
||||
if (remainingArgs.length != 1) {
|
||||
if (remainingArgs.length == 0) {
|
||||
System.out.println("Please choose one apk file you want to process. ");
|
||||
}
|
||||
if (remainingArgs.length > 1) {
|
||||
System.out.println("This tool can only used with one apk file.");
|
||||
}
|
||||
usage();
|
||||
return;
|
||||
}
|
||||
|
||||
apkPath = remainingArgs[0];
|
||||
|
||||
File srcApkFile = new File(apkPath);
|
||||
|
||||
if (!srcApkFile.exists()) {
|
||||
System.out.println("The source apk file not exsit, please choose another one. " +
|
||||
"current apk file is = " + apkPath);
|
||||
return;
|
||||
}
|
||||
|
||||
String currentDir = new File(".").getAbsolutePath();
|
||||
System.out.println("currentDir: " + currentDir);
|
||||
System.out.println("apkPath: " + apkPath);
|
||||
|
||||
if (output == null || output.length() == 0) {
|
||||
output = getBaseName(apkPath) + "-xposed-signed.apk";
|
||||
}
|
||||
|
||||
File outputFile = new File(output);
|
||||
if (outputFile.exists() && !forceOverwrite) {
|
||||
System.err.println(output + " exists, use --force to overwrite");
|
||||
usage();
|
||||
return;
|
||||
}
|
||||
|
||||
String outputApkFileParentPath = outputFile.getParent();
|
||||
if (outputApkFileParentPath == null) {
|
||||
String absPath = outputFile.getAbsolutePath();
|
||||
int index = absPath.lastIndexOf(File.separatorChar);
|
||||
outputApkFileParentPath = absPath.substring(0, index);
|
||||
}
|
||||
|
||||
System.out.println("output apk path: " + output);
|
||||
|
||||
String apkFileName = getBaseName(srcApkFile);
|
||||
|
||||
String tempFilePath = outputApkFileParentPath + File.separator +
|
||||
currentTimeStr() + "-tmp" + File.separator;
|
||||
|
||||
unzipApkFilePath = tempFilePath + apkFileName + "-" + UNZIP_APK_FILE_NAME + File.separator;
|
||||
|
||||
System.out.println("outputApkFileParentPath: " + outputApkFileParentPath);
|
||||
System.out.println("unzipApkFilePath = " + unzipApkFilePath);
|
||||
|
||||
// save the apk original signature info, to support crach signature.
|
||||
new SaveApkSignatureTask(apkPath, unzipApkFilePath).run();
|
||||
|
||||
long currentTime = System.currentTimeMillis();
|
||||
FileUtils.decompressZip(apkPath, unzipApkFilePath);
|
||||
|
||||
System.out.println("decompress apk cost time: " + (System.currentTimeMillis() - currentTime) + "ms");
|
||||
|
||||
// Get the dex count in the apk zip file
|
||||
dexFileCount = findDexFileCount(unzipApkFilePath);
|
||||
|
||||
System.out.println("dexFileCount: " + dexFileCount);
|
||||
|
||||
String manifestFilePath = unzipApkFilePath + "AndroidManifest.xml";
|
||||
|
||||
currentTime = System.currentTimeMillis();
|
||||
|
||||
// parse the app main application full name from the manifest file
|
||||
ManifestParser.Pair pair = ManifestParser.parseManifestFile(manifestFilePath);
|
||||
String applicationName = null;
|
||||
if (pair != null && pair.applicationName != null) {
|
||||
applicationName = pair.applicationName;
|
||||
}
|
||||
|
||||
System.out.println("Get application name cost time: " + (System.currentTimeMillis() - currentTime) + "ms");
|
||||
System.out.println("Get the application name: " + applicationName);
|
||||
|
||||
// modify manifest
|
||||
File manifestFile = new File(manifestFilePath);
|
||||
String manifestFilePathNew = unzipApkFilePath + "AndroidManifest" + "-" + currentTimeStr() + ".xml";
|
||||
File manifestFileNew = new File(manifestFilePathNew);
|
||||
fuckIfFail(manifestFile.renameTo(manifestFileNew));
|
||||
|
||||
modifyManifestFile(manifestFilePathNew, manifestFilePath, applicationName);
|
||||
|
||||
// new manifest may not exist
|
||||
if (manifestFile.exists() && manifestFile.length() > 0) {
|
||||
fuckIfFail(manifestFileNew.delete());
|
||||
}
|
||||
else {
|
||||
fuckIfFail(manifestFileNew.renameTo(manifestFile));
|
||||
}
|
||||
|
||||
// save original main application name to asset file
|
||||
if (isNotEmpty(applicationName)) {
|
||||
mXpatchTasks.add(new SaveOriginalApplicationNameTask(applicationName, unzipApkFilePath));
|
||||
}
|
||||
|
||||
// copy xposed so and dex files into the unzipped apk
|
||||
mXpatchTasks.add(new SoAndDexCopyTask(dexFileCount, unzipApkFilePath));
|
||||
|
||||
// compress all files into an apk and then sign it.
|
||||
mXpatchTasks.add(new BuildAndSignApkTask(true, unzipApkFilePath, output));
|
||||
|
||||
// copy origin apk to assets
|
||||
// convenient to bypass some check like CRC
|
||||
copyFile(srcApkFile, new File(unzipApkFilePath, "assets/origin_apk.bin"));
|
||||
|
||||
// excute these tasks
|
||||
for (Runnable executor : mXpatchTasks) {
|
||||
currentTime = System.currentTimeMillis();
|
||||
executor.run();
|
||||
|
||||
System.out.println(executor.getClass().getSimpleName() + " cost time: "
|
||||
+ (System.currentTimeMillis() - currentTime) + "ms");
|
||||
}
|
||||
|
||||
System.out.println("Output APK: " + output);
|
||||
}
|
||||
|
||||
private void modifyManifestFile(String filePath, String dstFilePath, String originalApplicationName) {
|
||||
ModificationProperty property = new ModificationProperty();
|
||||
boolean modifyEnabled = false;
|
||||
|
||||
if (debuggable >= 0) {
|
||||
modifyEnabled = true;
|
||||
property.addApplicationAttribute(new AttributeItem(NodeValue.Application.DEBUGGABLE, debuggable != 0));
|
||||
}
|
||||
|
||||
property.addApplicationAttribute(new AttributeItem("extractNativeLibs", true));
|
||||
|
||||
modifyEnabled = true;
|
||||
property.addApplicationAttribute(new AttributeItem(NodeValue.Application.NAME, proxyname));
|
||||
|
||||
FileProcesser.processManifestFile(filePath, dstFilePath, property);
|
||||
}
|
||||
|
||||
private int findDexFileCount(String unzipApkFilePath) {
|
||||
File zipfileRoot = new File(unzipApkFilePath);
|
||||
if (!zipfileRoot.exists()) {
|
||||
return 0;
|
||||
}
|
||||
File[] childFiles = zipfileRoot.listFiles();
|
||||
if (childFiles == null || childFiles.length == 0) {
|
||||
return 0;
|
||||
}
|
||||
int count = 0;
|
||||
for (File file : childFiles) {
|
||||
String fileName = file.getName();
|
||||
if (Pattern.matches("classes.*\\.dex", fileName)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
// Use the current timestamp as the name of the build file
|
||||
@SuppressWarnings("SimpleDateFormat")
|
||||
private String currentTimeStr() {
|
||||
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
|
||||
return df.format(new Date());
|
||||
}
|
||||
|
||||
private String[] getXposedModules(String modules) {
|
||||
if (modules == null || modules.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return modules.split(File.pathSeparator);
|
||||
}
|
||||
|
||||
private static boolean isNotEmpty(String str) {
|
||||
return str != null && !str.isEmpty();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.storm.wind.xpatch.base;
|
||||
package org.lsposed.patch.base;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.OutputStreamWriter;
|
||||
|
|
@ -1,9 +1,10 @@
|
|||
package com.storm.wind.xpatch.task;
|
||||
package org.lsposed.patch.task;
|
||||
|
||||
import com.android.apksigner.ApkSignerTool;
|
||||
import com.storm.wind.xpatch.MainCommand;
|
||||
import com.storm.wind.xpatch.util.FileUtils;
|
||||
import com.storm.wind.xpatch.util.ShellCmdUtil;
|
||||
|
||||
import org.lsposed.patch.LSPatch;
|
||||
import org.lsposed.patch.util.FileUtils;
|
||||
import org.lsposed.patch.util.ShellCmdUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
|
|
@ -56,12 +57,12 @@ public class BuildAndSignApkTask implements Runnable {
|
|||
File signedApkFile = new File(signedApkPath);
|
||||
// delete unsigned apk file
|
||||
if (!keepUnsignedApkFile && unsignedApkFile.exists() && signedApkFile.exists() && signResult) {
|
||||
MainCommand.fuckIfFail(unsignedApkFile.delete());
|
||||
LSPatch.fuckIfFail(unsignedApkFile.delete());
|
||||
}
|
||||
|
||||
// delete the keystore file
|
||||
if (keyStoreFile.exists()) {
|
||||
MainCommand.fuckIfFail(keyStoreFile.delete());
|
||||
LSPatch.fuckIfFail(keyStoreFile.delete());
|
||||
}
|
||||
}
|
||||
catch (Exception err) {
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
package com.storm.wind.xpatch.task;
|
||||
package org.lsposed.patch.task;
|
||||
|
||||
import com.storm.wind.xpatch.util.ApkSignatureHelper;
|
||||
import org.lsposed.patch.util.ApkSignatureHelper;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.storm.wind.xpatch.task;
|
||||
package org.lsposed.patch.task;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
|
|
@ -1,11 +1,9 @@
|
|||
package com.storm.wind.xpatch.task;
|
||||
package org.lsposed.patch.task;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.storm.wind.xpatch.util;
|
||||
package org.lsposed.patch.util;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.security.cert.Certificate;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.storm.wind.xpatch.util;
|
||||
package org.lsposed.patch.util;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.storm.wind.xpatch.util;
|
||||
package org.lsposed.patch.util;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.storm.wind.xpatch.util;
|
||||
package org.lsposed.patch.util;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.storm.wind.xpatch.util;
|
||||
package org.lsposed.patch.util;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.Closeable;
|
||||
Loading…
Reference in New Issue