通过Java自带的API获取未安装的apk签名信息

通过Java自带的API获取未安装的apk签名信息

【转】

某些时候需要获取某个特定的apk(已安装或者未安装)的签名信息,如程序自检测,可信赖的第三方检测(应用市场),系统限定安装
对此,有两种实现方法
可以使用Java自带的API(主要用到的为JarFile,JarEntry,Certificate)进行获取,还有一种方法是使用系统隐藏的API
PackageParser,通过反射来使用对应的API.
但是由于安卓系统的分裂版本过多,并且不同厂商进行的修改很多,依赖反射隐藏API的方法并不能保证兼容性和通用性,因此推荐使用JAVA自带API进行获取:

> 代码:

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.security.cert.Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

public class getApkSign {

    public static void main(String[] args) throws IOException {

        String path = "F:/myapk/test.apk";//apk的路径

        List list = getSignaturesFromApk(path);
        // for (String s : list) {
        // System.out.println(s);
        // }
        System.out.println(list.get(0));
    }

    /**
     * 从APK中读取签名
     * 
     * @param file
     * @return
     * @throws IOException
     */
    private static List getSignaturesFromApk(String strFile)
            throws IOException {
        File file = new File(strFile);
        List signatures = new ArrayList();
        JarFile jarFile = new JarFile(file);
        try {
            JarEntry je = jarFile.getJarEntry("AndroidManifest.xml");
            byte[] readBuffer = new byte[8192];
            Certificate[] certs = loadCertificates(jarFile, je, readBuffer);
            if (certs != null) {
                for (Certificate c : certs) {
                    String sig = toCharsString(c.getEncoded());
                    signatures.add(sig);
                }
            }
        } catch (Exception ex) {
        }
        return signatures;
    }

    /**
     * 加载签名
     * 
     * @param jarFile
     * @param je
     * @param readBuffer
     * @return
     */
    private static Certificate[] loadCertificates(JarFile jarFile, JarEntry je,
            byte[] readBuffer) {
        try {
            InputStream is = jarFile.getInputStream(je);
            while (is.read(readBuffer, 0, readBuffer.length) != -1) {
            }
            is.close();
            return je != null ? je.getCertificates() : null;
        } catch (IOException e) {
        }
        return null;
    }

    /**
     * 将签名转成转成可见字符串
     * 
     * @param sigBytes
     * @return
     */
    private static String toCharsString(byte[] sigBytes) {
        byte[] sig = sigBytes;
        final int N = sig.length;
        final int N2 = N * 2;
        char[] text = new char[N2];
        for (int j = 0; j < N; j++) {
            byte v = sig[j];
            int d = (v >> 4) & 0xf;
            text[j * 2] = (char) (d >= 10 ? ('a' + d - 10) : ('0' + d));
            d = v & 0xf;
            text[j * 2 + 1] = (char) (d >= 10 ? ('a' + d - 10) : ('0' + d));
        }
        return new String(text);
    }

}

结束语:ok,签名就这样出来了。一大长串的数字、字母哈。
ps:感觉markdown貌似还很好用哈,虽然现在没有用习惯、。

你可能感兴趣的:(工具类)