diff --git a/uengine-api/README.md b/uengine-api/README.md new file mode 100755 index 0000000..8630a4e --- /dev/null +++ b/uengine-api/README.md @@ -0,0 +1,109 @@ +# API 介绍 +# 必知 +1. 此 API 只支持可以运行 UEngine 的 Linux 上,Windows 上无法使用 +2. 部分函数需要 root 权限 +3. 这是 UEngine 运行器的函数重构,所以一些 UEngine 运行器上没有的 bug 可能在这个 API 里有 +## ProgramInformation +用于获取一些程序信息,详细如下(未特殊表明的是变量,否则是函数): +| 变量/函数名 | 变量/函数介绍 | +|:-:|:-:| +| programPath | 获取程序所在路径 | +| version | API 版本 | +| updateTime | 更新时间 | +| websize | 程序官网 | +| home | 用户 home(用户文件)目录 | +| developer | 参与的开发者列表 | +| language | 当前语言 | +| DesktopPath() | (函数)用户桌面目录 | + +## Check +用于检查 API 所需的东西是否完整,详细如下: +| 函数名 | 函数介绍 | +|:-:|:-:| +| CheckDepend() | 检查 API 所需的依赖是否完整 | + +## ROOT +用于检查 ROOT 方面问题,详细如下: +| 函数名 | 函数介绍 | +|:-:|:-:| +| GetRoot() | 检查程序/API是否以 ROOT 权限运行 | + +## APK +这是面向对象的写法,所以应用方式也不一样: +```python +import api +xxx = api.APK("APK 所在路径") +``` +具体函数介绍: +| 函数名 | 函数介绍 | +|:-:|:-:| +| xxx.install() | 安装这个 APK 包(需要 Root) | +| xxx.uninstall()| 卸载这个 APK 包(需要 Root) | +| xxx.information()| 获取从 aapt 获取到的 APK 信息 | +| xxx.activityName() | 获取 APK 的 Activity 信息 | +| xxx.packageName() | 获取 APK 包名 | +| xxx.chineseLabel() | 获取 APK 中文名称 | +| xxx.saveApkIcon("图标保存路径") | 保存 APK 的图标到指定路径 | +| xxx.version() | 获取 APK 版本号 | +| xxx.saveDesktopFile("图标保存路径", "快捷方式保存路径") | 保存支持 UEngine 启动的 APK 快捷方式 | +| xxx.run() | 运行该应用(需要保证已经安装) | +| xxx.buildDeb("deb 包保存路径", qianZhui) | 打包为 deb 包(“qianZhui”是布尔值,可略,True代表有前缀为“uengine-dc”,False代表没有前缀) | + +## UEngine +用于对 UEngine 进行一点点操控,详细如下: +| 函数名 | 函数介绍 | +|:-:|:-:| +| UengineAppManager() | 显示 UEngine 安装应用程序管理器 | +| OpenApp("应用包名", "应用Activity") | 运行指定的应用(需要保证程序已经安装) | +| UengineDataClean() | 清空 UEngine 数据(需要 Root) | +| RemoveUengineCheck() | 删除 UEngine 的检查脚本(需要 Root) | +| CPUCheck() | 检查 CPU 是否支持运行 UEngine | +| BuildUengineRootImage() | 构建 UEngine 的 Root 镜像 | +| OpenUengineRootData() | 打开 UEngine 数据目录 | +| InstallRootUengineImage() | 安装已经被 Root 过的 UEngine 镜像(需要 Root) | +| Services | 用于操控 UEngine 服务的类,见下(需要 Root) | +| InternetBridge | 用于操控 UEngine 网络桥接的类,见下(需要 Root) | +### Services +关于 UEngine 的服务控制: +| 函数名 | 函数介绍 | +|:-:|:-:| +| Services.Open() | 打开 UEngine 服务(需要 Root) | +| Services.Close() | 关闭 UEngine 服务(需要 Root) | +| Services.Restart() | 重启 UEngine 服务(需要 Root) | +### InternetBridge +关于 UEngine 的网络桥接控制: +| 函数名 | 函数介绍 | +|:-:|:-:| +| InternetBridge.Open() | 打开 UEngine 网络桥接(需要 Root) | +| InternetBridge.Close() | 关闭 UEngine 网络桥接(需要 Root) | +| InternetBridge.Restart() | 重启 UEngine 网络桥接(需要 Root) | +| InternetBridge.Reload() | 重新加载 UEngine 网络桥接(需要 Root) | +| InternetBridge.ForceReload() | 强制加载 UEngine 网络桥接(需要 Root) | +## Adb +用于对 Adb 的部分操控 +| 函数名 | 函数介绍 | +|:-:|:-:| +| Services | 用于操控 Adb 服务的类,见下 | +### Service +关于 Adb 的服务控制: +| 函数名 | 函数介绍 | +|:-:|:-:| +| Services.Open() | 打开 Adb 服务 | +| Services.Close() | 关闭 Adb 服务 | +| Services.Kill() | 杀死 Adb 进程 | +## File +关于文件的读取和写入,这是面向对象的写法,所以应用方式也不一样: +```python +import api +xxx = api.File("文件所在路径") +``` +| 函数名 | 函数介绍 | +|:-:|:-:| +| xxx.read() | 读取这个文件 | +| xxx.write("写入内容") | 写入这个文件 | + +## UengineRunner +用于 UEngine 运行器的部分操控(请保证安装了 UEngine 运行器) +| 函数名 | 函数介绍 | +|:-:|:-:| +| CleanHistory() | 清理 UEngine 运行器的历史记录 | \ No newline at end of file diff --git a/uengine-api/__init__.py b/uengine-api/__init__.py new file mode 100755 index 0000000..9409c47 --- /dev/null +++ b/uengine-api/__init__.py @@ -0,0 +1,371 @@ +import os +import random +import shutil +import zipfile +import traceback +import subprocess +from getxmlimg import getsavexml + +class ProgramInformation: + programPath = os.path.split(os.path.realpath(__file__))[0] # 返回 string + version = "1.6.0Alpha2" + updateTime = "2022年05月21日" + websize = ["https://gitee.com/gfdgd-xi/uengine-runner", "https://github.com/gfdgd-xi/uengine-runner"] + home = os.path.expanduser('~') + developer = ["gfdgd xi<3025613752@qq.com>", "为什么您不喜欢熊出没和阿布呢<https://weibo.com/u/7755040136>", "星空露光<https://gitee.com/Cynorkyle>", "actionchen<917981399@qq.com>", "柚子<https://gitee.com/Limexb>"] + lang = os.getenv('LANG') + # 获取用户桌面目录 + def DesktopPath() -> "获取用户桌面目录": + for line in open(get_home() + "/.config/user-dirs.dirs"): # 以行来读取配置文件 + desktop_index = line.find("XDG_DESKTOP_DIR=\"") # 寻找是否有对应项,有返回 0,没有返回 -1 + if desktop_index != -1: # 如果有对应项 + break # 结束循环 + if desktop_index == -1: # 如果是提前结束,值一定≠-1,如果是没有提前结束,值一定=-1 + return -1 + else: + get = line[17:-2] # 截取桌面目录路径 + get_index = get.find("$HOME") # 寻找是否有对应的项,需要替换内容 + if get != -1: # 如果有 + get = get.replace("$HOME", get_home()) # 则把其替换为用户目录(~) + return get # 返回目录 + +# 判断程序以正确方式运行 +class Check: + def CheckDepend(): + depend = ["/usr/bin/uengine", "UEngine", "/usr/bin/adb", "adb", "/usr/bin/uengine-session-launch-helper", "UEngine", "/usr/bin/aapt", "aapt"] + for i in range(0, len(depend), 2): + if not os.path.exists(depend[i]): + print("依赖{}不存在".format(depend[i + 1])) + +class ROOT: + def GetRoot(): + return os.geteuid() == 0 + +class APK: + def __init__(self, apkPath): + self.apkPath = apkPath + def install(self): + os.system("pkexec /usr/bin/uengine-session-launch-helper -- uengine install --apk='{}'".format(self.apkPath)) + def uninstall(self): + os.system("pkexec /usr/bin/uengine-session-launch-helper -- uengine uninstall --pkg='{}'".format(self.packageName())) + def information(self): + return subprocess.getoutput("aapt dump badging '{}'".format(self.apkPath)) + def activityName(self): + info = self.information() + for line in info.split('\n'): + if "launchable-activity" in line: + line = line[0: line.index("label='")] + line = line.replace("launchable-activity: ", "") + line = line.replace("'", "") + line = line.replace(" ", "") + line = line.replace("name=", "") + line = line.replace("label=", "") + line = line.replace("icon=", "") + return line + # 获取 apk 包名 + def packageName(self): + info = self.information() + for line in info.split('\n'): + if "package:" in line: + line = line[0: line.index("versionCode='")] + line = line.replace("package:", "") + line = line.replace("name=", "") + line = line.replace("'", "") + line = line.replace(" ", "") + return line + # 获取软件的中文名称 + def chineseLabel(self) -> "获取软件的中文名称": + info = self.information() + for line in info.split('\n'): + if "application-label:" in line: + line = line.replace("application-label:", "") + line = line.replace("'", "") + return line + # 保存apk图标 + def saveApkIcon(self, iconSavePath) -> "保存 apk 文件的图标": + try: + if os.path.exists(iconSavePath): + os.remove(iconSavePath) + info = self.information() + for line in info.split('\n'): + if "application:" in line: + xmlpath = line.split(":")[-1].split()[-1].split("=")[-1].replace("'", "") + if xmlpath.endswith('.xml'): + xmlsave = getsavexml() + print(xmlpath) + xmlsave.savexml(self.apkPath, xmlpath, iconSavePath) + return + else: + zip = zipfile.ZipFile(self.apkPath) + iconData = zip.read(xmlpath) + with open(iconSavePath, 'w+b') as saveIconFile: + saveIconFile.write(iconData) + return + print("None Icon! Show defult icon") + shutil.copy(ProgramInformation.programPath + "/defult.png", iconSavePath) + except: + traceback.print_exc() + print("Error, show defult icon") + shutil.copy(ProgramInformation.programPath + "/defult.png", iconSavePath) + def version(self): + info = self.information() + for line in info.split('\n'): + if "package:" in line: + if "compileSdkVersion='" in line: + line = line.replace(line[line.index("compileSdkVersion='"): -1], "") + if "platform" in line: + line = line.replace(line[line.index("platform"): -1], "") + line = line.replace(line[0: line.index("versionName='")], "") + line = line.replace("versionName='", "") + line = line.replace("'", "") + line = line.replace(" ", "") + return line + def saveDesktopFile(self, desktopPath, iconPath): + showName = self.chineseLabel() + if showName == "" or showName == None: + showName = "未知应用" + self.saveApkIcon(iconPath) + things = '''[Desktop Entry] + Categories=app; + Encoding=UTF-8 + Exec=uengine launch --action=android.intent.action.MAIN --package={} --component={} + GenericName={} + Icon={} + MimeType= + Name={} + StartupWMClass={} + Terminal=false + Type=Application + '''.format(self.packageName(), self.activityName(), showName, iconPath, showName, showName) + File(desktopPath).write(things) + def run(self): + UEngine.OpenApp(self.packageName(), self.activityName()) + + def buildDeb(self, savePath, qianZhui = True): + tempPath = "/tmp/uengine-apk-builder-{}".format(int(random.randint(0, 1024))) + #RunCommandShow("echo '======================================New===================================='") + #RunCommandShow("echo '创建目录'") + os.makedirs("{}/DEBIAN".format(tempPath)) + os.makedirs("{}/usr/share/applications".format(tempPath)) + os.makedirs("{}/usr/share/uengine/apk".format(tempPath)) + os.makedirs("{}/usr/share/uengine/icons".format(tempPath)) + apkPackageName = self.packageName() + if qianZhui: + apkPackageNameNew = "uengine-dc-" + self.packageName().lower() + else: + apkPackageNameNew = self.packageName().lower() + apkPackageVersion = self.version() + if apkPackageVersion[0].upper() == "V": + package = list(apkPackageVersion) + package.pop(0) + apkPackageVersion = "".join(package) + apkChineseLabel = self.chineseLabel() + apkActivityName = self.activityName() + iconSavePath = "{}/usr/share/uengine/icons/{}.png".format(tempPath, apkPackageNameNew) + debControl = '''Package: {} +Version: {} +Architecture: all +Maintainer: {} +Depends: deepin-elf-verify (>= 0.0.16.7-1), uengine (>= 1.0.1) +Section: utils +Priority: optional +Description: {}\n'''.format(apkPackageNameNew, apkPackageVersion, apkChineseLabel, apkChineseLabel) + debPostinst = '''#!/bin/sh + +APK_DIR="/usr/share/uengine/apk" +APK_NAME="{}" +APK_PATH="$APK_DIR/$APK_NAME" +DESKTOP_FILE="{}" + + +if [ -f $APK_PATH ]; then + echo "Installing $APK_NAME" +else + echo "ERROR: $APK_NAME does not exist." + exit 0 +fi + +session_manager=`ps -ef | grep "uengine session-manager" | grep -v grep` +if test -z "$session_manager"; then + echo "ERROR: app install failed(session-manager is not running)." + sess_dir="/usr/share/uengine/session_install" + if [ ! -d $sess_dir ]; then + mkdir $sess_dir + chmod 777 $sess_dir + fi + apk_name=${{APK_PATH##*/}} + fileName="$sess_dir/$apk_name" + echo $DESKTOP_FILE > $fileName + abistr="" + if test -n "$abistr"; then + abi=`echo $abistr |awk -F \= '{{print $2}}'` + echo $abi >> $fileName + fi + chmod 766 $fileName +fi + +/usr/bin/uengine-session-launch-helper -- uengine install --apk="$APK_PATH" + +exit 0'''.format(apkPackageNameNew + ".apk", "/usr/share/applications/{}.desktop".format(apkPackageNameNew)) + debPrerm = '''#!/bin/sh + +APP_NAME="{}" +DESKTOP_FILE="{}" + +session_manager=`ps -ef | grep "uengine session-manager" | grep -v grep` +if test -z "$session_manager"; then + echo "ERROR: app uninstall failed(session-manager is not running)." + sess_dir="/usr/share/uengine/session_uninstall" + if [ ! -d $sess_dir ]; then + mkdir $sess_dir + chmod 777 $sess_dir + fi + fileName="$sess_dir/$APP_NAME" + echo $DESKTOP_FILE > $fileName + chmod 766 $fileName +fi + +echo "Uninstalling $APP_NAME" +/usr/bin/uengine-session-launch-helper -- uengine uninstall --pkg="$APP_NAME" + +exit 0'''.format(apkPackageName, "/usr/share/applications/{}.desktop".format(apkPackageNameNew)) + desktopFile = '''[Desktop Entry] +Categories=Other; +Exec=uengine launch --action=android.intent.action.MAIN --package={} --component={} +Icon=/usr/share/uengine/icons/{}.png +Terminal=false +Type=Application +GenericName={} +Name={} +''' + # RunCommandShow("echo '{}' > '{}/DEBIAN/control'".format(debControl, tempPath)) + #RunCommandShow("echo 正在写入文件:'{}/DEBIAN/control'".format(tempPath)) + File("{}/DEBIAN/control".format(tempPath)).write(debControl) + #RunCommandShow("echo 正在写入文件:'{}/DEBIAN/postinst'".format(tempPath)) + File("{}/DEBIAN/postinst".format(tempPath)).write(debPostinst) + #RunCommandShow("echo 正在写入文件:'{}/DEBIAN/prerm'".format(tempPath)) + File("{}/DEBIAN/prerm".format(tempPath)).write(debPrerm) + #RunCommandShow("echo 正在写入文件:'/usr/share/applications/{}.desktop'".format(apkPackageNameNew)) + # write_txt("{}/usr/share/applications/{}.desktop".format(tempPath, apkPackageNameNew), desktopFile) + self.saveDesktopFile("{}/usr/share/applications/{}.desktop".format(tempPath, apkPackageNameNew), + "{}/usr/share/uengine/icons/{}.png".format(tempPath, apkPackageNameNew)) + #BuildUengineDesktop(apkPackageName, apkActivityName, apkChineseLabel, + # "/usr/share/uengine/icons/{}.png".format(apkPackageNameNew), + # "{}/usr/share/applications/{}.desktop".format(tempPath, apkPackageNameNew)) + #RunCommandShow("echo '复制文件'") + #RunCommandShow("echo '写入 APK 软件图标'") + #SaveApkIcon(apkPath, iconSavePath) + self.saveApkIcon(iconSavePath) + #RunCommandShow("echo '复制 APK 文件'") + shutil.copy(self.apkPath, "{}/usr/share/uengine/apk/{}.apk".format(tempPath, apkPackageNameNew)) + #RunCommandShow("cp -rv '{}' '{}/usr/share/uengine/apk/{}.apk'".format(apkPath, tempPath, apkPackageNameNew)) + #RunCommandShow("echo '正在设置文件权限……'") + os.system("chmod 0775 -vR '{}/DEBIAN/postinst'".format(tempPath)) + os.system("chmod 0775 -vR '{}/DEBIAN/prerm'".format(tempPath)) + #RunCommandShow("echo '打包 deb 到桌面……'") + os.system( + "dpkg -b '{}' '{}'".format(tempPath, savePath)) + #RunCommandShow("echo '正在删除临时目录……'") + #shutil.rmtree(tempPath) + #RunCommandShow("rm -rfv '{}'".format(tempPath)) + #RunCommandShow("echo '完成!'") + #findApkHistory.append(apkPath) + #combobox1['value'] = findApkHistory + #write_txt(get_home() + "/.config/uengine-runner/FindApkBuildHistory.json", + # str(json.dumps(ListToDictionary(findApkHistory)))) # 将历史记录的数组转换为字典并写入 + #messagebox.showinfo(title="提示", message="打包完成") + #DisabledAndEnbled(False) + + +class UEngine: + def UengineAppManager(): + os.system("uengine launch --package=org.anbox.appmgr --component=org.anbox.appmgr.AppViewActivity") + def OpenApp(appPackage, appActivity): + os.system("uengine launch --package={} --component={}".format(appPackage, appActivity)) + # 清空 uengine 数据 + def UengineDataClean() -> "清空 uengine 数据": + shutil.rmtree("{}/.local/share/applications/uengine/".format(ProgramInformation.home)) + shutil.rmtree("/data/uengine") + def RemoveUengineCheck(): + os.remove("/usr/share/uengine/uengine-check-runnable.sh") + def CPUCheck(): + return subprocess.getoutput("uengine check-features") + def BuildUengineRootImage(): + os.system(ProgramInformation.programPath + "/root-uengine.sh") + def OpenUengineRootData(): + os.system("xdg-open /data/uengine/data/data") + def InstallRootUengineImage(): + if not os.path.exists: + os.mkdir("/tmp/uengine-runner") + File("/tmp/uengine-runner/install.sh").write("sudo dpkg -i /tmp/uengine-runner/u*.deb\nsudo apt install -f") + os.system("wget -P '/tmp/uengine-runner' 'https://hub.fastgit.xyz/gfdgd-xi/uengine-runner/releases/download/U1.2.15/uengine-android-image_1.2.15_amd64.deb' && pkexec bash '/tmp/uengine-runner/install.sh'") + class Services: + def Open(): + os.system("pkexec systemctl enable uengine-container uengine-session && systemctl start uengine-container uengine-session") + def Close(): + os.system("pkexec systemctl disable uengine-container uengine-session") + def Restart(): + os.system("pkexec systemctl restart uengine*") + class InternetBridge: + def Open(): + os.system("pkexec uengine-bridge.sh start") + def Close(): + os.system("pkexec uengine-bridge.sh stop") + def Restart(): + os.system("pkexec uengine-bridge.sh restart") + def Reload(): + os.system("pkexec uengine-bridge.sh reload") + def ForceReload(): + os.system("pkexec uengine-bridge.sh force-reload") + +class Adb: + def __init__(self, ip=""): + self.ip = ip + + def connect(self): + os.system(f"adb connect {self.ip}") + + class Service: + def Open(): + os.system("adb start-server") + def Close(): + os.system("adb kill-server") + def Kill(): + os.system("killall adb") + + def boolAndroidInstallOtherAppSetting(self): + return subprocess.getoutput(f"adb -s {self.ip} shell settings get secure install_non_market_apps").replace(" ", "") == "1" + + def setAndroidInstallOtherAppSetting(self, op: bool): + os.system(f"adb -s {self.ip} shell settings put secure install_non_market_apps {int(op)}") + +class File: + def __init__(self, filePath): + self.filePath = filePath + def read(self): + f = open(self.filePath, "r") # 设置文件对象 + str = f.read() # 获取内容 + f.close() # 关闭文本对象 + return str # 返回结果 + def write(self, things) -> "写入文本文档": + TxtDir = os.path.dirname(self.filePath) + print(TxtDir) + if not os.path.exists(TxtDir): + os.makedirs(TxtDir, exist_ok=True) + file = open(self.filePath, 'w', encoding='UTF-8') # 设置文件对象 + file.write(things) # 写入文本 + file.close() # 关闭文本对象 + +class UengineRunner: + def CleanHistory(): + shutil.rmtree(ProgramInformation.home + "/.config/uengine-runner") + +if __name__ == "__main__": + print("本 API 不支持直接运行,请通过引入的方式使用此 API") + adb = Adb("192.168.250.2:5555") + print(adb.boolAndroidInstallOtherAppSetting()) + + quit() + +if not ROOT.GetRoot(): + print("请获取 ROOT 权限以便更好的使用该 API") \ No newline at end of file diff --git a/uengine-api/__pycache__/__init__.cpython-310.pyc b/uengine-api/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000..d5c6100 Binary files /dev/null and b/uengine-api/__pycache__/__init__.cpython-310.pyc differ diff --git a/uengine-api/__pycache__/__init__.cpython-37.pyc b/uengine-api/__pycache__/__init__.cpython-37.pyc new file mode 100644 index 0000000..2bd853a Binary files /dev/null and b/uengine-api/__pycache__/__init__.cpython-37.pyc differ diff --git a/uengine-api/__pycache__/getxmlimg.cpython-37.pyc b/uengine-api/__pycache__/getxmlimg.cpython-37.pyc new file mode 100755 index 0000000..79021ab Binary files /dev/null and b/uengine-api/__pycache__/getxmlimg.cpython-37.pyc differ diff --git a/uengine-api/defult.png b/uengine-api/defult.png new file mode 100755 index 0000000..c836b68 Binary files /dev/null and b/uengine-api/defult.png differ diff --git a/uengine-api/getxmlimg.py b/uengine-api/getxmlimg.py new file mode 100755 index 0000000..af59a70 --- /dev/null +++ b/uengine-api/getxmlimg.py @@ -0,0 +1,118 @@ +import PIL.Image as Image +import PIL.ImageDraw as ImageDraw +import zipfile +import subprocess +import re + +class getsavexml(): + + def savexml(self,apkFilePath,xmlpath,iconSavePath): + cmddumpid = "aapt dump xmltree "+ apkFilePath + " " + xmlpath + print(cmddumpid) + xmltree = subprocess.getoutput(cmddumpid) + xmls = xmltree.splitlines() + # find strs ,print next line + def FindStrs(lines,strs): + i=0 + while i < len(lines): + if re.search(strs,lines[i]): + tmpstr = lines[i+1] + i += 1 + Resultstr = tmpstr.split(":")[-1].split("=")[-1].split("0x")[-1] + return Resultstr + else: + i += 1 + #从apk的信息中获取前后景图片的ID号 + backimgid = FindStrs(xmls,"background") + foreimgid = FindStrs(xmls,"foreground") + print(backimgid) + print(foreimgid) + + # 直接从apk resource文件获取前后两层图片路径及ID字符串 + resource = subprocess.getoutput("aapt dump --values resources " + apkFilePath + "| grep -iE -A1 " + "\"" + backimgid + "|" + foreimgid + "\"") + resourcelines = resource.splitlines() + print(resourcelines) + + # 从过滤出的字符串中获取所有相同ID的图片路径 + def Findpicpath(lines,imgid): + i=0 + Resultstr = [] + while i < len(lines): + if re.search(imgid,lines[i]) and re.search("string8",lines[i+1]) : + print(lines[i+1]) + tmpstr = lines[i+1].replace("\"","") + i += 1 + Resultstr.append(tmpstr.split()[-1]) + else: + i += 1 + return Resultstr + + #获取所有带前后图片ID的图片路径(相同背景或者前景的图片ID但分辨率不一样) + backimgs = Findpicpath(resourcelines,backimgid) + foreimgs = Findpicpath(resourcelines,foreimgid) + print(backimgs) + print(foreimgs) + #获取分辨率最高的图片路径 + def getmaxsize(imgs): + j = 0 + size=(0,0) + zipapk = zipfile.ZipFile(apkFilePath) + imgpath = "" + while j < len(imgs): + print(imgs[j]) + img = Image.open(zipapk.open(imgs[j])) + print(imgs[j]) + print(img.size) + if size < img.size: + size = img.size + imgpath = imgs[j] + j += 1 + return imgpath + + # 获取到文件列表后,进行比较分辨率,选取分辨率最高的张图片 + iconbackpath = getmaxsize(backimgs) + iconforepath = getmaxsize(foreimgs) + print(iconbackpath + " " + iconforepath) + + #从APK文件获取最终图片 + zipapk = zipfile.ZipFile(apkFilePath) + iconback = zipapk.open(iconbackpath) + iconfore = zipapk.open(iconforepath) + + + # 叠加图片,mask 设置前景为蒙版 + iconbackimg = Image.open(iconback).convert("RGBA") + iconforeimg = Image.open(iconfore).convert("RGBA") + iconbackimg.paste(iconforeimg,mask=iconforeimg) + + + # 圆角图片函数,网上拷贝的 + def circle_corner(img, radii): #把原图片变成圆角,这个函数是从网上找的,原址 https://www.pyget.cn/p/185266 + """ + 圆角处理 + :param img: 源图象。 + :param radii: 半径,如:30。 + :return: 返回一个圆角处理后的图象。 + """ + # 画圆(用于分离4个角) + circle = Image.new('L', (radii * 2, radii * 2), 0) # 创建一个黑色背景的画布 + draw = ImageDraw.Draw(circle) + draw.ellipse((0, 0, radii * 2, radii * 2), fill=255) # 画白色圆形 + # 原图 + img = img.convert("RGBA") + w, h = img.size + # 画4个角(将整圆分离为4个部分) + alpha = Image.new('L', img.size, 255) + alpha.paste(circle.crop((0, 0, radii, radii)), (0, 0)) # 左上角 + alpha.paste(circle.crop((radii, 0, radii * 2, radii)), (w - radii, 0)) # 右上角 + alpha.paste(circle.crop((radii, radii, radii * 2, radii * 2)), (w - radii, h - radii)) # 右下角 + alpha.paste(circle.crop((0, radii, radii, radii * 2)), (0, h - radii)) # 左下角 + # alpha.show() + img.putalpha(alpha) # 白色区域透明可见,黑色区域不可见 + return img + + # 圆角半径1/8边长,保存icon图片 + w,h = iconbackimg.size + iconimg = circle_corner(iconbackimg,int(w/8)) + iconimg.save(iconSavePath) + diff --git a/uengine-api/root-uengine.sh b/uengine-api/root-uengine.sh new file mode 100755 index 0000000..335f765 --- /dev/null +++ b/uengine-api/root-uengine.sh @@ -0,0 +1,76 @@ +#!/bin/bash + +#sudo apt install squashfs-tools + +mkdir -p ~/temp +cd ~/temp +echo "正在下载supersu" +aria2c -x 16 -s 16 -d ~/temp http://supersuroot.org/downloads/SuperSU-v2.82-201705271822.zip +cd .. +mkdir -p ~/temp/work/dabao/extract/DEBIAN +echo "正在解压supersu" +unzip ~/temp/SuperSU-v2.82-201705271822.zip -d ~/temp/work/su +WORKDIR=~/temp/work +cd "$WORKDIR" +echo "正在下载uengine-android-image" +apt download uengine-android-image +echo "正在解压uengine-android-image" +cd dabao +dpkg-deb -x $WORKDIR/uengine-android-image*.deb extract/ +dpkg-deb -e $WORKDIR/uengine-android-image*.deb extract/DEBIAN +cd .. +cp dabao/extract/usr/share/uengine/android.img android.img + +echo "正在解压android镜像" +sudo unsquashfs android.img + +sudo mkdir -p ./squashfs-root/system/app/SuperSU +sudo mkdir -p ./squashfs-root/system/bin/.ext/ + +echo "正在将supersu安装到android镜像" +sudo cp ./su/common/Superuser.apk ./squashfs-root/system/app/SuperSU/SuperSU.apk +sudo cp ./su/common/install-recovery.sh ./squashfs-root/system/etc/install-recovery.sh +sudo cp ./su/common/install-recovery.sh ./squashfs-root/system/bin/install-recovery.sh +sudo cp ./su/x64/su ./squashfs-root/system/xbin/su +sudo cp ./su/x64/su ./squashfs-root/system/bin/.ext/.su +sudo cp ./su/x64/su ./squashfs-root/system/xbin/daemonsu +sudo cp ./su/x64/supolicy ./squashfs-root/system/xbin/supolicy +sudo cp ./su/x64/libsupol.so ./squashfs-root/system/lib64/libsupol.so +sudo cp ./squashfs-root/system/bin/app_process64 ./squashfs-root/system/bin/app_process_init +sudo cp ./squashfs-root/system/bin/app_process64 ./squashfs-root/system/bin/app_process64_original +sudo cp ./squashfs-root/system/xbin/daemonsu ./squashfs-root/system/bin/app_process +sudo cp ./squashfs-root/system/xbin/daemonsu ./squashfs-root/system/bin/app_process64 + +sudo chmod +x ./squashfs-root/system/app/SuperSU/SuperSU.apk +sudo chmod +x ./squashfs-root/system/etc/install-recovery.sh +sudo chmod +x ./squashfs-root/system/bin/install-recovery.sh +sudo chmod +x ./squashfs-root/system/xbin/su +sudo chmod +x ./squashfs-root/system/bin/.ext/.su +sudo chmod +x ./squashfs-root/system/xbin/daemonsu +sudo chmod +x ./squashfs-root/system/xbin/supolicy +sudo chmod +x ./squashfs-root/system/lib64/libsupol.so +sudo chmod +x ./squashfs-root/system/bin/app_process_init +sudo chmod +x ./squashfs-root/system/bin/app_process64_original +sudo chmod +x ./squashfs-root/system/bin/app_process +sudo chmod +x ./squashfs-root/system/bin/app_process64 + +echo "正在打包android镜像" +sudo rm android.img +sudo mksquashfs squashfs-root android.img -b 131072 -comp xz -Xbcj ia64 + + +cp android.img dabao/extract/usr/share/uengine/android.img + +echo "正在打包uengine-android-image" +cd dabao/extract +find usr -type f -print0 |xargs -0 md5sum >md5sums +cd .. +mkdir build +dpkg-deb -b extract/ build/ + +cp build/*.deb ~/ + +echo "正在清理垃圾" +sudo rm -rf ~/temp + +echo "已在用户主目录生成新的安装包,安装后重启即可生效" \ No newline at end of file