Search code examples
nativescript

NativeScript: How to copy a file from an apps folder to a user accessible folder?


I want to copy storage.db to documents or downloads folder. It's very easy to get the file path:

const filePath = application.android.context.getDatabasePath("storage.db").getAbsolutePath();

But, what isn't that easy is to copy that file to a folder users have access to. I searched this whole forum, and I found nothing useful for my case.

I'm using NativeScript 4.0.1 with vanilla JS.


Solution

  • I finally found the solution. I've seen so many users trying to achieve this, and I hope this will help all of you.

    Add this to your AndroidManifest.xml:

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

    Install nativescript-permissions:

    npm i nativescript-permissions
    

    Asking for permission:

    const permissions = require('nativescript-permissions');
    permissions.requestPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE, "");
    

    Require the necessary modules:

    const fileSystemModule = require("tns-core-modules/file-system");
    const application = require("application");
    

    Then, create this function where you need to use it:

    function copyFile() {
        var myInput = new java.io.FileInputStream(appModule.android.context.getDatabasePath("storage.db").getAbsolutePath());
        
        var myOutput = new java.io.FileOutputStream("/storage/emulated/0/databases/storage.db");
    
        try {
            var buffer = java.lang.reflect.Array.newInstance(java.lang.Byte.class.getField("TYPE").get(null), 1024);
            var length;
            while ((length = myInput.read(buffer)) > 0) {
                myOutput.write(buffer, 0, length);
            }
        }
        catch (err) {
            console.info("Error", err);
        }
    
    
        //Close the streams
        myOutput.flush();
        myOutput.close();
        myInput.close();
    }
    exports.copyFile = copyFile;
    

    In my case, the file storage.db will be copied to /storage/emulated/0/databases. If you need to create a folder, just do the following:

    try {
            var javaFile = new java.io.File("/storage/emulated/0/newfolder");
            if (!javaFile.exists()) {
                javaFile.mkdirs();
                javaFile.setReadable(true);
                javaFile.setWritable(true);
            }
        }
        catch (err) {
            console.info("Error", err);
        }
    

    If the destination folder has a file with the same name as the one you want to copy, you need to remove it first. That's why you should create a specific folder to guarantee it's empty.