在我的应用程序中,有一个由sqlite创建的数据库。我要复制数据库以下载文件夹。我使用了不同的方式,但无法在实际设备中工作(它说拒绝访问目录),可能是它想要扎根手机。请帮忙,我想授予访问权限,以便用户可以从下载文件夹中获取数据库。
请注意,我正在使用最新版本的android studio。
在下面给定的DatabaseHelper类中。在exportDB()方法中,我要实现这一点。
package com.tarikul.sqlitedatabase1;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Environment;
import android.widget.Toast;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
public class DatabaseHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "Students.db";
private static final String TABLE_NAME = "student_details";
private static final String ID = "_id";
private static final String NAME = "Name";
private static final String AGE = "Age";
private static final String GENDER = "Gender";
private static final int VERSION_NUMBER = 1;
private static final String CREATE_TABLE = "CREATE TABLE "+TABLE_NAME+"("+ID+" INTEGER PRIMARY KEY AUTOINCREMENT, "+NAME+" VARCHAR(155), "+AGE+" INTEGER, "+GENDER+" VARCHAR(15));";
private static final String DROP_TABLE = "DROP TABLE IF EXISTS " + TABLE_NAME;
private static final String SELECT_ALL_DATA = "SELECT * FROM " + TABLE_NAME;
private Context context;
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, VERSION_NUMBER);
this.context=context;
}
@Override
public void onCreate(SQLiteDatabase db) {
try {
db.execSQL(CREATE_TABLE);
Toast.makeText(context,"OnCreate is called.",Toast.LENGTH_SHORT).show();
}catch (Exception e){
Toast.makeText(context,"Exception: "+e,Toast.LENGTH_SHORT).show();
}
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
try {
Toast.makeText(context,"onUpgrade is called.",Toast.LENGTH_SHORT).show();
db.execSQL(DROP_TABLE);
onCreate(db);
}catch (Exception e){
Toast.makeText(context,"Exception: "+e,Toast.LENGTH_SHORT).show();
}
}
public long insert(String name, String age, String gender)
{
SQLiteDatabase sqLiteDatabase = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(NAME,name);
contentValues.put(AGE,age);
contentValues.put(GENDER,gender);
long rowId = sqLiteDatabase.insert(TABLE_NAME,null,contentValues);
return rowId;
}
public Cursor displayAllData(){
SQLiteDatabase sqLiteDatabase = this.getWritableDatabase();
Cursor cursor = sqLiteDatabase.rawQuery(SELECT_ALL_DATA,null);
return cursor;
}
public boolean updateData(String id, String name, String age, String gender)
{
SQLiteDatabase sqLiteDatabase = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(ID,id);
contentValues.put(NAME,name);
contentValues.put(AGE,age);
contentValues.put(GENDER,gender);
sqLiteDatabase.update(TABLE_NAME, contentValues,ID + " = ?",new String[]{id});
return true;
}
public int deleteData(String id)
{
SQLiteDatabase sqLiteDatabase = this.getWritableDatabase();
return sqLiteDatabase.delete(TABLE_NAME,ID + " = ?", new String[]{id});
}
public void exportDB()
{
}
}
答案 0 :(得分:1)
简而言之,您需要
清单中有:-<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
,如果构建版本为23或更高版本,请在运行时检查/请求它,例如我用:-
if(Build.VERSION.SDK_INT >= 23) {
ExternalStoragePermissions.verifyStoragePermissions(this);
}
以及:-
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.WRITE_EXTERNAL_STORAGE
};
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
);
}
}
}
如果正在使用预写日志记录(WAL),则应关闭数据库或至少检查数据库。在WAL模式下,事务(更新/插入/删除)存储在-wal和-shm文件中,仅当这些事务被提交(关闭或完全检查点)时,数据库的一部分才保留在这些文件中,因此您需要数据。
在日志方式下,对数据库所做的更改存储在-journal文件中。这些可以用来回滚在数据库中所做的更改(在WAL中回滚是从-wal和-shm文件中删除更改,因此它们永远不会应用于数据库文件)。
>添加到您的以下方法 DatabaseHelper 类将在需要时检查数据库:-
private void checkpointIfWALEnabled(Context context, String databaseName) {
Cursor csr;
int wal_busy = -99, wal_log = -99, wal_checkpointed = -99;
SQLiteDatabase db = SQLiteDatabase.openDatabase(context.getDatabasePath(databaseName).getPath(), null, SQLiteDatabase.OPEN_READWRITE);
csr = db.rawQuery("PRAGMA journal_mode", null);
if (csr.moveToFirst()) {
String mode = csr.getString(0);
if (mode.toLowerCase().equals("wal")) {
csr = db.rawQuery("PRAGMA wal_checkpoint", null);
if (csr.moveToFirst()) {
wal_busy = csr.getInt(0);
wal_log = csr.getInt(1);
wal_checkpointed = csr.getInt(2);
}
csr = db.rawQuery("PRAGMA wal_checkpoint(TRUNCATE)", null);
csr.getCount();
csr = db.rawQuery("PRAGMA wal_checkpoint", null);
if (csr.moveToFirst()) {
wal_busy = csr.getInt(0);
wal_log = csr.getInt(1);
wal_checkpointed = csr.getInt(2);
}
}
}
csr.close();
db.close();
}
例如以下是您可以使用的核心代码的示例
public void exportDB() {
this.getWritableDatabase().close();
try {
String dbfilename = this.getDatabasePath(DATABASE_NAME).getPath();
File dbfile = new File(dbfilename);
String backupfilename = (new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),null)).getPath() + File.separator + DATABASE_NAME + "-backup";
checkpointIfWALEnabled(context,DATABASE_NAME);
FileInputStream fis = new FileInputStream(dbfile);
OutputStream backup = new FileOutputStream(backupfilename);
String methodname = new Object() {
}.getClass().getEnclosingMethod().getName();
byte[] buffer = new byte[32768]; //32k buffer, may be changed
int length;
while ((length = fis.read(buffer)) > 0) {
backup.write(buffer, 0, length);
}
backup.flush();
backup.close();
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}