在我的应用程序中,有一个由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()
{
}
}
简言之,你需要
>
在清单中有:-
如果构建版本为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();
}
}
注意:上面的代码是从更复杂的代码中提取出来的,并且经过了轻微的调整。它尚未测试或运行,因此可能存在一些小错误
我试图使用Adobe reader读取从服务器下载的pdf文件,但问题是当我将其存储在内部存储时,其他应用程序无法读取该文件。现在我想知道如何将此文件复制到外部存储(/sdcard/)中,以便pdf查看器可以查看。 由于安全原因,我将文件存储在内部存储,然后删除外部存储的文件。 我的问题是如何复制保存在内部存储中的文件,而不使用raw或将其放入InputStream中的资产。
问题内容: 我的应用程序( Android API 15 )制作图片并将其存储在内部存储器的文件夹中。现在,我想将此文件复制到外部存储中的另一个文件夹,例如。我尝试了以下方法: 方法1: 方法2: 方法3: 这些方法都不能解决我的任务。在检查了许多相关主题之后,我发现的唯一建议是验证 在和它确实存在。 该 方法#1 完成执行,但没有文件夹和文件被复制。 在 方法#2 ,应用程序失败,异常的,但对象
这些方法都不能解决我的任务。中检查了一些相关主题,我发现的唯一建议是验证 在中,并且它仍然存在。 方法#1完成执行,但没有复制文件夹和文件。 因为这是我迈向Android的第一步,我觉得我错过了一些小东西。请告诉我,如何在Android中将文件从一个文件夹复制到另一个文件夹,包括文件从内部内存移动到外部内存。
问题内容: 如何复制到外部存储保持,以便以后可以共享首选项。 试图读取并另存为一个文件,创建了类型,但我需要一个。想过遍历应用程序的内部存储和复制文件,然后将其放入外部存储,但这可能太复杂了。 真的很想知道是否存在一种简单而明智的方式来传递`sharedpreferences。 问题答案: 使用此代码, 并取回它, 注意 使用此代码只能处理字符串类型首选项,
我写了一个Android应用。导出为签名APK发送通过邮件安装到设备。-不在市场。 在运行时,它将用类似的代码将他们的数据保存到内部存储: 据我所知-如果我错了,请纠正我-它将保存到/data/data/com。我的公司。myapp/文件名 因为它是用保存的,所以我不确定市场上或我的其他应用程序是否能看到它保存它。也许如果我创建一个具有相同签名的应用程序? 手机没有根。我已经尝试了很多备份,应用程
那是外部存储代码,但我想保存在Android手机的内部存储。