init
This commit is contained in:
224
page1.py
Normal file
224
page1.py
Normal file
@@ -0,0 +1,224 @@
|
||||
import customtkinter as ctk
|
||||
from tkinter import filedialog
|
||||
import os
|
||||
import subprocess
|
||||
import threading
|
||||
|
||||
CREATE_NO_WINDOW = 0x08000000
|
||||
|
||||
class Page1:
|
||||
def __init__(self, parent):
|
||||
self.parent = parent
|
||||
self.frame = ctk.CTkFrame(parent)
|
||||
self.frame.pack(fill=ctk.BOTH, expand=True)
|
||||
|
||||
self.work_dir = "apk_work"
|
||||
rootPath = os.path.dirname(os.path.abspath(__file__))
|
||||
self.apktool_jar_path = os.path.join(rootPath, "apktool_2.11.1.jar")
|
||||
self.uber_jar_path = os.path.join(rootPath, "uber-apk-signer.jar")
|
||||
|
||||
self.jdk_path = os.path.join(rootPath, r"jdk-21.0.7\bin\java.exe")
|
||||
|
||||
self.apk_path = ""
|
||||
|
||||
ctk.CTkLabel(self.frame, text="Page 1: Extract and compress APK").pack(pady=10)
|
||||
|
||||
file_frame = ctk.CTkFrame(self.frame)
|
||||
file_frame.pack(pady=5)
|
||||
|
||||
self.label_apk = ctk.CTkLabel(file_frame, text="Not selected APK file")
|
||||
self.label_apk.pack(pady=3)
|
||||
|
||||
self.btn_choose_apk = ctk.CTkButton(file_frame, text="Choose APK file", command=self.choose_apk)
|
||||
self.btn_choose_apk.pack(pady=3)
|
||||
|
||||
self.btn_extract = ctk.CTkButton(file_frame, text="Extract APK", command=self.extract_apk, state=ctk.DISABLED)
|
||||
self.btn_extract.pack(pady=10)
|
||||
|
||||
name_frame = ctk.CTkFrame(self.frame)
|
||||
name_frame.pack(pady=10)
|
||||
|
||||
ctk.CTkLabel(name_frame, text="APK output name:").pack(side=ctk.LEFT)
|
||||
self.name_entry = ctk.CTkEntry(name_frame, width=400)
|
||||
self.name_entry.insert(0, "StarRail")
|
||||
self.name_entry.pack(side=ctk.LEFT, padx=5)
|
||||
self.btn_compress = ctk.CTkButton(self.frame, text="Compress and sign APK", command=self.compress_apk)
|
||||
self.btn_compress.pack(pady=5)
|
||||
|
||||
self.loading_label = ctk.CTkLabel(self.frame, text="")
|
||||
self.loading_label.pack(pady=5)
|
||||
|
||||
self.log_output = ctk.CTkTextbox(self.frame, width=600, height=200, corner_radius=0)
|
||||
self.log_output.pack(pady=5)
|
||||
|
||||
|
||||
def compress_apk(self):
|
||||
if not self.work_dir:
|
||||
self.log_output.insert(ctk.END, "Not found work directory\n")
|
||||
return
|
||||
|
||||
apk_name = self.name_entry.get()
|
||||
if not apk_name:
|
||||
self.log_output.insert(ctk.END, "Not found apk name\n")
|
||||
return
|
||||
|
||||
self.loading_label.configure(text="Compressing APK...")
|
||||
self.btn_compress.configure(state=ctk.DISABLED)
|
||||
self.log_output.insert(ctk.END, f"Compressing APK {apk_name}...\n")
|
||||
|
||||
threading.Thread(target=self.compress_apk_thread, daemon=True, args=(apk_name,)).start()
|
||||
|
||||
def compress_apk_thread(self, apk_name):
|
||||
try:
|
||||
decompiled_dir = os.path.join(self.work_dir)
|
||||
compressed_apk = f"{apk_name}.apk"
|
||||
|
||||
cmd = [self.jdk_path,
|
||||
"-jar", self.apktool_jar_path,
|
||||
"b", decompiled_dir,
|
||||
"-o", compressed_apk]
|
||||
|
||||
self.log_output.insert(ctk.END, "Running apktool to compress...\n")
|
||||
|
||||
process = subprocess.Popen(cmd, creationflags=CREATE_NO_WINDOW, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
|
||||
while True:
|
||||
output = process.stdout.readline()
|
||||
if output == '' and process.poll() is not None:
|
||||
break
|
||||
if output:
|
||||
self.log(output.strip())
|
||||
rc = process.poll()
|
||||
|
||||
if rc != 0:
|
||||
self.log(f"Error when compress APK: Process returned code {rc}")
|
||||
return False
|
||||
|
||||
self.log("Signing APK using Uber...")
|
||||
|
||||
|
||||
if not os.path.exists(self.uber_jar_path):
|
||||
self.log(f"Error: Cannot find uber-apk-signer at {self.uber_jar_path}")
|
||||
self.log("Please make sure uber-apk-signer.jar is in the correct location")
|
||||
return False
|
||||
|
||||
uber_cmd = [self.jdk_path,
|
||||
"-jar", self.uber_jar_path,
|
||||
"-a", compressed_apk]
|
||||
|
||||
process = subprocess.Popen(uber_cmd, creationflags=CREATE_NO_WINDOW, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
|
||||
while True:
|
||||
output = process.stdout.readline()
|
||||
if output == '' and process.poll() is not None:
|
||||
break
|
||||
if output:
|
||||
self.log(output.strip())
|
||||
rc = process.poll()
|
||||
|
||||
if rc != 0:
|
||||
self.log(f"Error when sign APK: Process returned code {rc}")
|
||||
return False
|
||||
|
||||
signed_apk = f"{apk_name}-aligned-debugSigned.apk"
|
||||
signed_id = f"{apk_name}-aligned-debugSigned.apk.idsig"
|
||||
if os.path.exists(signed_apk):
|
||||
if os.path.exists(compressed_apk):
|
||||
os.remove(compressed_apk)
|
||||
os.rename(signed_apk, compressed_apk)
|
||||
self.log(f"Successfully renamed signed APK to {compressed_apk}")
|
||||
else:
|
||||
self.log("Warning: Signed APK not found")
|
||||
|
||||
if os.path.exists(signed_id):
|
||||
os.remove(signed_id)
|
||||
|
||||
self.loading_label.configure(text="Completed!")
|
||||
self.log("Completed compressing and signing APK!")
|
||||
|
||||
except Exception as e:
|
||||
self.log(f"Error: {str(e)}")
|
||||
finally:
|
||||
self.btn_compress.configure(state=ctk.NORMAL)
|
||||
|
||||
|
||||
def choose_apk(self):
|
||||
file_path = filedialog.askopenfilename(
|
||||
title="Choose APK file",
|
||||
filetypes=[("APK files", "*.apk")]
|
||||
)
|
||||
if file_path:
|
||||
self.apk_path = file_path
|
||||
self.label_apk.configure(text=f"File APK: {file_path}")
|
||||
self.btn_extract.configure(state=ctk.NORMAL)
|
||||
self.log(f"Selected APK file: {file_path}")
|
||||
|
||||
def extract_apk(self):
|
||||
threading.Thread(target=self.extract_apk_thread, daemon=True).start()
|
||||
|
||||
def extract_apk_thread(self):
|
||||
if not self.apk_path:
|
||||
self.log_output.insert(ctk.END, "Not found apk path\n")
|
||||
return
|
||||
|
||||
try:
|
||||
self.loading_label.configure(text="Extracting APK...")
|
||||
self.btn_extract.configure(state=ctk.DISABLED)
|
||||
self.btn_choose_apk.configure(state=ctk.DISABLED)
|
||||
|
||||
self.log_output.delete(1.0, ctk.END)
|
||||
|
||||
if os.path.exists(self.work_dir):
|
||||
try:
|
||||
import time
|
||||
time.sleep(1)
|
||||
|
||||
for root, dirs, files in os.walk(self.work_dir, topdown=False):
|
||||
for name in files:
|
||||
try:
|
||||
file_path = os.path.join(root, name)
|
||||
os.chmod(file_path, 0o777)
|
||||
os.remove(file_path)
|
||||
except Exception as e:
|
||||
self.log(f"Cannot remove file {file_path}: {e}")
|
||||
for name in dirs:
|
||||
try:
|
||||
dir_path = os.path.join(root, name)
|
||||
os.rmdir(dir_path)
|
||||
except Exception as e:
|
||||
self.log(f"Cannot remove directory {dir_path}: {e}")
|
||||
|
||||
try:
|
||||
os.rmdir(self.work_dir)
|
||||
except Exception as e:
|
||||
self.log(f"Cannot remove directory {self.work_dir}: {e}")
|
||||
|
||||
self.log(f"Deleted old folder {self.work_dir}")
|
||||
except Exception as e:
|
||||
self.log(f"Error when removing folder {self.work_dir}: {e}")
|
||||
return False
|
||||
|
||||
decode_cmd = [self.jdk_path, "-jar", self.apktool_jar_path, "d", self.apk_path, "-f", "-o", self.work_dir]
|
||||
process = subprocess.Popen(decode_cmd, creationflags=CREATE_NO_WINDOW, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
|
||||
while True:
|
||||
output = process.stdout.readline()
|
||||
if output == '' and process.poll() is not None:
|
||||
break
|
||||
if output:
|
||||
self.log(output.strip())
|
||||
rc = process.poll()
|
||||
|
||||
if rc == 0:
|
||||
self.log(f"Extracted APK to folder {self.work_dir}")
|
||||
else:
|
||||
self.log(f"Error when extracting APK: Process returned code {rc}")
|
||||
return False
|
||||
except Exception as e:
|
||||
self.log(f"Error when extracting APK: {e}")
|
||||
return False
|
||||
finally:
|
||||
self.loading_label.configure(text="")
|
||||
self.btn_extract.configure(state=ctk.NORMAL)
|
||||
self.btn_choose_apk.configure(state=ctk.NORMAL)
|
||||
|
||||
def log(self, msg):
|
||||
self.log_output.insert(ctk.END, f"{msg}\n")
|
||||
self.log_output.see(ctk.END)
|
||||
Reference in New Issue
Block a user