Coder Social home page Coder Social logo

hexiyou / atool Goto Github PK

View Code? Open in Web Editor NEW

This project forked from chenzhi-ls/atool

0.0 1.0 0.0 1.15 MB

一个用于查看和修改Apk的命令行工具(包名、启动页面名称、Apk名称、版本信息)

License: Apache License 2.0

Batchfile 0.17% Java 99.83%

atool's Introduction

ATool

一、为什么会有ATool?

因为笔者的工作关系,经常需要查看或者修改APK信息(比如:APP名称、敏感权限、版本、包名和icon等信息)。一般,查看APK信息,我们会用到jadx或者aapt等工具来进行查看;而修改包体信息,我们可能会先用apktool对包体进行反编译,然后修改成自己想要的内容后再进行回编签名。

虽然apktool功能强大,基本上已经可以满足我们的需求,但是操作上还是相对比较繁琐。在使用apktool的过程中,笔者就想,能不能在apktool和aapt的基础上开发一个简单好用的工具,同时还可以兼容查看和修改信息的,于是就有了这个工具ATool

二、ATool能做什么?

  • 查看APP信息
    • APP名称
    • APP包名
    • 版本信息
    • 支持安装的版本
    • 启动页面名称
    • APP的icon
    • 导出icon
    • 导出清单文件
  • 修改APP内容
    • 包名
    • 版本名称
    • 版本代号
    • APP名称

关于Apk二次签:

使用ATool修改APP内容后,默认用debug.keystore进行签名打包。我们可以在CmdUtil类中进行修改,替换成自己的签名文件。

三、ATool是怎么工作的?

查看Apk信息:

通过aapt获取Apk的信息(包名、版本、清单文件内容等)

直接获取Apk文件中的二进制文件进行解析、保存,高效快捷!!!

修改Apk内容:

利用apktool对Apk进行反编译和二次打包(我们只需要输入apk路径和替换的内容即可,ATool就会进行自动替换和签名打包,简单快捷!!!)

四、怎么使用ATool?###

我们可以直接通过命令行来使用:

首先进入ATool所在的目录:

查看帮助信息:

输入命令行,完成操作:

五、开发实现

Apk信息获取

我们可以通过aapt查看或者是利用apktool反编译后解析清单文件来获取。这里,因为我们只需要查看信息,所以笔者采用第一种方式,直接利用aapt命令来获取。

对应的aapt命令如下:

aapt.exe d badging [apk路径]

其他常用的aapt命令:

查看APK中的AndroidManifest.xml内容

aapt d xmltree [apk路径] AndroidManifest.xml

查看APK中所用的权限列表

aapt d permissions [apk路径] AndroidManifest.xml

通过在命令行中输入以上命令,我们可以获取到这样的信息:

package: name='com.example.example' versionCode='1' versionName='1.0'
sdkVersion:'8'
targetSdkVersion:'19'
application-label:'Example'
application-icon-160:'res/drawable-mdpi/ic_launcher.png'
application-icon-240:'res/drawable-hdpi/ic_launcher.png'
application-icon-320:'res/drawable-xhdpi/ic_launcher.png'
application-icon-480:'res/drawable-xxhdpi/ic_launcher.png'
application: label='Example' icon='res/drawable-mdpi/ic_launcher.png'
application-debuggable
launchable-activity: name='com.example.example.MainActivity'  label='Example' ic
on=''
uses-feature:'android.hardware.touchscreen'
uses-implied-feature:'android.hardware.touchscreen','assumed you require a touch
screen unless explicitly made optional'
main
supports-screens: 'small' 'normal' 'large' 'xlarge'
supports-any-density: 'true'
densities: '160' '240' '320' '480'

那么接下来, 我们要做的就是去通过这段内容中获取需要的apk信息,主要代码如下:

