我正在尝试将创建的数据库sqlite文件从android内存复制到sdcard,但我收到“无法复制”错误。有没有办法创建数据库sqlite文件,以便可以轻松复制?我是否需要在设备的任何位置设置权限?
答案 0 :(得分:1)
是的,你确实需要权限,如果少于23,则取决于API,那么你需要
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
清单中的(AndroidManifest.xml)。
如果是23或更高,则需要特别要求Accsess。例如在一个活动中(我在MainActivity中有这个,所以总是检查)有: -
if(Build.VERSION.SDK_INT >= 23) {
ExternalStoragePermissions.verifyStoragePermissions(this);
}
ExternalStoragePermissions类是: -
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如果你有类似SQLite Manager的东西,你甚至可以将文件复制到PC并打开它(连接)。我用它来测试查询等。你甚至可以修改数据库并将其复制回来(我可以,非常容易,因为还原方面)。我甚至不知道如果我复制一个非SQLite文件并从中恢复会发生什么(基本上它应对但是需要关闭然后重新打开才能绕过不可预测的结果)。< / p>
作为长度/卷积的一个例子,这是我做的第一个检查之一: -
// 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();
对于备份本身,我使用: -
/**************************************************************************
* 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
,在调用检查例程时会填充