简体   繁体   中英

How to copy android database sqlite file to sdcard?

I am trying to copy created database sqlite file from android memory to an sdcard but I am getting "failed to copy" error. Is there a way to create the database sqlite file so it can be easily copied? Do I need to set permissions anywhere on the device?

Yes you do need permissions and how depends upon the API if less than 23 then you need to have

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

in your manifest (AndroidManifest.xml).

If 23 or greater then you need to specifically request Accsess. eg In an activity ( I have this in MainActivity so it is always checked ) have :-

if(Build.VERSION.SDK_INT >= 23) {
            ExternalStoragePermissions.verifyStoragePermissions(this);
        }

ExternalStoragePermissions Class is :-

class ExternalStoragePermissions {

    public int API_VERSION = Build.VERSION.SDK_INT;
    private static final int REQUEST_EXTERNAL_STORAGE = 1;
    private static String[] PERMISSIONS_STORAGE = {

            //Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.WRITE_EXTERNAL_STORAGE
    };
    public static final String THISCLASS = ExternalStoragePermissions.class.getSimpleName();

    public ExternalStoragePermissions() {}
    // Note call this method
    public static void verifyStoragePermissions(Activity activity) {

        int permission = ActivityCompat.checkSelfPermission(
                activity,
                Manifest.permission.WRITE_EXTERNAL_STORAGE);

        if(permission != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(
                    activity,
                    PERMISSIONS_STORAGE,
                    REQUEST_EXTERNAL_STORAGE
            );
        }
    }
}

This prompt the user to allow access.

PS I have both encoded so that the app copes with both situations.

I do actually have a working backup/restore where a backup is a copy. However, it's quite long winded and perhaps a little convoluted. As I've tried to handle many situations. I actually backup to a folder created in the downloads folder.

PS if you have something like SQLite Manager, you can even copy the file to a PC and open it (connect). I use this for testing queries etc. You can even modify the database and copy it back (well I can, very easily, because of the restore side). I've even gone to the lengths of seeing what happens if I copy a non-SQLite file and restore from that (basically it copes but does require the App to be closed and then re-opened to circumvent unpredictable results).

As an example of the length/convolution this is one of the first checks I do :-

    // External Storage must be mounted.
    String chkmnt = Environment.getExternalStorageState();

    if(!(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))) {
        switch (Environment.getExternalStorageState()) {
            case Environment.MEDIA_SHARED : {
                errorlist.add(
                        "Although External Storage is present." +
                                " It cannot be used as it's in use via USB." +
                                "\nDisconnect the USB cable and then try again."
                );
                break;
            }
            case Environment.MEDIA_REMOVED : {
                errorlist.add(
                        "External Storage is not present." +
                                "\nInsert an SC Card."
                );
                break;
            }
            case Environment.MEDIA_EJECTING : {
                errorlist.add(
                        "External Storage is being ejected." +
                                "\nRe-insert the SD Card."
                );
                break;
            }
            case Environment.MEDIA_NOFS : {
                errorlist.add(
                        "External Storage is blank or does not have the correct" +
                                " filesystem present." +
                                "\nUse a valid SDCard."
                );
                break;
            }
            case Environment.MEDIA_BAD_REMOVAL : {
                errorlist.add(
                        "External Storage was removed incorrectly." +
                                "\nRe-insert the SD Card, if this fails then" +
                                " try restarting the device."
                );
                break;
            }
            case Environment.MEDIA_CHECKING : {
                errorlist.add(
                        "External Storage is unavailable as it is being checked." +
                                "\nTry again."
                );
            }
            case Environment.MEDIA_MOUNTED_READ_ONLY : {
                errorlist.add(
                        "External Storage is READ ONLY." +
                                "\nInsert an SD card that is not protected."
                );
            }
            case Environment.MEDIA_UNKNOWN : {
                errorlist.add(
                        "External Storage state is UNKNOWN." +
                                "\ntry a different SD Card."
                );
            }
            case Environment.MEDIA_UNMOUNTABLE : {
                errorlist.add(
                        "External Storage cannot be mounted." +
                                "\nTry re-inserting the SD Card or using a different SD Card."
                );
            }
            case Environment.MEDIA_UNMOUNTED : {
                errorlist.add(
                        "External Storage is not mounted." +
                                "\nTry re-inserting the SD Card or using a different SD Card."
                );

            }
            default: {
                errorlist.add(
                        "Undefined Error"
                );
            }
        }
        this.errorcode = UNMOUNTED;
        return;
    } else {
        this.mounted = true; 
    }

    // Get the require directory and specified sub directory
    File dir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),subdirectory);
    this.directory = dir.getPath();

For the backup itself I use :-

/**************************************************************************
 * method saveDB save a file copy of the Database
 */
private void saveDB() {

    busy.show();
    errlist.clear();
    confirmaction = true;
    String dbfilename = this.getDatabasePath(
            DBConstants.DATABASE_NAME).getPath();
    dbfile = new File(dbfilename);
    backupfilename = directory.getText().toString() +
            "/" +
            backupfullfilename.getText().toString();
    new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                FileInputStream fis = new FileInputStream(dbfile);
                OutputStream backup = new FileOutputStream(backupfilename);

                //byte[] buffer = new byte[32768];
                int length;
                while((length = fis.read(buffer)) > 0) {
                    backup.write(buffer, 0, length);
                }
                backup.flush();
                backup.close();
                fis.close();
            }
            catch (IOException e) {
                e.printStackTrace();
                errlist.add("Database backup failed with an IO Error. Error Message was " +
                        e.getMessage() +
                        "/n/tFile Name was " +
                        backupfilename);
                confirmaction = false;
            }
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    busy.dismiss();
                    AlertDialog.Builder dbbackupresult = new AlertDialog.Builder(context);
                    dbbackupresult.setCancelable(true);
                    if(confirmaction) {
                        dbbackupresult.setTitle("DB Data Backed up OK.");
                        dbbackupresult.setMessage("DB Data successfully saved in file \n\t" +
                                backupfilename );
                    } else {
                        dbbackupresult.setTitle("DB Backup Failed.");
                        String emsg = "";
                        for(int i = 0; i < errlist.size(); i++) {
                            emsg = emsg + errlist.get(i);
                        }
                    }
                    dbbackupresult.setPositiveButton("OK", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {

                        }
                    }).show();
                }
            });
        }
    }).start();

Note these are extracts and may make references to code that is not included. eg busy is a progressdialog, directory is an EditText that is populated when the check routine is called

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM