Skip to content

Instantly share code, notes, and snippets.

@nukc
Created January 18, 2017 09:10
Show Gist options
  • Save nukc/f762f73276c4ad02618147acd6978d16 to your computer and use it in GitHub Desktop.
Save nukc/f762f73276c4ad02618147acd6978d16 to your computer and use it in GitHub Desktop.
获取 apk 文件注释里的渠道号
package com.github.nukc.plugin;
import java.io.DataInput;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;
/**
* Created by Nukc.
* Base on https://github.com/mcxiaoke/packer-ng-plugin/blob/master/helper/src/main/java/com/mcxiaoke/packer/helper/PackerNg.java
*/
public class ZipCommentHelper {
private static final byte[] COMMENT_SIGN = new byte[]{99, 104, 97, 110, 110, 101, 108}; //channel
private static final String EMPTY_STRING = "";
private static String sCachedChannel;
public static String getChannel(final Object context) {
return getChannel(context, EMPTY_STRING);
}
public static synchronized String getChannel(final Object context, final String defaultValue) {
if (sCachedChannel == null) {
sCachedChannel = getChannelInternal(context, defaultValue).channel;
}
return sCachedChannel;
}
public static ChannelInfo getChannelInfo(final Object context) {
return getChannelInfo(context, EMPTY_STRING);
}
public static synchronized ChannelInfo getChannelInfo(final Object context, final String defaultValue) {
return getChannelInternal(context, defaultValue);
}
private static ChannelInfo getChannelInternal(final Object context, final String defaultValue) {
String market;
Exception error;
try {
final String sourceDir = getSourceDir(context);
market = readZipComment(new File(sourceDir));
error = null;
} catch (Exception e) {
market = null;
error = e;
}
return new ChannelInfo(market == null ? defaultValue : market, error);
}
public static final class ChannelInfo {
public final String channel;
public final Exception error;
public ChannelInfo(final String channel, final Exception error) {
this.channel = channel;
this.error = error;
}
@Override
public String toString() {
return "ChannelInfo{" +
"channel='" + channel + '\'' +
", error=" + error +
'}';
}
}
// for android code
private static String getSourceDir(final Object context) throws ClassNotFoundException,
InvocationTargetException, IllegalAccessException, NoSuchFieldException, NoSuchMethodException {
final Class<?> contextClass = Class.forName("android.content.Context");
final Class<?> applicationInfoClass = Class.forName("android.content.pm.ApplicationInfo");
final Method getApplicationInfoMethod = contextClass.getMethod("getApplicationInfo");
final Object appInfo = getApplicationInfoMethod.invoke(context);
// try ApplicationInfo.publicSourceDir
final Field publicSourceDirField = applicationInfoClass.getField("publicSourceDir");
String sourceDir = (String) publicSourceDirField.get(appInfo);
if (sourceDir == null) {
// try ApplicationInfo.sourceDir
final Field sourceDirField = applicationInfoClass.getField("sourceDir");
sourceDir = (String) sourceDirField.get(appInfo);
}
if (sourceDir == null) {
// try Context.getPackageCodePath()
final Method getPackageCodePathMethod = contextClass.getMethod("getPackageCodePath");
sourceDir = (String) getPackageCodePathMethod.invoke(context);
}
return sourceDir;
}
private static String readZipComment(File file) throws IOException {
RandomAccessFile raf = null;
try {
raf = new RandomAccessFile(file, "r");
long index = raf.length();
byte[] buffer = new byte[COMMENT_SIGN.length];
index -= COMMENT_SIGN.length;
// read sign bytes
raf.seek(index);
raf.readFully(buffer);
// if sign bytes matched
if (Arrays.equals(buffer, COMMENT_SIGN)) {
index -= 2;
raf.seek(index);
// read content length field
int length = readShort(raf);
if (length > 0) {
index -= length;
raf.seek(index);
// read content bytes
byte[] bytesComment = new byte[length];
raf.readFully(bytesComment);
return new String(bytesComment, "utf-8");
} else {
throw new IOException("Zip comment content not found");
}
} else {
throw new IOException("Zip comment sign bytes not found");
}
} finally {
if (raf != null) {
raf.close();
}
}
}
private static short readShort(DataInput input) throws IOException {
byte[] buf = new byte[2];
input.readFully(buf);
ByteBuffer bb = ByteBuffer.wrap(buf).order(ByteOrder.LITTLE_ENDIAN);
return bb.getShort(0);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment