如果您的应用程序需要一个数据库,并且它带有内置数据,那么最好的运输方法是什么? 我是不是该:
预先创建SQLite数据库并将其包含在
.apk
?在应用程序中包括SQL命令,并让它创建数据库并在首次使用时插入数据吗?
我看到的缺点是:
可能的SQLite版本不匹配可能会导致问题,并且我目前不知道数据库应该去哪里以及如何访问它。
在设备上创建和填充数据库可能会花费很长时间。
有什么建议么? 有关任何问题的文档指针将不胜感激。
#1楼
SQLiteAssetHelper
库使此任务非常简单。
添加为gradle依赖关系很容易(但是Jar也可用于Ant / Eclipse),并且与文档一起可以在以下位置找到:
https://github.com/jgilfelt/android-sqlite-asset-helper
注意:该项目不再按上述Github链接中所述进行维护。
如文档中所述:
将依赖项添加到模块的gradle构建文件中:
dependencies { compile 'com.readystatesoftware.sqliteasset:sqliteassethelper:+' }
将数据库复制到资产目录中的一个名为
assets/databases
的子目录中。 例如:assets/databases/my_database.db
(可选地,您可以使用zip文件(例如
assets/databases/my_database.zip
)压缩assets/databases/my_database.zip
。这是不需要的,因为APK已被整体压缩。)创建一个类,例如:
public class MyDatabase extends SQLiteAssetHelper { private static final String DATABASE_NAME = "my_database.db"; private static final int DATABASE_VERSION = 1; public MyDatabase(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } }
#2楼
将数据库运送到apk内,然后将其复制到/data/data/...
将使数据库大小增加一倍(在apk中为1,在data/data/...
),并且会增加apk的大小(课程)。 因此,您的数据库不应太大。
#3楼
如果所需数据不太大(我不知道限制,取决于很多因素),则还可以从网站/ webapp下载数据(以XML,JSON等格式)。 接收后,使用接收到的数据执行SQL语句,以创建表并插入数据。
如果您的移动应用程序包含大量数据,则以后可能更容易用更准确的数据或更改来更新已安装的应用程序中的数据。
#4楼
最后我做到了! 我已使用此链接帮助在Android应用程序中使用您自己的SQLite数据库 ,但不得不对其进行一些更改。
如果您有许多软件包,则应在此处输入主软件包名称:
private static String DB_PATH = "data/data/masterPakageName/databases";
我更改了将数据库从本地文件夹复制到仿真器文件夹的方法! 该文件夹不存在时出现了一些问题。 因此,首先,它应检查路径,如果路径不存在,则应创建文件夹。
在上面的代码中,
copyDatabase
方法从来没有所谓当数据库不存在与checkDataBase
造成异常的方法。 所以我稍微修改了代码。如果您的数据库没有文件扩展名,请不要在文件名中使用一个扩展名。
它对我来说很好,我希望它对你也有用
package farhangsarasIntroduction;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
public class DataBaseHelper extends SQLiteOpenHelper{
//The Android's default system path of your application database.
private static String DB_PATH = "data/data/com.example.sample/databases";
private static String DB_NAME = "farhangsaraDb";
private SQLiteDatabase myDataBase;
private final Context myContext;
/**
* Constructor
* Takes and keeps a reference of the passed context in order to access to the application assets and resources.
* @param context
*/
public DataBaseHelper(Context context) {
super(context, DB_NAME, null, 1);
this.myContext = context;
}
/**
* Creates a empty database on the system and rewrites it with your own database.
* */
public void createDataBase() {
boolean dbExist;
try {
dbExist = checkDataBase();
} catch (SQLiteException e) {
e.printStackTrace();
throw new Error("database dose not exist");
}
if(dbExist){
//do nothing - database already exist
}else{
try {
copyDataBase();
} catch (IOException e) {
e.printStackTrace();
throw new Error("Error copying database");
}
//By calling this method and empty database will be created into the default system path
//of your application so we are gonna be able to overwrite that database with our database.
this.getReadableDatabase();
}
}
/**
* Check if the database already exist to avoid re-copying the file each time you open the application.
* @return true if it exists, false if it doesn't
*/
private boolean checkDataBase(){
SQLiteDatabase checkDB = null;
try{
String myPath = DB_PATH +"/"+ DB_NAME;
checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
}catch(SQLiteException e){
//database does't exist yet.
throw new Error("database does't exist yet.");
}
if(checkDB != null){
checkDB.close();
}
return checkDB != null ? true : false;
}
/**
* Copies your database from your local assets-folder to the just created empty database in the
* system folder, from where it can be accessed and handled.
* This is done by transfering bytestream.
* */
private void copyDataBase() throws IOException{
//copyDataBase();
//Open your local db as the input stream
InputStream myInput = myContext.getAssets().open(DB_NAME);
// Path to the just created empty db
String outFileName = DB_PATH +"/"+ DB_NAME;
File databaseFile = new File( DB_PATH);
// check if databases folder exists, if not create one and its subfolders
if (!databaseFile.exists()){
databaseFile.mkdir();
}
//Open the empty db as the output stream
OutputStream myOutput = new FileOutputStream(outFileName);
//transfer bytes from the inputfile to the outputfile
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer))>0){
myOutput.write(buffer, 0, length);
}
//Close the streams
myOutput.flush();
myOutput.close();
myInput.close();
}
@Override
public synchronized void close() {
if(myDataBase != null)
myDataBase.close();
super.close();
}
@Override
public void onCreate(SQLiteDatabase db) {
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
you to create adapters for your views.
}
#5楼
Android已经提供了一种版本感知的数据库管理方法。 BARACUS框架已将这种方法用于Android应用程序。
它使您能够在应用程序的整个版本生命周期中管理数据库,从而能够将sqlite数据库从任何先前版本更新到当前版本。
我不确定100%,但是特定设备的热恢复可能使您能够在应用中发布准备好的数据库。 但是我不确定特定于某些设备,供应商或设备一代的数据库二进制格式。
由于这些东西是Apache License 2,请随时重用代码的任何部分, 可以在github上找到它们
编辑:
如果只想发送数据,则可以考虑在应用程序首次启动时实例化和持久化POJO。 BARACUS为此提供了内置支持(用于配置信息的内置键值存储,例如“ APP_FIRST_RUN”以及后上下文自举程序挂钩,以便在上下文中运行发布后操作)。 这使您可以在应用程序中附带紧密耦合的数据。 在大多数情况下,这适合我的用例。
#6楼
我的解决方案既不使用任何第三方库,也不强制您在SQLiteOpenHelper
子类上调用自定义方法以在创建时初始化数据库。 它还负责数据库升级。 所有需要做的就是SQLiteOpenHelper
。
先决条件:
- 您希望随应用程序一起提供的数据库。 它应包含一个名为
android_metadata
的1x1表,该表除了应用程序特有的表外,其属性locale
的值为en_US
。
子类化SQLiteOpenHelper
:
- 子类
SQLiteOpenHelper
。 - 在
SQLiteOpenHelper
子类中创建一个private
方法。 此方法包含将数据库内容从“ assets”文件夹中的数据库文件复制到在应用程序包上下文中创建的数据库的逻辑。 - 覆盖
SQLiteOpenHelper
onCreate
,onUpgrade
和onOpen
方法。
说够了。 这里是SQLiteOpenHelper
子类:
public class PlanDetailsSQLiteOpenHelper extends SQLiteOpenHelper {
private static final String TAG = "SQLiteOpenHelper";
private final Context context;
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME = "my_custom_db";
private boolean createDb = false, upgradeDb = false;
public PlanDetailsSQLiteOpenHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
this.context = context;
}
/**
* Copy packaged database from assets folder to the database created in the
* application package context.
*
* @param db
* The target database in the application package context.
*/
private void copyDatabaseFromAssets(SQLiteDatabase db) {
Log.i(TAG, "copyDatabase");
InputStream myInput = null;
OutputStream myOutput = null;
try {
// Open db packaged as asset as the input stream
myInput = context.getAssets().open("path/to/shipped/db/file");
// Open the db in the application package context:
myOutput = new FileOutputStream(db.getPath());
// Transfer db file contents:
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer)) > 0) {
myOutput.write(buffer, 0, length);
}
myOutput.flush();
// Set the version of the copied database to the current
// version:
SQLiteDatabase copiedDb = context.openOrCreateDatabase(
DATABASE_NAME, 0, null);
copiedDb.execSQL("PRAGMA user_version = " + DATABASE_VERSION);
copiedDb.close();
} catch (IOException e) {
e.printStackTrace();
throw new Error(TAG + " Error copying database");
} finally {
// Close the streams
try {
if (myOutput != null) {
myOutput.close();
}
if (myInput != null) {
myInput.close();
}
} catch (IOException e) {
e.printStackTrace();
throw new Error(TAG + " Error closing streams");
}
}
}
@Override
public void onCreate(SQLiteDatabase db) {
Log.i(TAG, "onCreate db");
createDb = true;
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.i(TAG, "onUpgrade db");
upgradeDb = true;
}
@Override
public void onOpen(SQLiteDatabase db) {
Log.i(TAG, "onOpen db");
if (createDb) {// The db in the application package
// context is being created.
// So copy the contents from the db
// file packaged in the assets
// folder:
createDb = false;
copyDatabaseFromAssets(db);
}
if (upgradeDb) {// The db in the application package
// context is being upgraded from a lower to a higher version.
upgradeDb =