feat: add output log to media
底層實現了日誌檔案寫入。為管理器新增了 outputLog 選項,可以將日誌輸出到 Android/media 目錄。
This commit is contained in:
parent
02c9d34f5a
commit
7613e7de10
|
|
@ -109,6 +109,9 @@ jobs:
|
|||
echo 'android.native.buildOutput=verbose'
|
||||
} >> gradle.properties
|
||||
|
||||
- name: Grant execution permission to gradlew
|
||||
run: chmod +x gradlew
|
||||
|
||||
- name: Build dependencies with Gradle
|
||||
working-directory: libxposed
|
||||
run: |
|
||||
|
|
|
|||
|
|
@ -4,5 +4,5 @@
|
|||
branch = android10-release
|
||||
[submodule "core"]
|
||||
path = core
|
||||
url = https://github.com/JingMatrix/LSPosed.git
|
||||
url = https://github.com/HSSkyBoy/LSPosed.git
|
||||
branch = master
|
||||
|
|
|
|||
2
core
2
core
|
|
@ -1 +1 @@
|
|||
Subproject commit fd894b94b2c0790f69aed8b75f13d2cc4f5c26b9
|
||||
Subproject commit b168c71f7b05b81a05cefc8343ca10bfb5fb1dc9
|
||||
|
|
@ -359,6 +359,14 @@ private fun PatchOptionsBody(modifier: Modifier, onAddEmbed: () -> Unit) {
|
|||
desc = stringResource(R.string.patch_inject_dex_desc)
|
||||
)
|
||||
|
||||
SettingsCheckBox(
|
||||
modifier = Modifier.clickable { viewModel.outputLog = !viewModel.outputLog },
|
||||
checked = viewModel.outputLog,
|
||||
icon = Icons.Outlined.AddCard,
|
||||
title = stringResource(R.string.patch_output_log_to_media),
|
||||
desc = stringResource(R.string.patch_output_log_to_media_desc)
|
||||
)
|
||||
|
||||
var bypassExpanded by remember { mutableStateOf(false) }
|
||||
AnywhereDropdown(
|
||||
expanded = bypassExpanded,
|
||||
|
|
|
|||
|
|
@ -33,10 +33,10 @@ fun checkIsApkFixedByLSP(context: Context, packageName: String): Boolean {
|
|||
context.packageManager.getApplicationInfo(packageName, PackageManager.GET_META_DATA)
|
||||
(app.metaData?.containsKey("lspatch") != true)
|
||||
} catch (_: PackageManager.NameNotFoundException) {
|
||||
Log.e("LSPatch", "Package not found: $packageName")
|
||||
Log.e("NPatch", "Package not found: $packageName")
|
||||
false
|
||||
} catch (e: Exception) {
|
||||
Log.e("LSPatch", "Unexpected error in checkIsApkFixedByLSP", e)
|
||||
Log.e("NPatch", "Unexpected error in checkIsApkFixedByLSP", e)
|
||||
false
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ class NewPatchViewModel : ViewModel() {
|
|||
var overrideVersionCode by mutableStateOf(false)
|
||||
var sigBypassLevel by mutableStateOf(2)
|
||||
var injectDex by mutableStateOf(false)
|
||||
var outputLog by mutableStateOf(true)
|
||||
var embeddedModules = emptyList<AppInfo>()
|
||||
|
||||
lateinit var patchApp: AppInfo
|
||||
|
|
@ -96,7 +97,7 @@ class NewPatchViewModel : ViewModel() {
|
|||
if (useManager) embeddedModules = emptyList()
|
||||
patchOptions = Patcher.Options(
|
||||
injectDex = injectDex,
|
||||
config = PatchConfig(useManager, debuggable, overrideVersionCode, sigBypassLevel, null, null),
|
||||
config = PatchConfig(useManager, debuggable, overrideVersionCode, sigBypassLevel, null, null, outputLog),
|
||||
apkPaths = listOf(patchApp.app.sourceDir) + (patchApp.app.splitSourceDirs ?: emptyArray()),
|
||||
embeddedModules = embeddedModules.flatMap { listOf(it.app.sourceDir) + (it.app.splitSourceDirs ?: emptyArray()) }
|
||||
)
|
||||
|
|
|
|||
|
|
@ -112,6 +112,9 @@ public class LSPApplication {
|
|||
// WARN: Since it uses `XResource`, the following class should not be initialized
|
||||
// before forkPostCommon is invoke. Otherwise, you will get failure of XResources
|
||||
|
||||
if (config.outputLog){
|
||||
XposedBridge.setLogPrinter(new XposedLogPrinter(0,"NPatch"));
|
||||
}
|
||||
Log.i(TAG, "Load modules");
|
||||
LSPLoader.initModules(appLoadedApk);
|
||||
Log.i(TAG, "Modules initialized");
|
||||
|
|
@ -119,7 +122,7 @@ public class LSPApplication {
|
|||
switchAllClassLoader();
|
||||
SigBypass.doSigBypass(context, config.sigBypassLevel);
|
||||
|
||||
Log.i(TAG, "LSPatch bootstrap completed");
|
||||
Log.i(TAG, "NPatch bootstrap completed");
|
||||
}
|
||||
|
||||
private static Context createLoadedApkWithContext() {
|
||||
|
|
@ -142,7 +145,7 @@ public class LSPApplication {
|
|||
Log.i(TAG, "Use manager: " + config.useManager);
|
||||
Log.i(TAG, "Signature bypass level: " + config.sigBypassLevel);
|
||||
|
||||
Path originPath = Paths.get(appInfo.dataDir, "cache/lspatch/origin/");
|
||||
Path originPath = Paths.get(appInfo.dataDir, "cache/npatch/origin/");
|
||||
Path cacheApkPath;
|
||||
try (ZipFile sourceFile = new ZipFile(appInfo.sourceDir)) {
|
||||
cacheApkPath = originPath.resolve(sourceFile.getEntry(ORIGINAL_APK_ASSET_PATH).getCrc() + ".apk");
|
||||
|
|
|
|||
|
|
@ -0,0 +1,49 @@
|
|||
package org.lsposed.lspatch.loader;
|
||||
|
||||
import android.app.ActivityThread;
|
||||
import android.os.Environment;
|
||||
import android.util.Log;
|
||||
import android.util.LogPrinter;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
public class XposedLogPrinter extends LogPrinter {
|
||||
|
||||
/**
|
||||
* Create a new Printer that sends to the log with the given priority
|
||||
* and tag.
|
||||
*
|
||||
* @param priority The desired log priority:
|
||||
* {@link Log#VERBOSE Log.VERBOSE},
|
||||
* {@link Log#DEBUG Log.DEBUG},
|
||||
* {@link Log#INFO Log.INFO},
|
||||
* {@link Log#WARN Log.WARN}, or
|
||||
* {@link Log#ERROR Log.ERROR}.
|
||||
* @param tag A string tag to associate with each printed log statement.
|
||||
*/
|
||||
public XposedLogPrinter(int priority, String tag) {
|
||||
super(priority, tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void println(String x) {
|
||||
writeLine(x);
|
||||
}
|
||||
private static SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
|
||||
private static FileOutputStream out;
|
||||
private static synchronized void writeLine(String text){
|
||||
try {
|
||||
if (out == null){
|
||||
File f = new File(Environment.getExternalStorageDirectory() + "/Android/media/" + ActivityThread.currentPackageName() + "/npatch/log/");
|
||||
f.mkdirs();
|
||||
out = new FileOutputStream(new File(f,format.format(new Date()) + ".log"),true);
|
||||
}
|
||||
out.write(text.getBytes());
|
||||
out.write("\n".getBytes());
|
||||
}catch (Exception ignored){ }
|
||||
}
|
||||
}
|
||||
|
|
@ -81,6 +81,9 @@ public class LSPatch {
|
|||
@Parameter(names = {"--injectdex"}, description = "Inject directly the loder dex file into the original application package")
|
||||
private boolean injectDex = false;
|
||||
|
||||
@Parameter(names = {"--outputLog"}, description = "Output Log to Media")
|
||||
private boolean outputLog = true;
|
||||
|
||||
@Parameter(names = {"-k", "--keystore"}, arity = 4, description = "Set custom signature keystore. Followed by 4 arguments: keystore path, keystore password, keystore alias, keystore alias password")
|
||||
private List<String> keystoreArgs = Arrays.asList(null, "123456", "key0", "123456");
|
||||
|
||||
|
|
@ -96,6 +99,7 @@ public class LSPatch {
|
|||
@Parameter(names = {"-m", "--embed"}, description = "Embed provided modules to apk")
|
||||
private List<String> modules = new ArrayList<>();
|
||||
|
||||
|
||||
private static final String ANDROID_MANIFEST_XML = "AndroidManifest.xml";
|
||||
private static final HashSet<String> ARCHES = new HashSet<>(Arrays.asList(
|
||||
"armeabi-v7a",
|
||||
|
|
@ -250,7 +254,7 @@ public class LSPatch {
|
|||
|
||||
logger.i("Patching apk...");
|
||||
// modify manifest
|
||||
final var config = new PatchConfig(useManager, debuggableFlag, overrideVersionCode, sigbypassLevel, originalSignature, appComponentFactory);
|
||||
final var config = new PatchConfig(useManager, debuggableFlag, overrideVersionCode, sigbypassLevel, originalSignature, appComponentFactory, outputLog);
|
||||
final var configBytes = new Gson().toJson(config).getBytes(StandardCharsets.UTF_8);
|
||||
final var metadata = Base64.getEncoder().encodeToString(configBytes);
|
||||
try (var is = new ByteArrayInputStream(modifyManifestFile(manifestEntry.open(), metadata, minSdkVersion))) {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ public class PatchConfig {
|
|||
public final boolean useManager;
|
||||
public final boolean debuggable;
|
||||
public final boolean overrideVersionCode;
|
||||
public final boolean outputLog;
|
||||
public final int sigBypassLevel;
|
||||
public final String originalSignature;
|
||||
public final String appComponentFactory;
|
||||
|
|
@ -17,7 +18,8 @@ public class PatchConfig {
|
|||
boolean overrideVersionCode,
|
||||
int sigBypassLevel,
|
||||
String originalSignature,
|
||||
String appComponentFactory
|
||||
String appComponentFactory,
|
||||
boolean outputLog
|
||||
) {
|
||||
this.useManager = useManager;
|
||||
this.debuggable = debuggable;
|
||||
|
|
@ -27,5 +29,6 @@ public class PatchConfig {
|
|||
this.appComponentFactory = appComponentFactory;
|
||||
this.lspConfig = LSPConfig.instance;
|
||||
this.managerPackageName = Constants.MANAGER_PACKAGE_NAME;
|
||||
this.outputLog = outputLog;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue