NutzCN Logo
问答 Java 怎么获取 Android APK 版本信息 有没有不使用第三方jar包的方式?
发布于 2802天前 作者 sunhai1988 5525 次浏览 复制 上一个帖子 下一个帖子
标签:

Java 怎么获取 Android APK 版本信息 有没有不使用第三方jar包的方式?

13 回复

apk是个zip文件,版本号在AndroidManifest.xml里面,但是这个文件是转义过的,需要一些代码进行反转义的

public static void getAndroidManifestInfo(byte[] bytes) {
		try {
			AXmlResourceParser parser = new AXmlResourceParser();
			StringBuilder indent = new StringBuilder(10);
			parser.open(Streams.wrap(bytes));
			while (true) {
				int type = parser.next();
				if (type == 1) {
					return;
				}
				switch (type) {
				case 0:
					log("<?xml version=\"1.0\" encoding=\"utf-8\"?>", new String[0]);
					break;
				case 2:
					log("%s<%s%s", new Object[] { indent, getNamespacePrefix(parser.getPrefix()), parser.getName() });
					indent.append("\t");
					int namespaceCountBefore = parser.getNamespaceCount(parser.getDepth() - 1);
					int namespaceCount = parser.getNamespaceCount(parser.getDepth());
					for (int i = namespaceCountBefore; i != namespaceCount; ++i) {
						log("%sxmlns:%s=\"%s\"", new Object[] { indent, parser.getNamespacePrefix(i), parser.getNamespaceUri(i) });
					}
					for (int i = 0; i != parser.getAttributeCount(); ++i) {
						log("%s%s%s=\"%s\"", new Object[] { indent, getNamespacePrefix(parser.getAttributePrefix(i)), parser.getAttributeName(i), getAttributeValue(parser, i) });
					}
					log("%s>", new Object[] { indent });
					break;
				case 3:
					indent.setLength(indent.length() - "\t".length());
					log("%s</%s%s>", new Object[] { indent, getNamespacePrefix(parser.getPrefix()), parser.getName() });
					break;
				case 4:
				case 1:
					break;
				}
			}
		} catch (Exception e) {
			log.error(e);
		}
	}
private static String log(String format, Object[] arguments) {
		String str = String.format(format, arguments);
		NAME.get().append(str).append("\n");
		return str;
	}

	private static String getNamespacePrefix(String prefix) {
		if ((prefix == null) || (prefix.length() == 0)) {
			return "";
		}
		return prefix + ":";
	}

	public static final StringBuffer getName() {
		return NAME.get();
	}

贴 UNZip 代码给你

package com.rekoe.decode;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.util.HashSet;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import org.nutz.lang.Files;
import org.nutz.lang.Lang;
import org.nutz.lang.Streams;
import org.nutz.lang.util.Callback2;
import org.nutz.lang.util.Disks;
import org.nutz.lang.util.FileVisitor;
import org.nutz.log.Log;
import org.nutz.log.Logs;

import android.content.res.AXmlResourceParser;

public abstract class UNZip {

	private final static Log log = Logs.get();

	private static final ThreadLocal<StringBuffer> NAME = new ThreadLocal<StringBuffer>();
	private static final float[] RADIX_MULTS = { 0.0039063F, 3.051758E-005F, 1.192093E-007F, 4.656613E-010F };

	private static final String[] DIMENSION_UNITS = { "px", "dip", "sp", "pt", "in", "mm", "", "" };

	private static final String[] FRACTION_UNITS = { "%", "%p", "", "", "", "", "", "" };

	public static void getZipInfo(File file, final Callback2<byte[], File> callback, final String filter, String... suffixs) throws Exception {
		NAME.set(new StringBuffer());
		final Set<String> suffix = new HashSet<String>();
		suffix.addAll(Lang.array2list(suffixs));
		FileFilter ff = new FileFilter() {
			public boolean accept(File pathname) {
				if (pathname.isDirectory())
					return true;
				return suffix.contains(Files.getSuffixName(pathname));
			}
		};
		FileVisitor fv = new FileVisitor() {
			public void visit(File file) {
				if (file.isDirectory())
					return;
				byte[] bytes = getInfoFile(file, filter);
				if (bytes == null) {
					log.errorf("Can not find file %s", filter);
					return;
				}
				callback.invoke(bytes, file);
			}
		};
		Disks.visitFile(file, fv, ff);
	}

	protected static byte[] getInfoFile(File apkFile, String filter) {
		FileInputStream fis = null;
		ByteArrayOutputStream fos = null;
		ZipInputStream zis = null;
		try {
			fis = new FileInputStream(apkFile);
			zis = new ZipInputStream(fis);
			ZipEntry zipEntry = null;
			while ((zipEntry = zis.getNextEntry()) != null) {
				String name = zipEntry.getName();
				if (log.isDebugEnabled()) {
					log.debug(name);
				}
				if (Lang.equals(filter, name)) {
					fos = new ByteArrayOutputStream();
					byte[] buffer = new byte[1024];
					int n = 0;
					while ((n = zis.read(buffer, 0, buffer.length)) != -1) {
						fos.write(buffer, 0, n);
					}
					break;
				}
			}
			zis.closeEntry();
			zipEntry = null;
			return fos.toByteArray();
		} catch (Exception e) {
			log.error(e);
		} finally {
			Streams.safeClose(fos);
			Streams.safeClose(zis);
			Streams.safeClose(fis);
		}
		return null;
	}