public static Map<String, String> getAppInfo4Map(String apkPath) {
	if (!FileUtils.getFileFormat(apkPath).equals("apk")) {
		apkPath = apkPath + ".apk";
	}

	BufferedReader bReader = CmdUtil.getCmdResult4Reader("aapt.exe d badging " + apkPath);
	Map<String, String> packageinfoMap = new HashMap<String, String>();

	try {
		String line = "";
		String packageName = "";
		String versionCode = "";
		String versionName = "";
		String appName = "";
		String iconName = "";
		String clearIconPath = "";
		String sdkVersion = "";
		String targetSdkVersion = "";

		while ((line = bReader.readLine()) != null) {
			if (line.contains("package:")) {
				String tempPackageStr = line.split("package: name='")[1];
				packageName = tempPackageStr.substring(0, tempPackageStr.indexOf("'"));

				String tempVersionCode = line.split("versionCode='")[1];
				versionCode = tempVersionCode.substring(0, tempVersionCode.indexOf("'"));

				String tempVersionName = line.split("versionName='")[1];
				versionName = tempVersionName.substring(0, tempVersionName.indexOf("'"));
			}
			if (line.contains("application-label")) {
				appName = line.substring(line.indexOf("'") + 1, line.lastIndexOf("'"));
			}
			if (line.contains("application-icon")) {
				iconName = line.substring(line.lastIndexOf("/") + 1, line.lastIndexOf("'"));
				clearIconPath = line.substring(line.indexOf("'") + 1, line.lastIndexOf("'"));
			}
			if (line.contains("sdkVersion:")) {
				sdkVersion = line.substring(line.indexOf("'") + 1, line.lastIndexOf("'"));
			}
			if (line.contains("targetSdkVersion:")) {
				targetSdkVersion = line.substring(line.indexOf("'") + 1, line.lastIndexOf("'"));
			}
		}
		// 关闭数据流
		bReader.close();
		// 保存我们想要的信息
		packageinfoMap.put("package_name", packageName);
		packageinfoMap.put("version_code", versionCode);
		packageinfoMap.put("version_name", versionName);
		packageinfoMap.put("app_name", appName);
		packageinfoMap.put("icon_name", iconName);
		packageinfoMap.put("clear_icon_path", clearIconPath);
		packageinfoMap.put("min_sdk_version", sdkVersion);
		packageinfoMap.put("target_sdk_version", targetSdkVersion);

	} catch (IOException e) {
		e.printStackTrace();
	}

	return packageinfoMap;
}

另外,可能我们还需要保存Apk的icon和清单文件(后续,我们可以加上窗体界面,直接显示Apk信息),代码如下:

public static void keepTempAppIcon(String apkPath) {
	Map<String, String> infoMap = getAppInfo4Map(apkPath);
	
	if (!FileUtils.getFileFormat(apkPath).equals("apk")) {
		apkPath = apkPath + ".apk";
	}
	ZipUtils zipFileUtils = new ZipUtils();
	zipFileUtils.copyFileFromZip(apkPath, infoMap.get("clear_icon_path"), AToolConstant.TEMP_ICON_NAME);
}

保存清单文件:

public static void keepTempManifestTxtFile(String apkPath) {
	try {
		String xmlContent = AXMLPrinter.getManifestXMLFromAPK(apkPath);
		FileUtils.writeTxtFile(xmlContent, new File(AToolConstant.MANIFEST_TFILE_NAME), "UTF-8");
	} catch (Exception e) {
		e.printStackTrace();
	}
}

保存icon和清单文件都是通过直接操作Apk文件来实现的。

关于APk文件,可以把它理解为是一个压缩文件,所以这里我们可以直接解压,然后把res文件下的icon保存到本地;至于清单文件也是这样,解压获取后再进行转换解析就可以了,具体逻辑请参考工程中的代码实现。

修改Apk内容

笔者是直接同过apktool进行反编译修改后进行二次打包。这里需要对反编译后的清单文件进行解析,修改,然后再进行回编。(后续笔者将加上其他功能,比如修改icon、替换文件等)

这里以修改包名为例,部分代码如下:

public boolean modifyPackage(String targetStr) {
	boolean result = false;
	try {
		if (curDocument == null) {
			noInitCurDoceumntTip();
			return result;
		}
		if (StringUtils.isEmpty(targetStr)) {
			strParamEmpty("新的包名");
			return result;
		}

		result = XmlUtils.modifyElementAttribute(curDocument, "manifest", "package", targetStr, curXmlName);
	} catch (Exception e) {
		e.printStackTrace();
	}

	onResultTip(result, "修改包名 " + targetStr);
	return result;
}

操作反编译后的清单文件:

/**
 * 修改当前只有一个元素的元素属性
 * 
 * @param elementName
 * @param attribute
 * @param targetStr
 * @param parentElement
 * @return
 */
public static boolean modifyElementAttribute(Document curDocument, String elementName, String attribute,
		String targetStr, String newXmlName) {
	boolean result = false;
	NodeList curNodeList = curDocument.getElementsByTagName(elementName);
	for (int i = 0; i < curNodeList.getLength(); i++) {
		if (curNodeList.item(i) instanceof Element) {
			Element manElement = (Element) curNodeList.item(i);
			if (manElement.getAttribute(attribute) != null) {
				manElement.setAttribute(attribute, targetStr);
				break;
			}
		}
	}

	result = commitCurElement(curDocument, newXmlName);
	return result;
}

关于操作xml文件,笔者这里用到的是DOM来实现的。

六、最后

以上就是ATool工具的主要内容,目前功能还相对简单;后续笔者将会添加新的功能(比如替换icon、空文件多渠道打包等),也希望大家多多交流!!!

atool's People

Contributors

chenzhi-ls avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.