Created
January 18, 2017 09:10
-
-
Save nukc/f762f73276c4ad02618147acd6978d16 to your computer and use it in GitHub Desktop.
获取 apk 文件注释里的渠道号
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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