代码之家  ›  专栏  ›  技术社区  ›  Pushkar

下载和恢复存储在google drive app文件夹中的sqlite数据库

  •  0
  • Pushkar  · 技术社区  · 7 年前

    我在驱动器的app文件夹中存储了一个数据库备份。下面是我编写的代码。

    public void startRestore(View view)
        {
            int EXTERNAL_WRITE_PERMISSION = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
    
            if(Build.VERSION.SDK_INT>= Build.VERSION_CODES.M)
            {
                if(EXTERNAL_WRITE_PERMISSION != PackageManager.PERMISSION_GRANTED)
                {
                    if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE))
                    {
                        Snackbar.make(mLayout, "Write permission is required",
                                Snackbar.LENGTH_INDEFINITE).setAction("OK", new View.OnClickListener() {
                            @Override
                            public void onClick(View view) {
                                // Request the permission
                                ActivityCompat.requestPermissions(BackupActivity.this,
                                        new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                                        PERMISSION_REQUEST_STORAGE);
                            }
                        }).show();
    
                    } else {
                        ActivityCompat.requestPermissions(this,
                                new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                                PERMISSION_REQUEST_STORAGE);
                    }
                }
            }
            if (backupExists())
            {
                Log.d("RESTORE: ", "Started restore");
    
                final  String driveFileID = sharedPreferences.getString("dbBackupDriveFileID", "");
                final DriveFile driveFile = DriveId.decodeFromString(driveFileID).asDriveFile();
    
                Log.d("RESTORE_FileID: ", driveFileID);
    
    
                final Task<DriveContents> openFileTask = mDriveResourceClient.openFile(driveFile, DriveFile.MODE_READ_ONLY);
    
                openFileTask.continueWithTask(new Continuation<DriveContents, Task<Void>>()
                {
                    @Override
                    public Task<Void> then(@NonNull Task<DriveContents> task) throws Exception
                    {
                        Log.d("RESTORE: ", "open File task");
    
                        DriveContents driveContents = task.getResult();
                        //TODO download file an add to database
    
                        InputStream inputStream = driveContents.getInputStream();
    
                        byte[] buf = new byte[8192];
    
                        int c = 0;
    
    
    
    String baseDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath();
                            String fileName = DatabaseHelper.DATABASE_NAME;
    
                            Log.d("RESTORE: ", baseDir + "/" +fileName);
    
    
                            File f = new File(baseDir+File.pathSeparator+fileName);
                            if(f.canWrite())
                            {
                                Log.d("RESTORE: ", "File writable");
    
                                OutputStream outputStream = new FileOutputStream(f);
    
                                while ((c = inputStream.read(buf, 0, buf.length)) > 0)
                                {
                                    outputStream.write(buf, 0, c);
                                    outputStream.flush();
                                }
                                outputStream.close();
                            }
                            else
                            {
                                Log.d("RESTORE: ", "File not writable");
                            }
    
                        return mDriveResourceClient.discardContents(driveContents);
                    }
                })
                .addOnFailureListener(new OnFailureListener()
                {
                    @Override
                    public void onFailure(@NonNull Exception e)
                    {
    
                    }
                });
    
    
            }
            else
            {
                Toast.makeText(this, "Backup does not exists", Toast.LENGTH_SHORT).show();
            }
    
        }
    

    在上述代码中,控件始终达到 Log.d("RESTORE: ", "File not writable"); . 我拥有清单中定义的写入权限,并且还授予运行时权限。日志中也没有错误。

    以下是备份功能供参考。

    public void startBackup(View view)
        {
            final ProgressDialog progressDialog = new ProgressDialog(this);
    
            final File currentDB = this.getDatabasePath(DatabaseHelper.DATABASE_NAME);
    
            Log.d("DATABASE: ", currentDB.getAbsolutePath());
            Log.d("DATABASE: ", currentDB.getName());
    
            progressDialog.setMessage("Backing Up!!!!");
            progressDialog.show();
    
            final Task<DriveFolder> appFolderTask = mDriveResourceClient.getAppFolder();
            final Task<DriveContents> createContentsTask = mDriveResourceClient.createContents();
    
            Tasks.whenAll(appFolderTask, createContentsTask)
                    .continueWithTask(new Continuation<Void, Task<DriveFile>>()
                                      {
                                          @Override
                                          public Task<DriveFile> then(@NonNull Task<Void> task) throws Exception
                                          {
                                              DriveFolder parent = appFolderTask.getResult();
                                              DriveContents contents = createContentsTask.getResult();
    
                                              InputStream inputStream = null;
    
                                              try
                                              {
                                                  inputStream = new FileInputStream(currentDB);
                                              }
                                              catch (FileNotFoundException e)
                                              {
                                                  e.printStackTrace();
                                              }
    
                                              OutputStream outputStream = contents.getOutputStream();
                                              int c = 0;
                                              byte[] buf = new byte[8192];
                                              if (inputStream != null)
                                              {
    
                                                  while ((c = inputStream.read(buf, 0, buf.length)) > 0)
                                                  {
                                                      outputStream.write(buf, 0, c);
                                                      outputStream.flush();
                                                  }
                                                  outputStream.close();
                                              }
                                              else
                                              {
                                                  Toast.makeText(BackupActivity.this, "Some error occurred", Toast.LENGTH_SHORT).show();
                                              }
    
                                              MetadataChangeSet changeSet = new MetadataChangeSet.Builder()
                                                      .setMimeType("application/x-sqlite3")
                                                      .setTitle(currentDB.getName())
                                                      .build();
    
    
                                              return mDriveResourceClient.createFile(parent, changeSet, contents);
                                          }
                                      })
                    .addOnSuccessListener(this, new OnSuccessListener<DriveFile>() {
                        @Override
                        public void onSuccess(DriveFile driveFile)
                        {
                            progressDialog.dismiss();
    
                            String driveFileID = driveFile.getDriveId().encodeToString();
    
                            String dateTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(new Date());
    
                            SharedPreferences.Editor editor = sharedPreferences.edit();
                            editor.putString("dbBackupDriveFileID", driveFileID);
                            editor.putString("lastDbBackupTime", dateTime);
                            editor.apply();
    
                            Log.d("DRIVE_FILE", driveFileID);
    
                            String d = getString(R.string.last_backup) + dateTime;
    
                            textView.setText(d);
    
                            Toast.makeText(BackupActivity.this, "Backup Successful. File "+driveFile.getDriveId()
                                    .encodeToString(), Toast.LENGTH_LONG).show();
    
                        }
                    })
                    .addOnFailureListener(this, new OnFailureListener() {
                        @Override
                        public void onFailure(@NonNull Exception e)
                        {
                            progressDialog.dismiss();
                            Log.e("DRIVE ", "Unable to create file", e);
                            Toast.makeText(BackupActivity.this, "Unable to backup", Toast.LENGTH_SHORT).show();
                        }
                    });
        }
    
    2 回复  |  直到 7 年前
        1
  •  1
  •   Pushkar    7 年前

    而不是使用 File f = new File(baseDir+File.pathSeparator+fileName); 我用 FileOutputStream . 还原功能的修改部分:

    DriveContents driveContents = task.getResult();
                        //TODO download file an add to database
    
                        InputStream inputStream = driveContents.getInputStream();
    
                        byte[] buf = new byte[8192];
    
                        int c = 0;
                        if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
                        {
    
                            Log.d("RESTORE: ", "External DIR mounted");
    
                            String baseDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath();
                            String fileName = DatabaseHelper.DATABASE_NAME;
    
    
                            String fileFullName = baseDir + File.separator + fileName;
    
                            Log.d("RESTORE: ", fileFullName);
    
    
                                    FileOutputStream outputStream;
                                    outputStream = new FileOutputStream(fileFullName, false);
    
                                    while ((c = inputStream.read(buf, 0, buf.length)) > 0) {
                                        outputStream.write(buf, 0, c);
                                        outputStream.flush();
                                    }
                                    outputStream.close();
                        }
                        else
                        {
                            Log.d("RESTORE: ", "External DIR not mounted");
                        }
    

    这解决了我的问题。

        2
  •  0
  •   MikeT    7 年前

    答案很简单,只需添加 f.mkdirs() 紧接着 File f = new File(baseDir+File.pathSeparator+fileName); 和之前 if(f.canWrite()) .

    然而,原因有很多 canWrite 可以返回false,因此您应该检查状态(可能在尝试之前 会写 )

    我个人使用了以下冗长的代码:-

    class StoreData {
    
        private String directory; //Note built internally and includes subdirectory
        private String subdirectory;
        private String filename;
        private boolean mounted;
        private boolean inerror;
        private boolean fileexists;
        private boolean direxists;
        private long errorcode;
        private ArrayList<String> errorlist = new ArrayList<>();
        private ArrayList<File> otherfilesindirectory = new ArrayList<>();
    
        // Need to be aware of the API
        @SuppressWarnings("unused")
        public static final int API_VERSION = Build.VERSION.SDK_INT;
        private static final long UNMOUNTED = 1;
        private static final long FILEIOERR = 2;
        private static final long READERR = 4;
        private static final String NEWLINE = "\r\n";
    
        /**
         * Sole Constructor for a StoreData object
         * Note instantiating creates but the deletes a file, assuming that
         * no prior errors left the instance in an unusable state (as initially set)
         * Note instantiating, if existcheck (3rd param) is true, does not create
         * and delete the file, rather it checks that the file exists
         *     typically for reading an existing file.
         *
         * @param subdirectory - Sub directory in which to create file
         * @param filename - the file name where actual data will be stored
         * @param existcheck - whether or not to check for the existence of the file
         *
         *  Note!! existcheck, if true, will not try to create the file
         */
        public StoreData(String subdirectory, @SuppressWarnings("SameParameterValue") String filename, boolean existcheck) {
            fileexists = false;
            direxists = false;
            mounted = false;
            inerror = false;
            errorcode = 0;
    
            this.directory = "";
            this.subdirectory = subdirectory;
            this.filename = filename;
    
            // 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 SD 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 required directory and specified sub directory
            File dir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),subdirectory);
            this.directory = dir.getPath();
    
            // If existcheck is true check that the directories exist
            if (existcheck && dir.exists()) {
                direxists = true;
    
            }
            // If the directories do not exist try to create them and redo check
            // Note! existcheck is more for file level so always try to create
            // directories
            else {
                boolean x = dir.mkdirs();
                if(dir.exists()) {
                    direxists = true;
                }
            }
            if(direxists) {
                refreshOtherFilesInDirectory();
            }
    
            // File level
            File f = new File(directory,filename);
            // Check if the file exists if requested and return if it does
            if (existcheck) {
                if (f.exists()) {
                    fileexists = true;
                }
                return;
            }
    
            try {
                boolean x = f.createNewFile();
            }
            catch (IOException e) {
                e.printStackTrace();
                this.errorcode = FILEIOERR ;
                errorlist.add(
                        "File Error " + e.getMessage()
                );
                return;
            }
            boolean x = f.delete();
        }
    
        @SuppressWarnings({"ConstantConditions", "UnusedReturnValue"})
        public boolean refreshOtherFilesInDirectory() {
            boolean rv = true;
            File dir = new File(directory);
            File[] dirlist = dir.listFiles();
            if((dirlist.length) > 0) {
                // Sort the list
                Arrays.sort(dirlist, new Comparator<File>() {
                    @Override
                    public int compare(File object1, File object2) {
                        return object1.getName().compareTo(object2.getName());
                    }
                });
                otherfilesindirectory.clear();
                for (File aDirlist : dirlist) {
                    if (!(aDirlist.getName().equals(this.filename))) {
                        otherfilesindirectory.add(aDirlist);
                    }
                }
            }
            return rv;
        }
    
        /**
         * writeData - Write data to the file from String Arraylist passed
         * Note!! a linefeed is added to each string
         * @param datatowrite - strng ArrayList holding data to write
         * @return result flag
         */
        @SuppressWarnings("unused")
        public boolean writeData(ArrayList<String> datatowrite) {
            // Check that this instance is OK
            if (!this.isOK()) {
                this.errorlist.add(
                        "\nError prior to call to writeData method."
                );
                return false;
            }
            // Prepare to write
            this.errorlist.clear();
            File f = new File(this.directory,File.separator + this.filename);
            try {
                boolean x =  f.createNewFile();
                FileOutputStream fos = new FileOutputStream(f);
                OutputStreamWriter osw = new OutputStreamWriter(fos);
                for (int i = 0; i < datatowrite.size(); i++) {
                    osw.write(datatowrite.get(i) + NEWLINE);
                }
                osw.flush();
                osw.close();
                fos.flush();
                fos.close();
                this.fileexists = true;
            }
            catch (IOException e) {
                e.printStackTrace();
                this.errorcode = FILEIOERR;
                errorlist.add(
                        "File Error " + e.getMessage()
                );
                return false;
            }
            return true;
        }
    
        /**
         * readData - Populate a String ArrayList from the data in the file
         * Note! Assumes linefeeds in the file separate strings of data
         * @return - result flag
         */
        @SuppressWarnings("unused")
        public ArrayList<String> readData() {
            ArrayList<String> rv = new ArrayList<>();
    
            if(!this.isOKandExists()) {
                this.errorlist.add(
                        "\nError prior to call to readData method or the file doesn't exist."
                );
                this.errorcode = READERR;
                return rv;
            }
    
            this.errorlist.clear();
            File f = new File(this.directory,File.separator + this.filename);
            try {
                FileInputStream fis = new FileInputStream(f);
                InputStreamReader isr = new InputStreamReader(fis);
                BufferedReader br = new BufferedReader(isr);
                String line;
                while((line = br.readLine()) != null) {
                    rv.add(line);
                }
            }
            catch (IOException e) {
                e.printStackTrace();
                this.errorcode = READERR;
                errorlist.add(
                        "File Read Error" + e.getMessage()
                );
                return rv;
            }
            return rv;
        }
    
        /**
         * isOK - Check if object is usable
         * @return true if OK else false
         */
        public boolean isOK() {
            return !(errorcode != 0 || !mounted || inerror);
        }
    
        /**
         * exists = Check if the file exists
         * @return - Result of check
         */
        @SuppressWarnings("unused")
        public boolean exists() {
            return this.fileexists;
        }
    
        public boolean isOKandExists() {
            return this.isOK() && this.fileexists;
        }
    
        /**
         * Return a string displaying the instances details
         * @return string displaying object's members
         */
        public String Display() {
            String rv;
    
            rv = "Directory path=" + directory + "\n" +
                    "SubDirectory=" + subdirectory + "\n" +
                    "Filename=" + filename + "\n" +
                    "Mounted =" + Boolean.toString(mounted) + "\n" +
                    "Directory Exists=" + Boolean.toString(this.direxists) + "\n" +
                    "File Exists=" + Boolean.toString(this.fileexists) + "\n" +
                    "In Error=" + Boolean.toString(inerror) + "\n" +
                    "Last Error Code=" + Long.toString(errorcode);
            return rv;
        }
    
        @SuppressWarnings("unused")
        public String DisplayWithOtherFiles() {
            String rv;
            rv = this.Display() + "\nOther Files in Directory (" + this.directory + ") ";
    
            for(int i = 0; i < otherfilesindirectory.size(); i++) {
                rv = rv + "\n\t" + otherfilesindirectory.get(i).getName();
            }
            return rv;
        }
    
        /**
         * Retrieve generated error messages. if any
         * @return sting comprised of all error messages generated
         */
        @SuppressWarnings("unused")
        public String getErrorMessages() {
            String rv = "";
            for(int i = 0; i < errorlist.size(); i++) {
                rv = rv + errorlist.get(i);
            }
            return rv;
        }
    
        /**
         * Method: getDirectory - get the backup directory as a String
         * @return Directory as a String
         */
        public String getDirectory() {
            return this.directory;
        }
    
        /**
         * Method: getFilename - get the filename of the object as a String
         * @return Filename as a String
         */
        @SuppressWarnings("unused")
        public String getFilename() {
            return this.filename;
        }
    
        /**
         * Method: getSubDirectory - get the sub-directory as a string
         * @return Sub-Directory as a String
         */
        @SuppressWarnings("unused")
        public String getSubDirectory() {
            return this.subdirectory;
        }
    
        /**
         * Method: getFilesInDirectory - return an ArrayList of type File
         * @return List of files in the directory as an ArrayList<File>
         */
        public ArrayList<File> getFilesInDirectory() {
            return this.otherfilesindirectory;
        }
    }