12 Commits

Author SHA1 Message Date
AndnixSH 8f72cf9dee Merge branch 'pr/48' 2026-05-03 13:17:37 +02:00
AndnixSH 79e8cd2ef9 Refactor + Add Apktool version checks 2026-05-03 11:56:56 +02:00
AndnixSH 5be8c9623a Merge branch 'pr/49' 2026-04-28 17:56:14 +02:00
backryun 08fb90285c ci: package artifact with exe/resources/changelog only 2026-03-05 20:56:43 +09:00
backryun e0e99c862f fix: correct signing/build option handling and drag-drop stability
Use Sign_UseOutputDir in signing flows instead of Zipalign_UseOutputDir
Fix apktool arg composition so -api and -j are both preserved
Fix JarProcess JVM arg order and default java executable handling
Replace non-functional splitTypes string replacement with Regex.Replace in ApkFixer
Remove duplicate private-key click handler registration
Fix APK info drag-drop target textbox and guard drag-drop helpers against empty drops
Keep DEBUG/RELEASE catch split to avoid CS0168 in Release
2026-03-05 20:37:17 +09:00
backryun cfb094a275 Update ADB, apktool, APKEditor 2026-03-05 20:11:35 +09:00
Aleksandr ca58db1975 Update Russian localization 2026-02-16 10:39:19 +03:00
AndnixSH 5e6eee2f5e Update README.md 2026-01-20 21:41:23 +01:00
AndnixSH eb39b5bf69 Update README.md 2026-01-20 21:23:08 +01:00
AndnixSH 8230d8239d Auto remove remaining split elements 2026-01-20 20:59:43 +01:00
AndnixSH 824aadbce1 Update changelog.txt 2025-11-26 17:39:45 +01:00
AndnixSH e12fc939b9 Change version to 3.3.2.1 2025-11-26 17:37:03 +01:00
22 changed files with 1831 additions and 1549 deletions
+6 -5
View File
@@ -31,13 +31,14 @@ jobs:
run: mkdir package
- name: Copy essential files to package
shell: pwsh
run: |
cp APKToolGUI/bin/Release/APKToolGUI.exe package/
cp -r APKToolGUI/bin/Release/Resources package/
cp APKToolGUI/bin/Release/*.dll package/
Copy-Item APKToolGUI/bin/Release/APKToolGUI.exe package/
Copy-Item changelog.txt package/Changelog.txt
- name: Create placeholder config.xml
run: New-Item -Path package/ -Name "config.xml" -ItemType "file"
if (Test-Path APKToolGUI/bin/Release/Resources) {
Copy-Item APKToolGUI/bin/Release/Resources package/ -Recurse
}
- name: Upload artifact
uses: actions/upload-artifact@v4
+2
View File
@@ -30,6 +30,8 @@ namespace APKToolGUI.ApkTool
manifestText = manifestText.Replace("android:manageSpace=\"true\"", "");
manifestText = manifestText.Replace("android:localeConfig=\"@xml/locales_config\"", "");
manifestText = manifestText.Replace("STAMP_TYPE_DISTRIBUTION_APK", "STAMP_TYPE_STANDALONE_APK");
manifestText = Regex.Replace(manifestText, @"\s*android:requiredSplitTypes=""[^""]*""", "");
manifestText = Regex.Replace(manifestText, @"\s*android:splitTypes=""[^""]*""", "");
File.WriteAllText(manifestPath, manifestText);
return true;
+246 -146
View File
@@ -14,55 +14,118 @@ namespace APKToolGUI
public class Apktool : JarProcess, IDisposable
{
private bool disposed = false;
private static readonly Regex ApktoolVersionRegex = new Regex(@"v?(?<version>\d+\.\d+\.\d+)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
public Version ParsedVersion { get; private set; }
public string Version { get; private set; }
enum ApktoolActionType
public Apktool(string javaPath, string jarPath) : base(javaPath, jarPath)
{
Decompile,
Build,
InstallFramework,
ClearFramework,
Null
Exited += Apktool_Exited;
OutputDataReceived += Apktool_OutputDataReceived;
ErrorDataReceived += Apktool_ErrorDataReceived;
string apktoolVersion = GetVersion();
string apktoolVersionOld = GetVersionOld();
if (!String.IsNullOrWhiteSpace(apktoolVersion) && !Regex.IsMatch(apktoolVersion, @"\r\n?|\n"))
Version = apktoolVersion;
else if (!String.IsNullOrWhiteSpace(apktoolVersionOld) && !Regex.IsMatch(apktoolVersionOld, @"\r\n?|\n"))
Version = apktoolVersionOld;
ParsedVersion = ParseVersion(Version);
Debug.WriteLine($"[Apktool] Parsed version: {ParsedVersion}");
}
static class DecompileKeys
{
public const string NoSource = " -s"; //Do not decode sources.
public const string NoResource = " -r"; //Do not decode resources.
public const string NoDebugInfo = " -b"; //don't write out debug info (.local, .param, .line, etc.)
public const string Force = " -f"; //Skip changes detection and build all files.
public const string FrameworkPath = " -p"; //Uses framework files located in <dir>.
public const string KeepBrokenResource = " -k"; //Use if there was an error and some resources were dropped
public const string MatchOriginal = " -m"; //Keeps files to closest to original as possible. Prevents rebuild.
public const string OutputDir = " -o"; //The name of folder that gets written. Default is apk.out
public const string OnlyMainClasses = " -only-main-classes"; //Only disassemble the main dex classes (classes[0-9]*.dex) in the root.
public const string ApiLevel = " -api"; //The numeric api-level of the file to generate, e.g. 14 for ICS.
public const string Jobs = " -j"; // Sets the number of threads to use.
//Do not decode sources.
public const string NoSource = " -s";
//Do not decode resources.
public const string NoResource = " -r";
//don't write out debug info (.local, .param, .line, etc.)
//The -b flag has been removed from APKtool 3.0.1 and later versions,
//but the --no-debug-info flag is supported in all versions.
public const string NoDebugInfo = " --no-debug-info";
//Skip changes detection and build all files.
public const string Force = " -f";
//Uses framework files located in <dir>.
public const string FrameworkPath = " -p";
//Use if there was an error and some resources were dropped
public const string KeepBrokenResource = " -k";
//Keeps files to closest to original as possible. Prevents rebuild.
public const string MatchOriginal = " -m";
//The name of folder that gets written. Default is apk.out
public const string OutputDir = " -o";
//Only disassemble the main dex classes (classes[0-9]*.dex) in the root.
public const string OnlyMainClasses = " --only-main-classes";
//The numeric api-level of the file to generate, e.g. 14 for ICS.
public const string ApiLevel = " -api";
// Sets the number of threads to use.
public const string Jobs = " -j";
}
static class BuildKeys
{
public const string ForceAll = " -f"; //Skip changes detection and build all files.
public const string CopyOriginal = " -c"; //opies original AndroidManifest.xml and META-INF. See project page for more info.
public const string Aapt = " -a"; //Loads aapt from specified location.
public const string FrameworkPath = " -p"; //Uses framework files located in <dir>.
public const string OutputAppPath = " -o"; // The name of apk that gets written. Default is dist/name.apk
public const string NoCrunch = " -nc"; // Disable crunching of resource files during the build step.
public const string ApiLevel = " -api"; //The numeric api-level of the file to generate, e.g. 14 for ICS.
public const string UseAapt2 = " --use-aapt2"; //Upgrades apktool to use experimental aapt2 binary.
public const string NetSecConf = " --net-sec-conf"; //Add a generic Network Security Configuration file in the output APK
public const string Jobs = " -j"; // Sets the number of threads to use.
//Skip changes detection and build all files.
public const string ForceAll = " -f";
//opies original AndroidManifest.xml and META-INF. See project page for more info.
public const string CopyOriginal = " -c";
//Loads aapt from specified location.
public const string Aapt = " -a";
//Uses framework files located in <dir>.
public const string FrameworkPath = " -p";
// The name of apk that gets written. Default is dist/name.apk
public const string OutputAppPath = " -o";
// Disable crunching of resource files during the build step.
public const string NoCrunch = " -nc";
//The numeric api-level of the file to generate, e.g. 14 for ICS.
public const string ApiLevel = " -api";
//Upgrades apktool to use experimental aapt2 binary.
public const string UseAapt2 = " --use-aapt2";
//Add a generic Network Security Configuration file in the output APK
public const string NetSecConf = " --net-sec-conf";
// Sets the number of threads to use.
public const string Jobs = " -j";
}
static class InstallFrameworkKeys
{
public const string FrameDir = " -p"; //Stores framework files into <dir>.
public const string Tag = " -t"; //Tag frameworks using <tag>.
//Stores framework files into <dir>.
public const string FrameDir = " -p";
//Tag frameworks using <tag>.
public const string Tag = " -t";
}
static class EmptyFrameworkKeys
{
public const string FrameDir = " -p"; //Stores framework files into <dir>.
public const string ForceDelete = " -f"; //Force delete destination directory.
//Stores framework files into <dir>.
public const string FrameDir = " -p";
//Force delete destination directory.
public const string ForceDelete = " -f";
//Include all framework files regardless of tag. (3.0.1+)
public const string All = " -a";
}
ApktoolDataReceivedEventHandler onApktoolOutputDataRecieved;
@@ -91,15 +154,6 @@ namespace APKToolGUI
}
}
string _jarPath;
public Apktool(string javaPath, string jarPath) : base(javaPath, jarPath)
{
_jarPath = jarPath;
Exited += Apktool_Exited;
OutputDataReceived += Apktool_OutputDataReceived;
ErrorDataReceived += Apktool_ErrorDataReceived;
}
private void Apktool_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
if (onApktoolErrorDataRecieved != null && e.Data != null)
@@ -120,7 +174,7 @@ namespace APKToolGUI
public int Decompile(string inputPath, string outputDir)
{
string keyNoSrc = null, keyNoRes = null, keyForce = null, keyFramePath = null, keyMatchOriginal = null, keyOutputDir = null, onlyMainClasses = null, noDebugInfo = null, keyKeepBrokenRes = null, apiLevel = null;
string keyNoSrc = null, keyNoRes = null, keyForce = null, keyFramePath = null, keyMatchOriginal = null, keyOutputDir = null, onlyMainClasses = null, noDebugInfo = null, keyKeepBrokenRes = null, apiLevel = null, jobs = null;
if (Settings.Default.Decode_NoSrc)
keyNoSrc = DecompileKeys.NoSource;
@@ -132,7 +186,7 @@ namespace APKToolGUI
keyKeepBrokenRes = DecompileKeys.KeepBrokenResource;
if (Settings.Default.Decode_MatchOriginal)
keyMatchOriginal = DecompileKeys.MatchOriginal;
if (Settings.Default.Decode_OnlyMainClasses && !Settings.Default.Decode_NoSrc)
if (Settings.Default.Decode_OnlyMainClasses && !Settings.Default.Decode_NoSrc && IsVersionAtMost("2.12.1"))
onlyMainClasses = DecompileKeys.OnlyMainClasses;
if (Settings.Default.Decode_NoDebugInfo)
noDebugInfo = DecompileKeys.NoDebugInfo;
@@ -143,12 +197,12 @@ namespace APKToolGUI
if (Settings.Default.Decode_SetApiLevel)
apiLevel = String.Format("{0} {1}", DecompileKeys.ApiLevel, Settings.Default.Decode_ApiLevel);
if (Settings.Default.Decode_SetJobs)
apiLevel = String.Format("{0} {1}", DecompileKeys.Jobs, Settings.Default.Decode_Jobs);
jobs = String.Format("{0} {1}", DecompileKeys.Jobs, Settings.Default.Decode_Jobs);
keyOutputDir = String.Format("{0} \"{1}\"", DecompileKeys.OutputDir, outputDir);
string args = String.Format($"d{keyNoSrc}{keyNoRes}{keyForce}{onlyMainClasses}{noDebugInfo}{keyMatchOriginal}{keyFramePath}{keyKeepBrokenRes}{apiLevel}{keyOutputDir} \"{inputPath}\"");
string args = String.Format($"d{keyNoSrc}{keyNoRes}{keyForce}{onlyMainClasses}{noDebugInfo}{keyMatchOriginal}{keyFramePath}{keyKeepBrokenRes}{apiLevel}{jobs}{keyOutputDir} \"{inputPath}\"");
Log.d("Apktool CMD: " + _jarPath + " " + args);
Log.d("Apktool CMD: " + JarPath + " " + args);
Start(args);
BeginOutputReadLine();
@@ -157,6 +211,144 @@ namespace APKToolGUI
return ExitCode;
}
public int Build(string inputFolder, string outputFile)
{
string keyForceAll = null, keyAapt = null, keyCopyOriginal = null, noCrunch = null, keyFramePath = null, keyOutputAppPath = null, apiLevel = null, jobs = null, useAapt2 = null, netSecConf = null;
if (Settings.Default.Build_ForceAll)
keyForceAll = BuildKeys.ForceAll;
if (Settings.Default.Build_CopyOriginal)
keyCopyOriginal = BuildKeys.CopyOriginal;
if (Settings.Default.Build_NoCrunch)
noCrunch = BuildKeys.NoCrunch;
if (Settings.Default.Build_UseAapt)
keyAapt = String.Format("{0} \"{1}\"", BuildKeys.Aapt, Settings.Default.Build_AaptPath);
if (Settings.Default.Build_UseFramework)
keyFramePath = String.Format("{0} \"{1}\"", BuildKeys.FrameworkPath, Settings.Default.Framework_FrameDir);
else
keyFramePath = String.Format("{0} \"{1}\"", BuildKeys.FrameworkPath, Program.STANDALONE_FRAMEWORK_DIR);
if (Settings.Default.Build_SetApiLevel)
apiLevel = String.Format("{0} {1}", BuildKeys.ApiLevel, Settings.Default.Build_ApiLevel);
if (Settings.Default.Build_SetJobs)
jobs = String.Format("{0} {1}", BuildKeys.Jobs, Settings.Default.Build_Jobs);
if (Settings.Default.Build_UseAapt2)
useAapt2 = BuildKeys.UseAapt2;
if (Settings.Default.Build_NetSecConf)
netSecConf = BuildKeys.NetSecConf;
keyOutputAppPath = String.Format("{0} \"{1}\"", BuildKeys.OutputAppPath, outputFile);
string args = String.Format($"b{keyForceAll}{keyAapt}{keyCopyOriginal}{noCrunch}{keyFramePath}{apiLevel}{jobs}{useAapt2}{netSecConf}{keyOutputAppPath} \"{inputFolder}\"");
Log.d("Apktool CMD: " + JarPath + " " + args);
Start(args);
BeginOutputReadLine();
BeginErrorReadLine();
WaitForExit();
return ExitCode;
}
public int InstallFramework()
{
string inputPath = Settings.Default.InstallFramework_InputFramePath;
string keyFrameDir = null, keyTag = null;
if (Settings.Default.Framework_UseFrameDir)
keyFrameDir = String.Format("{0} \"{1}\"", InstallFrameworkKeys.FrameDir, Settings.Default.Framework_FrameDir);
if (Settings.Default.InstallFramework_UseTag)
keyTag = String.Format("{0} \"{1}\"", InstallFrameworkKeys.Tag, Settings.Default.InstallFramework_Tag);
string args = String.Format($"if{keyFrameDir}{keyTag} \"{inputPath}\"");
Log.d("Apktool CMD: " + JarPath + " " + args);
Start(args);
BeginOutputReadLine();
BeginErrorReadLine();
WaitForExit();
return ExitCode;
}
public int ClearFramework()
{
string keyFramePath = null;
if (Settings.Default.Decode_UseFramework)
keyFramePath = String.Format("{0} \"{1}\"", InstallFrameworkKeys.FrameDir, Settings.Default.Framework_FrameDir);
else
keyFramePath = String.Format("{0} \"{1}\"", DecompileKeys.FrameworkPath, Program.STANDALONE_FRAMEWORK_DIR);
string args = String.Format($"empty-framework-dir {EmptyFrameworkKeys.ForceDelete} {keyFramePath}");
if (IsVersionAtLeast("3.0.1"))
args = String.Format($"clean-frameworks {EmptyFrameworkKeys.All} {keyFramePath}");
Log.d("Apktool CMD: " + JarPath + " " + args);
Start(args);
BeginOutputReadLine();
BeginErrorReadLine();
WaitForExit();
return ExitCode;
}
public bool IsVersionAtLeast(string minimumVersion)
{
if (String.IsNullOrWhiteSpace(minimumVersion))
throw new ArgumentException("Minimum version cannot be null or empty.", nameof(minimumVersion));
return ParsedVersion.CompareTo(new Version(minimumVersion)) >= 0;
}
public bool IsVersionAtMost(string maximumVersion)
{
if (String.IsNullOrWhiteSpace(maximumVersion))
throw new ArgumentException("Maximum version cannot be null or empty.", nameof(maximumVersion));
return ParsedVersion.CompareTo(new Version(maximumVersion)) <= 0;
}
private static Version ParseVersion(string rawVersion)
{
if (String.IsNullOrWhiteSpace(rawVersion))
return null;
Match match = ApktoolVersionRegex.Match(rawVersion.Trim());
if (!match.Success)
return null;
try
{
return new Version(match.Groups["version"].Value);
}
catch (Exception)
{
return null;
}
}
public string GetVersion()
{
using (JarProcess apktoolJar = new JarProcess(JavaPath, JarPath))
{
apktoolJar.EnableRaisingEvents = false;
apktoolJar.Start("version");
string version = apktoolJar.StandardOutput.ReadToEnd();
apktoolJar.WaitForExit(3000);
return version.Replace("\r\n", "");
}
}
public string GetVersionOld()
{
using (JarProcess apktoolJar = new JarProcess(JavaPath, JarPath))
{
apktoolJar.EnableRaisingEvents = false;
apktoolJar.Start("-version");
string version = apktoolJar.StandardOutput.ReadToEnd();
apktoolJar.WaitForExit(3000);
return version.Replace("\r\n", "");
}
}
public void Cancel()
{
try
@@ -187,107 +379,6 @@ namespace APKToolGUI
}
}
public int Build(string inputFolder, string outputFile)
{
string keyForceAll = null, keyAapt = null, keyCopyOriginal = null, noCrunch = null, keyFramePath = null, keyOutputAppPath = null, apiLevel = null, useAapt2 = null, netSecConf = null;
if (Settings.Default.Build_ForceAll)
keyForceAll = BuildKeys.ForceAll;
if (Settings.Default.Build_CopyOriginal)
keyCopyOriginal = BuildKeys.CopyOriginal;
if (Settings.Default.Build_NoCrunch)
noCrunch = BuildKeys.NoCrunch;
if (Settings.Default.Build_UseAapt)
keyAapt = String.Format("{0} \"{1}\"", BuildKeys.Aapt, Settings.Default.Build_AaptPath);
if (Settings.Default.Build_UseFramework)
keyFramePath = String.Format("{0} \"{1}\"", BuildKeys.FrameworkPath, Settings.Default.Framework_FrameDir);
else
keyFramePath = String.Format("{0} \"{1}\"", BuildKeys.FrameworkPath, Program.STANDALONE_FRAMEWORK_DIR);
if (Settings.Default.Build_SetApiLevel)
apiLevel = String.Format("{0} {1}", BuildKeys.ApiLevel, Settings.Default.Build_ApiLevel);
if (Settings.Default.Build_SetJobs)
apiLevel = String.Format("{0} {1}", BuildKeys.Jobs, Settings.Default.Build_Jobs);
if (Settings.Default.Build_UseAapt2)
useAapt2 = BuildKeys.UseAapt2;
if (Settings.Default.Build_NetSecConf)
netSecConf = BuildKeys.NetSecConf;
keyOutputAppPath = String.Format("{0} \"{1}\"", BuildKeys.OutputAppPath, outputFile);
string args = String.Format($"b{keyForceAll}{keyAapt}{keyCopyOriginal}{noCrunch}{keyFramePath}{apiLevel}{useAapt2}{netSecConf}{keyOutputAppPath} \"{inputFolder}\"");
Log.d("Apktool CMD: " + _jarPath + " " + args);
Start(args);
BeginOutputReadLine();
BeginErrorReadLine();
WaitForExit();
return ExitCode;
}
public int InstallFramework()
{
string inputPath = Settings.Default.InstallFramework_InputFramePath;
string keyFrameDir = null, keyTag = null;
if (Settings.Default.Framework_UseFrameDir)
keyFrameDir = String.Format("{0} \"{1}\"", InstallFrameworkKeys.FrameDir, Settings.Default.Framework_FrameDir);
if (Settings.Default.InstallFramework_UseTag)
keyTag = String.Format("{0} \"{1}\"", InstallFrameworkKeys.Tag, Settings.Default.InstallFramework_Tag);
string args = String.Format($"if{keyFrameDir}{keyTag} \"{inputPath}\"");
Log.d("Apktool CMD: " + _jarPath + " " + args);
Start(args);
BeginOutputReadLine();
BeginErrorReadLine();
WaitForExit();
return ExitCode;
}
public int ClearFramework()
{
string keyFramePath = null;
if (Settings.Default.Decode_UseFramework)
keyFramePath = String.Format("{0} \"{1}\"", InstallFrameworkKeys.FrameDir, Settings.Default.Framework_FrameDir);
else
keyFramePath = String.Format("{0} \"{1}\"", DecompileKeys.FrameworkPath, Program.STANDALONE_FRAMEWORK_DIR);
string args = String.Format($"empty-framework-dir {EmptyFrameworkKeys.ForceDelete} {keyFramePath}");
Log.d("Apktool CMD: " + _jarPath + " " + args);
Start(args);
BeginOutputReadLine();
BeginErrorReadLine();
WaitForExit();
return ExitCode;
}
public string GetVersion()
{
using (JarProcess apktoolJar = new JarProcess(JavaPath, JarPath))
{
apktoolJar.EnableRaisingEvents = false;
apktoolJar.Start("version");
string version = apktoolJar.StandardOutput.ReadToEnd();
apktoolJar.WaitForExit(3000);
return version.Replace("\r\n", "");
}
}
public string GetVersionOld()
{
using (JarProcess apktoolJar = new JarProcess(JavaPath, JarPath))
{
apktoolJar.EnableRaisingEvents = false;
apktoolJar.Start("-version");
string version = apktoolJar.StandardOutput.ReadToEnd();
apktoolJar.WaitForExit(3000);
return version.Replace("\r\n", "");
}
}
public new void Dispose()
{
Dispose(true);
@@ -401,4 +492,13 @@ namespace APKToolGUI
Error,
Unknown
}
enum ApktoolActionType
{
Decompile,
Build,
InstallFramework,
ClearFramework,
Null
}
}
+3 -2
View File
@@ -28,6 +28,7 @@
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FormMain));
this.tabControlMain = new System.Windows.Forms.TabControl();
this.tabPageMain = new System.Windows.Forms.TabPage();
@@ -242,7 +243,7 @@
this.toolStripStatusLabelStateImage = new System.Windows.Forms.ToolStripStatusLabel();
this.toolStripStatusLabelStateText = new System.Windows.Forms.ToolStripStatusLabel();
this.progressBar = new System.Windows.Forms.ToolStripProgressBar();
this.contextMenuStripLog = new System.Windows.Forms.ContextMenuStrip();
this.contextMenuStripLog = new System.Windows.Forms.ContextMenuStrip(this.components);
this.copyToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.clearLogToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.logTxtBox = new System.Windows.Forms.RichTextBox();
@@ -264,7 +265,7 @@
this.apktoolIssuesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.baksmaliIssuesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolTip1 = new System.Windows.Forms.ToolTip();
this.toolTip1 = new System.Windows.Forms.ToolTip(this.components);
this.splitContainer1 = new System.Windows.Forms.SplitContainer();
this.tabControlMain.SuspendLayout();
this.tabPageMain.SuspendLayout();
+14 -23
View File
@@ -205,14 +205,17 @@ namespace APKToolGUI
ToLog(ApktoolEventType.Success, Language.Done);
ToStatus(Language.Done, Resources.done);
}
#if DEBUG
catch (Exception ex)
{
#if DEBUG
ToLog(ApktoolEventType.Warning, Language.ErrorGettingApkInfo + "\n" + ex.ToString());
#else
ToLog(ApktoolEventType.Warning, Language.ErrorGettingApkInfo);
#endif
}
#else
catch (Exception)
{
ToLog(ApktoolEventType.Warning, Language.ErrorGettingApkInfo);
}
#endif
}
private async Task<ApkParseResult> ParseApkInBackgroundAsync(string file, string splitPath)
@@ -701,18 +704,10 @@ namespace APKToolGUI
#region Apktool
public async void SetApktoolPath()
{
apktool.JarPath = Program.APKTOOL_PATH;
if (Settings.Default.UseCustomApktool)
{
apktool.JarPath = Settings.Default.ApktoolPath;
}
InitializeAPKTool();
string apktoolVersion = apktool.GetVersion();
string apktoolVersionOld = apktool.GetVersionOld();
if (!String.IsNullOrWhiteSpace(apktoolVersion) && !Regex.IsMatch(apktoolVersion, @"\r\n?|\n"))
ToLog(ApktoolEventType.None, $"{Language.APKToolVersion} \"{apktoolVersion}\"");
else if (!String.IsNullOrWhiteSpace(apktoolVersionOld) && !Regex.IsMatch(apktoolVersionOld, @"\r\n?|\n"))
ToLog(ApktoolEventType.None, $"{Language.APKToolVersion} \"{apktoolVersionOld}\"");
if (!String.IsNullOrWhiteSpace(apktool.Version))
ToLog(ApktoolEventType.None, $"{Language.APKToolVersion} \"{apktool.Version}\"");
else
ToLog(ApktoolEventType.Error, Language.CantDetectApktoolVersion);
@@ -1235,7 +1230,7 @@ namespace APKToolGUI
Running(Language.Signing);
string outputFile = input;
if (Settings.Default.Zipalign_UseOutputDir && !IgnoreOutputDirContextMenu)
if (Settings.Default.Sign_UseOutputDir && !IgnoreOutputDirContextMenu)
outputFile = Path.Combine(Settings.Default.Sign_OutputDir, Path.GetFileName(input));
if (!Settings.Default.Sign_OverwriteInputFile)
outputFile = PathUtils.GetDirectoryNameWithoutExtension(outputFile) + "_signed.apk";
@@ -1435,13 +1430,9 @@ namespace APKToolGUI
if (javaVersion != null)
{
ToLog(ApktoolEventType.None, javaVersion);
string apktoolVersion = apktool.GetVersion();
string apktoolVersionOld = apktool.GetVersionOld();
if (!String.IsNullOrWhiteSpace(apktoolVersion) && !Regex.IsMatch(apktoolVersion, @"\r\n?|\n"))
ToLog(ApktoolEventType.None, $"{Language.APKToolVersion} {apktoolVersion}");
else if (!String.IsNullOrWhiteSpace(apktoolVersionOld) && !Regex.IsMatch(apktoolVersionOld, @"\r\n?|\n"))
ToLog(ApktoolEventType.None, $"{Language.APKToolVersion} {apktoolVersionOld}");
if (!String.IsNullOrWhiteSpace(apktool.Version) && !Regex.IsMatch(apktool.Version, @"\r\n?|\n"))
ToLog(ApktoolEventType.None, $"{Language.APKToolVersion} {apktool.Version}");
else
ToLog(ApktoolEventType.Error, Language.CantDetectApktoolVersion);
@@ -1716,4 +1707,4 @@ namespace APKToolGUI
}
}
}
}
}
File diff suppressed because it is too large Load Diff
+75
View File
@@ -275,4 +275,79 @@
<data name="label_SIGN_PublicKey.Text" xml:space="preserve">
<value>Открытый ключ</value>
</data>
<data name="tabPageMain.Text" xml:space="preserve">
<value>Главная</value>
</data>
<data name="tabPageApkInfo.Text" xml:space="preserve">
<value>Инфо APK</value>
</data>
<data name="checkBox4.Text" xml:space="preserve">
<value>Количество потоков:</value>
</data>
<data name="checkBox_BUILD_NetSecConf.Text" xml:space="preserve">
<value>Добавить файл конфигурации сетевой безопасности (Network Security Configuration)</value>
</data>
<data name="useAapt2ChkBox.Text" xml:space="preserve">
<value>Использовать aapt2 (для версий apktool &lt; 2.11.1)</value>
</data>
<data name="buildSetApiLvlChkBox.Text" xml:space="preserve">
<value>Установить уровень API (напр. 14 для ICS)</value>
</data>
<data name="createUnsignApkChkBox.Text" xml:space="preserve">
<value>Создать неподписанный APK с оригинальной подписью (Core Patch)</value>
</data>
<data name="signAfterBuildChkBox.Text" xml:space="preserve">
<value>Подписать после сборки / выравнивания</value>
</data>
<data name="zipalignAfterBuildChkBox.Text" xml:space="preserve">
<value>Выровнять после сборки</value>
</data>
<data name="checkBox_BUILD_NoCrunch.Text" xml:space="preserve">
<value>Отключить сжатие ресурсов</value>
</data>
<data name="tabPageBaksmali.Text" xml:space="preserve">
<value>Baksmali / Smali</value>
</data>
<data name="tabPageAdb.Text" xml:space="preserve">
<value>ADB</value>
</data>
<data name="mergeApkBtn.Text" xml:space="preserve">
<value>Слияние APK</value>
</data>
<data name="selSplitApkBtn.Text" xml:space="preserve">
<value>Выбрать Split APK</value>
</data>
<data name="baksmaliUseOutputChkBox.Text" xml:space="preserve">
<value>Свой каталог вывода:</value>
</data>
<data name="smaliUseOutputChkBox.Text" xml:space="preserve">
<value>Свой каталог вывода:</value>
</data>
<data name="killAdbBtn.Text" xml:space="preserve">
<value>Перезапустить ADB</value>
</data>
<data name="installApkBtn.Text" xml:space="preserve">
<value>Установить APK</value>
</data>
<data name="refreshDevicesBtn.Text" xml:space="preserve">
<value>Обновить список</value>
</data>
<data name="selApkAdbBtn.Text" xml:space="preserve">
<value>Выбрать APK</value>
</data>
<data name="overrideAbiCheckBox.Text" xml:space="preserve">
<value>Переопределить ABI:</value>
</data>
<data name="bakSmaliGroupBox.Text" xml:space="preserve">
<value>Baksmali (DEX -&gt; Smali)</value>
</data>
<data name="smaliGroupBox.Text" xml:space="preserve">
<value>Smali (Smali -&gt; DEX)</value>
</data>
<data name="decSmaliBtn.Text" xml:space="preserve">
<value>Дизассемблировать</value>
</data>
<data name="comSmaliBtn.Text" xml:space="preserve">
<value>Ассемблировать</value>
</data>
</root>
+15
View File
@@ -163,4 +163,19 @@
<data name="$this.Text" xml:space="preserve">
<value>Настройки</value>
</data>
<data name="buttonCustomJavaLocation.Text" xml:space="preserve">
<value>Указать путь к Java</value>
</data>
<data name="useCustomApktoolChk.Text" xml:space="preserve">
<value>Свой путь к Apktool</value>
</data>
<data name="label1.Text" xml:space="preserve">
<value>Тема</value>
</data>
<data name="checkBox6.Text" xml:space="preserve">
<value>Режим отладки</value>
</data>
<data name="checkBox7.Text" xml:space="preserve">
<value>Аргументы JVM</value>
</data>
</root>
+1 -1
View File
@@ -208,7 +208,7 @@ namespace APKToolGUI.Handlers
string apkFile = null;
if (e.DropOneByEnd(file => apkFile = file, apks))
{
main.smaliBrowseInputDirTxtBox.Text = apkFile;
main.fileTxtBox.Text = apkFile;
main.basicInfoTabPage.BackColor = PanelBackColor();
await main.GetApkInfo(apkFile);
}
@@ -203,7 +203,7 @@ namespace APKToolGUI.Handlers
{
string inputFile = Settings.Default.Sign_InputFile;
string outputFile = inputFile;
if (Settings.Default.Zipalign_UseOutputDir)
if (Settings.Default.Sign_UseOutputDir)
outputFile = Path.Combine(Settings.Default.Sign_OutputDir, Path.GetFileName(inputFile));
if (File.Exists(outputFile))
@@ -24,7 +24,6 @@ namespace APKToolGUI.Handlers
main = Main;
main.button_SIGN_BrowsePublicKey.Click += Button_SIGN_BrowsePublicKey_Click;
main.button_SIGN_BrowsePrivateKey.Click += Button_SIGN_BrowsePrivateKey_Click;
main.button_SIGN_BrowsePrivateKey.Click += Button_SIGN_BrowsePrivateKey_Click;
main.button_SIGN_BrowseInputFile.Click += Button_SIGN_BrowseInputFile_Click;
main.button_SIGN_BrowseOutputFile.Click += Button_SIGN_BrowseOutputFile_Click;
main.schemev1ComboBox.SelectedIndexChanged += SchemeComboBox_SelectedIndexChanged;
+4 -3
View File
@@ -14,7 +14,7 @@ namespace Java
public JarProcess(string javaPath, string jarPath)
{
JavaPath = javaPath.Equals("java") ? "" : javaPath;
JavaPath = string.IsNullOrWhiteSpace(javaPath) ? "java" : javaPath;
JarPath = jarPath;
Initialize();
}
@@ -38,8 +38,9 @@ namespace Java
if (Settings.Default.UseCustomJVMArgs)
customArgs = Settings.Default.CustomJVMArgs;
StartInfo.Arguments = String.Format("-jar {0} \"{1}\" {2}", customArgs, JarPath, args);
Debug.WriteLine(String.Format("-jar {0} \"{1}\" {2}", customArgs, JarPath, args));
string jvmArgs = string.IsNullOrWhiteSpace(customArgs) ? string.Empty : customArgs.Trim() + " ";
StartInfo.Arguments = String.Format("{0}-jar \"{1}\" {2}", jvmArgs, JarPath, args);
Debug.WriteLine(StartInfo.Arguments);
return base.Start();
}
+30
View File
@@ -510,6 +510,36 @@
<data name="ClearFrameworkPrompt" xml:space="preserve">
<value>После изменения версии Apktool необходимо очистить кеш. Вы хотите очистить его сейчас?</value>
</data>
<data name="RestartApplicationPrompt" xml:space="preserve">
<value>Для применения изменений требуется перезапуск. Перезапустить приложение сейчас?</value>
</data>
<data name="ClearTempFolder" xml:space="preserve">
<value>Очистка временной папки</value>
</data>
<data name="DeletingFolder" xml:space="preserve">
<value>Удаление папки: {0}</value>
</data>
<data name="DirectoryNotExist" xml:space="preserve">
<value>Директория "{0}" не существует</value>
</data>
<data name="OpenComFolder" xml:space="preserve">
<value>Открыть папку скомпилированных файлов</value>
</data>
<data name="OpenDecFolder" xml:space="preserve">
<value>Открыть папку декомпилированных файлов</value>
</data>
<data name="FixApktoolYml" xml:space="preserve">
<value>Исправлен apktool.yml</value>
</data>
<data name="CopyFileTo" xml:space="preserve">
<value>Копирование файла "{0}" в "{1}"</value>
</data>
<data name="SplitApkNotFound" xml:space="preserve">
<value>Split APK не выбран</value>
</data>
<data name="CantDetectApkeditorVersion" xml:space="preserve">
<value>Не удалось определить версию APKEditor</value>
</data>
<data name="SetLanguageRestartApplication" xml:space="preserve">
<value>Язык установлен. Хотите перезапустить программу?</value>
</data>
+2 -2
View File
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("3.3.2.0")]
[assembly: AssemblyFileVersion("3.3.2.0")]
[assembly: AssemblyVersion("3.3.2.1")]
[assembly: AssemblyFileVersion("3.3.2.1")]
+24 -1
View File
@@ -38,6 +38,12 @@ namespace SaveToGameWpf.Logic.Utils
public static void CheckDragEnter(this DragEventArgs e, params string[] extensions)
{
string[] files = e.GetFilesDrop();
if (files.Length == 0)
{
e.Effect = DragDropEffects.None;
return;
}
if (extensions == null && Directory.Exists(files[0]))
e.Effect = DragDropEffects.Copy;
else if (extensions != null && extensions.Any(ext => files[0].EndsWith(ext, StringComparison.Ordinal)))
@@ -49,12 +55,18 @@ namespace SaveToGameWpf.Logic.Utils
public static bool CheckDragOver(this DragEventArgs e, params string[] extensions)
{
string[] files = e.GetFilesDrop();
if (files.Length == 0)
{
e.Effect = DragDropEffects.None;
return false;
}
if (extensions == null && Directory.Exists(files[0]))
{
e.Effect = DragDropEffects.Move;
return true;
}
else if (files.Length == 1 && extensions.Any(ext => files[0].EndsWith(ext, StringComparison.Ordinal)))
else if (extensions != null && files.Length == 1 && extensions.Any(ext => files[0].EndsWith(ext, StringComparison.Ordinal)))
{
e.Effect = DragDropEffects.Move;
return true;
@@ -68,6 +80,11 @@ namespace SaveToGameWpf.Logic.Utils
public static bool CheckManyDragOver(this DragEventArgs e, params string[] extensions)
{
string[] files = e.GetFilesDrop();
if (files.Length == 0)
{
e.Effect = DragDropEffects.None;
return false;
}
if (extensions == null && Directory.Exists(files[0]))
{
@@ -87,6 +104,9 @@ namespace SaveToGameWpf.Logic.Utils
public static bool DropOneByEnd(this DragEventArgs e, Action<string> onSuccess, params string[] extensions)
{
string[] files = e.GetFilesDrop();
if (files.Length == 0)
return false;
if (extensions == null && Directory.Exists(files[0]))
{
onSuccess(files[0]);
@@ -103,6 +123,9 @@ namespace SaveToGameWpf.Logic.Utils
public static bool DropManyByEnd(this DragEventArgs e, Action<string[]> onSuccess, params string[] extensions)
{
if (extensions == null || extensions.Length == 0)
return false;
foreach (string apk in extensions)
{
Debug.WriteLine(apk);
+32 -24
View File
@@ -10,13 +10,13 @@ It is a tool for reverse engineering 3rd party, closed, binary Android apps. It
# Download links
https://github.com/AndnixSH/APKToolGUI/releases
Any such report from your antivirus is a false positive and is due to how the application works. You must manually add APKToolGUI.exe to your antivirus's whitelist/exclusion list.
Any alert from your antivirus regarding this application is a **false positive**, caused by how the application operates. To resolve this, manually add **APKToolGUI.exe** to your antiviruss whitelist or exclusion list.
If you don't believe this then try to compile the app by yourself or simply don't use it until you can confirm it is safe by working directly with your antiirus provider.
If you remain unsure, you can compile the app yourself or refrain from using it until you confirm its safety with your antivirus provider.
# Requirements
- Windows 7 32-bit/64-bit and above
- [Java](https://www.java.com/en/) or [JDK](https://www.oracle.com/java/technologies/downloads/) 8 or above. Using latest JDK is not really necessary, it tends to cause unexpected issues. Java 8 and 17 (long-term support release) is enough. Use 64-bit version if your system is 64-bit
- [Java](https://www.java.com/en/) or [JDK](https://www.oracle.com/java/technologies/downloads/) 8 or above. Using latest JDK is not really necessary. Java 8 and 25 (long-term support release) is enough. Use 64-bit version if your system is 64-bit
- [.NET Framework 4.8](https://dotnet.microsoft.com/en-us/download/dotnet-framework/net48) (Windows 8 and above already have it preinstalled)
# Features
@@ -75,40 +75,48 @@ For Framework/system apps related issues, check on [XDA Forum](https://forum.xda
Anything else, [create a new issue](https://github.com/AndnixSH/APKToolGUI/issues)
# FAQ
##### Q: Can it be ported to other OS like Linux?
A: Notthing is impossible, but it's not easy as long as Microsoft not supporting WinForm for other platforms, making .NET Core useless, unlike Java FX that supports other platforms since decades. If you know, feel free to open an issue. Until then, use [WineHQ](https://www.winehq.org/) or similar to run exe
##### Can it be ported to macOS or Linux?
Microsoft has not made it easy to port, and .NET Core remains impractical for this purpose. While I could use Avalonia UI as an alternative, I currently dont have the time to port the entire project. Pull requests are welcome!
##### Q: How to update Apktool?
A: Download [Apktool.jar](https://github.com/iBotPeaches/Apktool/releases) and replace it on Resources folder
In the meantime, you can use [WineHQ](https://www.winehq.org/) or similar tools to run the .exe file.
##### Q: How to update Baksmali/Smali?
A: Download [Baksmali.jar/Smali.jar](https://bitbucket.org/JesusFreke/smali/downloads/) and replace it on Resources folder
##### How to update Apktool?
Download [Apktool.jar](https://github.com/iBotPeaches/Apktool/releases) and replace it on Resources folder
##### Q: How to reset?
A: Simply delete the config.xml file from the directory of the executeable
##### How to update Baksmali/Smali?
Download [Baksmali.jar/Smali.jar](https://bitbucket.org/JesusFreke/smali/downloads/) and replace it on Resources folder
##### Q: Can you make an automatic APK injecting tool?
A: No, I'm not interested.
##### How to reset?
Simply delete the config.xml file from the directory of the executeable
##### Q: Can you implement to convert APK to AAB?
A: No, apktool is about recompiling, not converting to other formats. AAB is only used for distributing an application to Play Store, so it is not directly installable. If you really want to convert APK to ABB, try APK2AAB tool https://github.com/sensei-z/APK2AAB
##### Can you help me with modding APKs in general?
No, I do not provide support for APK modding.
##### Q: I don't like split APK. Where can I get single APK instead?
A: Download from [Apkcombo's APK downloader](https://apkcombo.com/downloader/), or [Apkpure](https://apkpure.com/) (Choose APK instead XAPK)
##### Can you make an automatic APK injecting tool?
No, I'm not interested.
##### Q: Can you help me with modding APK in general?
A: Sorry, I don't offer support with it.
##### Can you implement APK to AAB conversion?
No, APKTool is designed for decompiling and recompiling APKs, not for converting between formats. AAB (Android App Bundle) is used exclusively for distributing apps on the Google Play Store and is not directly installable on devices.
##### Q: Can you implement features to protect/pack/obfuscate APK?
A: No, APK protection is beyond the scope of this tool
If you need to convert an APK to AAB, you can try using a tool like [APK2AAB](https://github.com/sensei-z/APK2AAB)
##### Q: Can you implement features to deobfuscate/unpack APK or bypass anti-cheat/security?
A: No, they are also beyond the scope of this tool. I don't condone bypassing such protections
##### Can you implement features to protect, pack, or obfuscate APKs?
No, APK protection is beyond the scope of this tool.
##### Can you implement features to deobfuscate, unpack APKs, or bypass anti-cheat/security?
No, these features are also beyond the scope of this tool. I do not support or condone bypassing such protections.
# Development
This project is written in C#
Use Visual Studio 2019 and above. NET Framework 4.8 SDK is required
Use Visual Studio 2022 and above. NET Framework 4.8 SDK is required
# Contributing
Contributions are welcome! Please ensure you:
- Submit pull requests with clear, detailed descriptions.
- Open an issue to discuss significant changes before implementing them.
- Do not submit pull requests for bypass or protection features.
# Credits
- AndnixSH
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+12
View File
@@ -1,3 +1,15 @@
3.3.2.2
- Updated APKEditor to 1.4.7
- Updated Apktool to 3.0.1
- Updated ADB to 37.0.0-14910828
3.3.2.1
- Updated APKEditor to 1.4.5
- Updated Apktool to 2.12.1
- Updated Aapt & Zipalign
- Fixed *.zip and *.apkm not selectable for merging
- Export image when clicking on icon box in APK Info
3.3.2.0
- Remove flickering fix due to tabs flickering in Russian language. I will look into WPF for modern UI instead
- Updated tools (Apktool, APKEditor, AAPT, etc.) to latest versions