Android dynamically loads so Library in sd card

Posted by reli4nt on Tue, 24 Dec 2019 23:19:21 +0100

Some so files are too large, which can be copied from the mobile memory or sd card to the running application. Interfaces are all packed in before. You can also do so update, that is, delete the previous copy, and then do not repackage apk to copy in again.

1. Encapsulated class

package com.rtcmdemo.until;

import android.content.Context;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;

/**
 * so The library is copied from sd card to the private directory of app, and compared, verified and loaded
 */

public class LoadSoFileUtils {
    private static String nameSO = "libSaveLib";

    /**
     * Load so file
     */
    public static int loadSoFile(Context context, String fromPath) {
        File dir = context.getDir("jniLibs", Context.MODE_PRIVATE);
        String fromPathFile = fromPath + "/" + nameSO + ".so";
        File isExist = new File(fromPathFile);
        if (!isLoadSoFile(dir, isExist.exists())) {
            return copy(fromPath, dir.getAbsolutePath());
        } else {
            return 0;
        }
    }

    /**
     * Determine whether so file exists
     */
    public static boolean isLoadSoFile(File dir, Boolean isExist) {
        File[] currentFiles;
        currentFiles = dir.listFiles();
        boolean hasSoLib = false;
        if (currentFiles == null) {
            return false;
        }
        for (File currentFile : currentFiles) {
            //Determine whether there is a library in it, and if sd also has a library, delete it, and then copy it outside
            if (currentFile.getName().contains(nameSO)) {
                hasSoLib = isExist && !currentFile.delete();
            }
        }
        return hasSoLib;
    }

    public static int copy(String fromFile, String toFile) {
        //Directory of files to copy
        File[] currentFiles;
        File root = new File(fromFile);
        //It's like judging whether the SD card exists or whether the file exists. If it doesn't exist, return it
        if (!root.exists()) {
            return -1;
        }
        //If it exists, get all the files in the current directory to fill the array
        currentFiles = root.listFiles();

        if (currentFiles == null) {
            return -1;
        }
        //Target directory
        File targetDir = new File(toFile);
        //Create directory
        if (!targetDir.exists()) {
            targetDir.mkdirs();
        }

        int statue = -1;
        //Traverse all files in the directory to be copied
        for (File currentFile : currentFiles) {
            if (currentFile.isDirectory()) {
                //If the current item is a subdirectory for recursion
                copy(currentFile.getPath() + "/", toFile + currentFile.getName() + "/");
            } else {
                //Copy the file if the current item is a file
                if (currentFile.getName().contains(".so")) {
                    statue = copySdcardFile(currentFile.getPath(), toFile + File.separator + currentFile.getName());
                }
            }
        }
        return statue;
    }


    //File copy
    //Copies of all non subdirectory (folder) files in the directory to be copied
    public static int copySdcardFile(String fromFile, String toFile) {
        try {
            FileInputStream fosfrom = new FileInputStream(fromFile);
            FileOutputStream fosto = new FileOutputStream(toFile);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = -1;
            while ((len = fosfrom.read(buffer)) != -1) {
                baos.write(buffer, 0, len);
            }
            // From memory to write to specific file
            fosto.write(baos.toByteArray());
            // Close file stream
            baos.close();
            fosto.close();
            fosfrom.close();
            return 0;
        } catch (Exception ex) {
            return -1;
        }
    }
}

2. Usage

        File dir = this.getDir("jniLibs", Activity.MODE_PRIVATE);
        String ext = FilePathManage.GetInstance().getDataDirectory();

        try {
            LoadSoFileUtils.loadSoFile(this, ext);
            File[] currentFiles;
            currentFiles = dir.listFiles();
            for (File currentFile : currentFiles) {
                System.load(currentFile.getAbsolutePath());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

Note that external loading uses:

System.load(currentFile.getAbsolutePath()); the parameter is so full path

Note that the jar interface should not have the following, because it will conflict with the above. Because sometimes we are used to writing the following directly in our own compilation library.

static{
    System.loadLibrary("libSaveLib");
}

Remember to add authority

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

 

Topics: Android Java Mobile