Packet Copy of Data in android

Keywords: Database Android less

Previously, in the development, I encountered a problem, that is, there is an apk under the project assets that needs to be installed into the device when the application starts. The idea of implementation is to copy the apk into the sdcard first, and then perform the installation operation. Another problem is that the database in the project also needs to be placed in the sdcard. This apk has about 5M, and my database has about 30M. Next, I copy it according to the normal I/O stream:

public static boolean copyDataToSD(Context context, String fileName, File strOutFile) {
        InputStream myInput = null;
        OutputStream myOutput = null;
        try {
            myOutput = new FileOutputStream(strOutFile);
            myInput =context.getAssets().open(fileName);
            byte[] buffer = new byte[1024];
            int length = myInput.read(buffer);
            while (length > 0) {
                myOutput.write(buffer, 0, length);
                length = myInput.read(buffer);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            try {
                if (myOutput != null) {
                    myOutput.flush();
                    myOutput.close();
                }
                if (myInput != null)
                    myInput.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

But when we execute the above code, we report an error. After querying, we know that Android 2.3 requires that the data copied from the apk must be less than 1M, Daddy!!!
So, we can only decompose the data! Look directly at the complete code:

public static List<String> splitBigFile(Context context, String fileName, String formatType, String dirName) {
        //File name of the file to be partitioned
        String base = fileName;
        //The suffix name of the file to be split
        String ext = formatType;

        List<String> list = new ArrayList<>();

        InputStream inputStream = null;

        //Divide each small file by 1024*1024 bytes, or 1M
        int split = 1024 * 1024;
        byte[] buf = new byte[1024];
        int num = 1;
        try {
            //Files that need to be split
            inputStream = context.getAssets().open(fileName + formatType);
            File fileDir = new File(SDCardUtils.getSDCardPath() + File.separator + dirName);
            if (!fileDir.exists()) {
                fileDir.mkdir();
            }
            while (true) {
                //Name the small file in the way of "demo"+num+".db", that is, demo1.db, demo2.db,... after partitioning.
                File file = new File(SDCardUtils.getSDCardPath() + File.separator + dirName + File.separator + base + num + ext);
                if (!file.exists()) {
                    file.createNewFile();
                }
                list.add(file.getPath());
                FileOutputStream fos = new FileOutputStream(file);
                for (int i = 0; i < split / buf.length; i++) {
                    int read = inputStream.read(buf);
                    fos.write(buf, 0, read);
                    // Determine whether large file reading ends
                    if (read < buf.length) {
                        inputStream.close();
                        fos.close();
                        return list;
                    }
                }
                num++;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }

    public static boolean mergeFile(Object[] partFileList, String dst, String formatType, String dirName) {
        try {
            OutputStream out = new FileOutputStream(dst);
            byte[] buffer = new byte[1024];
            InputStream in;
            int readLen = 0;
            for (int i = 0; i < partFileList.length; i++) {
                // Obtain the input stream and note the path of the file
                String str = partFileList[i].toString();
                if (partFileList[i].toString().endsWith(formatType)) {
                    in = new FileInputStream(new File(partFileList[i].toString()));
                    while ((readLen = in.read(buffer)) != -1) {
                        out.write(buffer, 0, readLen);
                    }
                    out.flush();
                    in.close();
                }
            }
            // Close the output stream after all the small files are written, and then merge into one file.
            out.close();

            deleteFolder(SDCardUtils.getSDCardPath() + File.separator + dirName);

            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

public static void deleteFolder(String folderPath) {
      File localFolder = new File(folderPath);
      if (localFolder.isDirectory()) {
            String[] childrenStrings = localFolder.list();
            int length = childrenStrings.length;
            for (int i = 0; i < length; i++) {
                File temp = new File(localFolder, childrenStrings[i]);
                if (temp.isDirectory()) {
                    deleteFolder(temp.getName());
                } else {
                    temp.delete();
                }
            }
            localFolder.delete();
        }
    }

From the above code, we can see that the idea is:
A. The source files are read and decomposed with an average size of 1M, and then each M stream is written to a small file in sdcard. The file path is stored in a collection. The names of these small files are similar to the numbers: xxx1. db, xxxx2. db. And so on.
b. Create a target file to be generated in sdcard, and then write each small file into the target file by traversing the small files.
c. Finally, close the stream object and delete these small files.

Finally, where calls are needed:

//The first parameter is context, the second parameter is the name of the packet under assets, the third parameter is the suffix of the packet, and the fourth parameter is the folder where the decomposed small files are temporarily stored in sdcard.
List<String> strings =CopyDataToSDUtils.splitBigFile(MainActivity.this, "xxx", ".apk", "xxxapk");
boolean b =CopyDataToSDUtils.mergeFile(strings.toArray(), apkPath, ".apk", "hdpapk");
if (b) {
   Log.d(MainActivity.class.getName(),"Success copy");
}else{
   Log.d(MainActivity.class.getName(),"Copy failure");
}

Posted by davidjmorin on Sun, 21 Apr 2019 13:48:33 -0700