	public static void getAndroidManifestInfo(byte[] bytes) {
		try {
			AXmlResourceParser parser = new AXmlResourceParser();
			StringBuilder indent = new StringBuilder(10);
			parser.open(Streams.wrap(bytes));
			while (true) {
				int type = parser.next();
				if (type == 1) {
					return;
				}
				switch (type) {
				case 0:
					log("<?xml version=\"1.0\" encoding=\"utf-8\"?>", new String[0]);
					break;
				case 2:
					log("%s<%s%s", new Object[] { indent, getNamespacePrefix(parser.getPrefix()), parser.getName() });
					indent.append("\t");
					int namespaceCountBefore = parser.getNamespaceCount(parser.getDepth() - 1);
					int namespaceCount = parser.getNamespaceCount(parser.getDepth());
					for (int i = namespaceCountBefore; i != namespaceCount; ++i) {
						log("%sxmlns:%s=\"%s\"", new Object[] { indent, parser.getNamespacePrefix(i), parser.getNamespaceUri(i) });
					}
					for (int i = 0; i != parser.getAttributeCount(); ++i) {
						log("%s%s%s=\"%s\"", new Object[] { indent, getNamespacePrefix(parser.getAttributePrefix(i)), parser.getAttributeName(i), getAttributeValue(parser, i) });
					}
					log("%s>", new Object[] { indent });
					break;
				case 3:
					indent.setLength(indent.length() - "\t".length());
					log("%s</%s%s>", new Object[] { indent, getNamespacePrefix(parser.getPrefix()), parser.getName() });
					break;
				case 4:
				case 1:
					break;
				}
			}
		} catch (Exception e) {
			log.error(e);
		}
	}

	private static String log(String format, Object[] arguments) {
		String str = String.format(format, arguments);
		NAME.get().append(str).append("\n");
		return str;
	}

	private static String getNamespacePrefix(String prefix) {
		if ((prefix == null) || (prefix.length() == 0)) {
			return "";
		}
		return prefix + ":";
	}

	public static final StringBuffer getName() {
		return NAME.get();
	}

	private static String getAttributeValue(AXmlResourceParser parser, int index) {
		int type = parser.getAttributeValueType(index);
		int data = parser.getAttributeValueData(index);
		if (type == 3) {
			return parser.getAttributeValue(index);
		}
		if (type == 2) {
			return String.format("?%s%08X", new Object[] { getPackage(data), Integer.valueOf(data) });
		}
		if (type == 1) {
			return String.format("@%s%08X", new Object[] { getPackage(data), Integer.valueOf(data) });
		}
		if (type == 4) {
			return String.valueOf(Float.intBitsToFloat(data));
		}
		if (type == 17) {
			return String.format("0x%08X", new Object[] { Integer.valueOf(data) });
		}
		if (type == 18) {
			return ((data != 0) ? "true" : "false");
		}
		if (type == 5) {
			return Float.toString(complexToFloat(data)) + DIMENSION_UNITS[(data & 0xF)];
		}
		if (type == 6) {
			return Float.toString(complexToFloat(data)) + FRACTION_UNITS[(data & 0xF)];
		}
		if ((type >= 28) && (type <= 31)) {
			return String.format("#%08X", new Object[] { Integer.valueOf(data) });
		}
		if ((type >= 16) && (type <= 31)) {
			return String.valueOf(data);
		}
		return String.format("<0x%X, type 0x%02X>", new Object[] { Integer.valueOf(data), Integer.valueOf(type) });
	}

	private static float complexToFloat(int complex) {
		return ((complex & 0xFFFFFF00) * RADIX_MULTS[(complex >> 4 & 0x3)]);
	}

	private static String getPackage(int id) {
		if (id >>> 24 == 1) {
			return "android:";
		}
		return "";
	}
}

UNZip.getZipInfo(new File(“apk path”), new Callback2<byte[], File>() {

				@Override
				public void invoke(byte[] bytes, File file) {
					UNZip.getAndroidManifestInfo(bytes);
					StringBuffer sb = UNZip.getName();
					try {
						SAXReader reader = new SAXReader();
						org.dom4j.Document document = reader.read(Streams.wrap(sb.toString().getBytes("utf-8")));
						org.dom4j.Element root = document.getRootElement();
//包信息						
root.attribute("package").getText();
					} catch (Exception e) {
						log.error(e);
					}
				}
			}, "AndroidManifest.xml", "apk");

AXmlResourceParser 在 AXMLPrinter.jar里面吗?

对 你需要jia包
@sunhai1988

@wendal 我在nutz.cn上传jar文件报错呢

请求报文格式错误。(400:token not specified)

@wendal 方便加个jar到jfrog吗? 我把jar放到群文件了

找源码建个github库呗

是在android.com 上下载的。不用自己维护吧


com.github.tony19
apktool-lib
1.4.4-3


com.github.tony19
apktool-lib
1.4.4-3

<dependency>
  <groupId>com.github.tony19</groupId>
  <artifactId>apktool-lib</artifactId>
  <version>1.4.4-3</version>
</dependency>
添加回复
请先登陆
回到顶部