阐明

因为一些原因,我们提供给客户的sdk,只能是jar包形式的,一些情况下,sdk里边有native库的时候,就不太便利操作了,此篇文章主要处理怎么把so库放入jar包里边,怎么打包成jar,以及怎么加载。

1.怎么把so库放入jar包

so库放入jar参阅此文章ANDROID将SO库封装到JAR包中并加载其中的SO库

Android将so库封装到jar包中并加载其中的so库
将so库改成.jet后缀,放置和加载so库的SoLoader类同一个目录下面。

2.怎么运用groovy打包jar

Android将so库封装到jar包中并加载其中的so库
先把需求打包的class放置到同一个文件夹下面,然后打包即可,使用groovy的copy task完结这项作业十分简单。

3.怎么加载jar包里边的so

3.1.首要判别当时jar里边是否存在so
InputStream inputStream = SoLoader.class.getResourceAsStream("/com/dianping/logan/arm64-v8a/liblogan.jet");

如果inputStream不为空就表示存在。

3.2.复制

判别是否现已把so库复制到手机里边了,如果没有复制过就进行复制,这个代码逻辑很简单。

public class SoLoader {
    private static final String TAG = "SoLoader";
    /**
     * so库释放位置
     */
    public static String getPath() {
        String path = GlobalCtx.getApp().getFilesDir().getAbsolutePath();
        //String path = GlobalCtx.getApp().getExternalFilesDir(null).getAbsolutePath();
        return path;
    }
    public static String get64SoFilePath() {
        String path = SoLoader.getPath();
        String v8a = path + File.separator + "jniLibs" + File.separator +
                "arm64-v8a" + File.separator + "liblogan.so";
        return v8a;
    }
    public static String get32SoFilePath() {
        String path = SoLoader.getPath();
        String v7a = path + File.separator + "jniLibs" + File.separator +
                "armeabi-v7a" + File.separator + "liblogan.so";
        return v7a;
    }
    /**
     * 支持两种模式,如果InputStream inputStream = SoLoader.class.getResourceAsStream("/com/dianping/logan/arm64-v8a/liblogan.jet");
     * 返回了空,表示可能此库是aar接入的,一般加载so库就行,不为空,需求复制so库,动态加载
     */
    public static boolean jarMode() {
        boolean jarMode = false;
        InputStream inputStream = SoLoader.class.getResourceAsStream("/com/dianping/logan/arm64-v8a/liblogan.jet");
        if (inputStream != null) {
            jarMode = true;
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return jarMode;
    }
    /**
     * 是否现已复制过so了
     */
    public static boolean alreadyCopySo() {
        String v8a = SoLoader.get64SoFilePath();
        File file = new File(v8a);
        if (file.exists()) {
            String v7a = SoLoader.get32SoFilePath();
            file = new File(v7a);
            return file.exists();
        }
        return false;
    }
    /**
     * 复制logan的so库
     */
    public static boolean copyLoganJni() {
        boolean load;
        File dir = new File(getPath(), "jniLibs");
        if (!dir.exists()) {
            load = dir.mkdirs();
            if (!load) {
                return false;
            }
        }
        File subdir = new File(dir, "arm64-v8a");
        if (!subdir.exists()) {
            load = subdir.mkdirs();
            if (!load) {
                return false;
            }
        }
        File dest = new File(subdir, "liblogan.so");
        //load = copySo("/lib/arm64-v8a/liblogan.so", dest);
        load = copySo("/com/dianping/logan/arm64-v8a/liblogan.jet", dest);
        if (load) {
            subdir = new File(dir, "armeabi-v7a");
            if (!subdir.exists()) {
                load = subdir.mkdirs();
                if (!load) {
                    return false;
                }
            }
            dest = new File(subdir, "liblogan.so");
            //load = copySo("/lib/armeabi-v7a/liblogan.so", dest);
            load = copySo("/com/dianping/logan/armeabi-v7a/liblogan.jet", dest);
        }
        return load;
    }
    public static boolean copySo(String name, File dest) {
        InputStream inputStream = SoLoader.class.getResourceAsStream(name);
        if (inputStream == null) {
            Log.e(TAG, "inputStream == null");
            return false;
        }
        boolean result = false;
        FileOutputStream outputStream = null;
        try {
            outputStream = new FileOutputStream(dest);
            int i;
            byte[] buf = new byte[1024 * 4];
            while ((i = inputStream.read(buf)) != -1) {
                outputStream.write(buf, 0, i);
            }
            result = true;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return result;
    }
}
3.3.加载

首要判别当时应用是32位仍是64位Process.is64Bit();。然后加载对应的32或者64位的so。

static {
    try {
        if (SoLoader.jarMode()) {
            if (SoLoader.alreadyCopySo()) {
                sIsCloganOk = loadLocalSo();
            } else {
                boolean copyLoganJni = SoLoader.copyLoganJni();
                if (copyLoganJni) {
                    sIsCloganOk = loadLocalSo();
                }
            }
        } else {
            System.loadLibrary(LIBRARY_NAME);
            sIsCloganOk = true;
        }
    } catch (Throwable e) {
        e.printStackTrace();
        sIsCloganOk = false;
    }
}
static boolean loadLocalSo() {
    boolean bit = Process.is64Bit();
    if (bit) {
        String v8a = SoLoader.get64SoFilePath();
        try {
            System.load(v8a);
            return true;
        } catch (Throwable e) {
            e.printStackTrace();
            return false;
        }
    } else {
        String v7a = SoLoader.get32SoFilePath();
        try {
            System.load(v7a);
            return true;
        } catch (Throwable e) {
            e.printStackTrace();
            return false;
        }
    }
}