我在驱动器的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();
}
});
}