如何将android数据库sqlite文件复制到sdcard?

问题描述:

我正在尝试将创建的数据库sqlite文件从android内存复制到sdcard,但出现无法复制"错误.有没有一种创建数据库sqlite文件的方法,以便可以轻松地复制它?我需要在设备上的任何地方设置权限吗?

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?

是的,您确实需要权限,如果少于23,则需要如何依赖于API,那么您需要拥有

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"/>

在清单(AndroidManifest.xml)中.

in your manifest (AndroidManifest.xml).

如果23或更大,则需要专门要求Accsess.例如在一个活动中(我在MainActivity中拥有此功能,因此始终会对其进行检查)具有:-

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

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

ExternalStoragePermissions类为:-

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
            );
        }
    }
}

这提示用户允许访问.

我都对PS进行了编码,因此应用程序可以应对两种情况.

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

我实际上有一个有效的备份/还原,其中备份是副本.但是,它缠绕了很长一段时间,也许有些令人费解.正如我尝试处理的许多情况一样.我实际上备份到了在downloads文件夹中创建的文件夹.

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.

如果您有类似SQLite Manager的工具,甚至可以将文件复制到PC上并打开(连接).我用它来测试查询等.您甚至可以修改数据库并将其复制回去(由于还原方面,我可以很容易地做到这一点).我什至不厌其烦地看到如果我复制一个非SQLite文件并从中还原会发生什么情况(基本上可以应付,但确实需要关闭该应用程序然后再打开以规避不可预测的结果).

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();

请注意,这些是摘录,可能引用了未包含的代码.例如busy是进度对话框,directory是在调用检查例程时填充的EditText

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