I would like to insert an existing SQLite database into my Android project.
In other words, I do not want to create it, but just to be able to access it within my app.
How would I be able to access the database, and in which folder should I put it?
Well, it's pretty easy, just put your database.db in assets folder and you can use Android SQLiteAssetHelper to read and write the database, this library makes the process pretty easy and straightforward.
Import the library
compile 'com.readystatesoftware.sqliteasset:sqliteassethelper:+'
and then
public class MyDatabase extends SQLiteAssetHelper {
private static final String DATABASE_NAME = "northwind.db";
private static final int DATABASE_VERSION = 1;
public MyDatabase(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
That's all you need to do to access the database.
Here is the full example for your convenience.
You have to add it into asset folder and reference it back in helper class
Put Your Data Base In Asset Folder
public void CopyDataBaseFromAsset() throws IOException {
InputStream in = context.getAssets().open(DATABASE_NAME);
Log.e("sample", "Starting copying");
String outputFileName = DATABASE_PATH+DATABASE_NAME;
File databaseFile = new File( "/data/data/*YOUR PACKGE NAME*/databases");
// check if databases folder exists, if not create one and its subfolders
if (!databaseFile.exists()){
databaseFile.mkdir();
}
OutputStream out = new FileOutputStream(outputFileName);
byte[] buffer = new byte[1024];
int length;
while ((length = in.read(buffer))>0){
out.write(buffer,0,length);
}
Log.e("sample", "Completed" );
out.flush();
out.close();
in.close();
}
Related
I been working on my project for a little bit while, I currently using emulator to access the DB I created. However, I wonder if anyone knows a way to access DB on a real device in DDMS eclipse?
I understand that to access DB on emulator is just open the data/data/package_name/database...I couldn't really find a way to check out DB on my real device. (The is some security issue in android device) The reason I want to use this is sometimes, emulator doesn't support GPS signal. Does any one knows is there any third-party lib/plugin I can download from ? Thank you so much.
i think it is work for you
**I am copy database in SdCard then access ** .
it is my database helper class
public class OpenDatabaseHelper extends SQLiteOpenHelper {
static final String DATABASE_NAME = "MyDB";
.
.
.
public OpenDatabaseHelper(Context context) {
// super(context, name, factory, version);
super(context, Environment.getExternalStorageDirectory()
+ File.separator + "/DataBase/" + File.separator
+ DATABASE_NAME, null, DATABASE_VERSION);
// TODO Auto-generated constructor stub
}
.
.
.
}
create object in Activity class
OpenDatabaseHelper db = new OpenDatabaseHelper(YourActivity.this);
call any method of database
db.DataBasemethod();
then put this code
try {
String destPath = Environment.getExternalStorageDirectory().toString();
File f = new File(destPath);
if (!f.exists()) {
f.mkdirs();
f.createNewFile();
// ---copy the db from the /data/data/ folder into
// the sdcard databases folder--- here MyDB is database name
CopyDB(new FileInputStream("/data/data/" + getPackageName()+ "/databases"), new FileOutputStream(destPath+ "/MyDB"));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
public void CopyDB(InputStream inputStream, OutputStream outputStream)
throws IOException {
// ---copy 1K bytes at a time---
byte[] buffer = new byte[1024];
int length;
while ((length = inputStream.read(buffer)) > 0) {
outputStream.write(buffer, 0, length);
}
inputStream.close();
outputStream.close();
}
I'm perfectly able to use Sugar ORM using provided examples.
In my usecase I download a SQLite DB from the server (ETL load for it is in millions of records so has to be done server side). The download saves to a custom path on internal storage.
In my case I do not need dynamic DB creation based on POCOs.
Is it possible to use Sugar ORM with pre-existing SQLite DB, pointing to a custom path, provided if all POCO classes fields match the table structure?
First of all, I am not comfortable with the idea that Sugar extends
the app class. What if I have other tasks need to be carried out
before app start?! So let's extend SugarApp with our own
AppClass then register the appClass name in manifest. Also, this is the right place to init db the first time I believe.
public class MyAppStartClass extends SugarApp {
#Override
public final void onCreate() {
init();
super.onCreate();
}
private void init() {
initDB();
}
private void initDB() {
try {
if (!doesDatabaseExist(this, consts.dbPath)) {
Context context = getApplicationContext();
SQLiteDatabase db = context.openOrCreateDatabase(consts.dbName, context.MODE_PRIVATE, null);
db.close();
InputStream dbInput = getApplicationContext().getAssets().open(consts.dbName);
String outFileName = consts.dbPath;
OutputStream dbOutput = new FileOutputStream(outFileName);
try {
byte[] buffer = new byte[1024];
int length;
while ((length = dbInput.read(buffer)) > 0) {
dbOutput.write(buffer, 0, length);
}
} finally {
dbOutput.flush();
dbOutput.close();
dbInput.close();
}
}
} catch (Exception e) {
e.toString();
}
}
private boolean doesDatabaseExist(ContextWrapper context, String dbName) {
File dbFile = context.getDatabasePath(dbName);
return dbFile.exists();
}
}
Manifest: android:name="com.myPackageName.MyAppStartClass"
Make sure you create an empty db first, if you don't you'll get an error from FileOutputStream() and dbPath = /data/data/com.myPackageName/databases/myDb.db
SQLiteDatabase db = context.openOrCreateDatabase(consts.dbName, context.MODE_PRIVATE, null);
db.close();
Make sure your existing db schema has a primary key column ID. Oh yeah! Sugar only sees ID as primary key to retrieve data.
If you want to use existing tables, do NOT specify T when you extend SugarRecord AND you have to add Sugar as a module and your project depends on it!
public class Book extends SugarRecord {
String title;
String edition;
public Book(){
}
public Book(String title, String edition){
this.title = title;
this.edition = edition;
}
}
6.If you want to use existing tables. Be aware that Sugar looks for UPPERCASE column names so if your existing table column names are lowercase you will never get any existing data out of it!
7.That leads me to a reluctant conclusion: Sugar is great if your start db from scratch and use it to generate db and tables for you. But not so when you have already had an existing db with data in it.
The solution I found, was by putting your db file inside of assets folder. Instead of reading a .csv file to create a .db file ( when you start the proper activity) firstly try to check if the .db file is in /data/data/file.db, if it isn't, copy it from your assets folder to that path. With the next code you will be able to make all:
protected void copyDataBase() throws IOException {
//Open your local db as the input stream
InputStream myInput = getApplicationContext().getAssets().open("file.db");
// Path to the just created empty db
String outFileName = "/data/data/com.yourpackagename/databases/" + "file.db";
//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();
}
protected boolean checkDataBase(){
SQLiteDatabase checkDB = null;
try{
String myPath = "/data/data/com.yourpackage/databases/" + "file.db";
checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
}catch(SQLiteException e){
//database does't exist yet.
}
if(checkDB != null){
checkDB.close();
}
return checkDB != null ? true : false;
}
I haven't tried it yet. Though, if you could copy your database file to /data/data//db_name.db location and use the same db_name & db version in the sugar config in manifest, it should just pick it up.
I have an android application that is supposed to read and expand a database that is already created on sqlite...it works fine on emulator by putting database in "data/data/(packagename)/database" folder on the file explorer of emulator. Now problem is occuring with the real device. Obviously it doesnt have the database to open.I tried to put database in assets folder but I am not getting to open it with the openhelper.
you should copy the .db file from your assets folder to an internal/external storage. You can use following codes,
private static String DB_PATH = "/data/data/your package/database/";
private static String DB_NAME ="final.db";// Database name
To create a database,
public void createDataBase() throws IOException
{
//If database not exists copy it from the assets
boolean mDataBaseExist = checkDataBase();
if(!mDataBaseExist)
{
try
{
//Copy the database from assests
copyDataBase();
Log.e(TAG, "createDatabase database created");
}
catch (IOException mIOException)
{
throw new Error("ErrorCopyingDataBase");
}
}
}
Check that the database exists here: /data/data/your package/database/DB Name
private boolean checkDataBase()
{
File dbFile = new File(DB_PATH + DB_NAME);
return dbFile.exists();
}
Copy the database from assets
private void copyDataBase() throws IOException
{
InputStream mInput = getApplicationContext().getAssets().open(DB_NAME);
String outFileName = DB_PATH + DB_NAME;
OutputStream mOutput = new FileOutputStream(outFileName);
byte[] mBuffer = new byte[1024];
int mLength;
while ((mLength = mInput.read(mBuffer))>0)
{
mOutput.write(mBuffer, 0, mLength);
}
mOutput.flush();
mOutput.close();
mInput.close();
}
i hope it should help you.
you cant access the database from asset folder directly you need to copy it first to the path data/data/(packagename)/database then using it :
private String DB_PATH = "/data/data/" + "yourpackaename" + "/databases/" + "db.db";
in your onCreate()
is = getAssets().open("db.db");
write(is);
Then the method to call:
public void write(InputStream is) {
try {
OutputStream out = new FileOutputStream(new File(DB_PATH));
int read = 0;
byte[] bytes = new byte[1024];
while ((read = is.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
is.close();
out.flush();
out.close();
System.err.println(out + "\n");
} catch (IOException e) {
e.printStackTrace();
}
}
You need to first copy the Database file from assests to application data location using java code.Can You Post some code to show How are you opening or handling the database?
You cannot directly open files from assets folder. Instead, you need to copy the contents of your assets folder on an internal/external storage and later use the File path to open the file.
In emulators, its easier for you to access the data folder of your apps. However, on a real non-rooted android device, its not possible due to security reasons.
Do you have a pre-populated database and looking to integrate into your app? If yes, you can simply do with my library
On your app's first launch after installation
SuperDatabase database=new SuperDatabase(getApplicationContext(),"foods.db", AssetDatabaseMode.COPY_TO_SYSTEM);
On subsequent launches
SuperDatabase database=new SuperDatabase(getApplicationContext(),"foods.db", AssetDatabaseMode.READ_FROM_DEVICE);
Simply fire SQL queries
database.sqlInject("INSERT INTO food VALUES('Banana','Vitamin A');");
Get results on Array in CSV, JSON, XML
ArrayList<String> rows=new ArrayList<String>();
rows=database.sqlEjectCSV("SELECT * FROM food;");
for (int i=0;i<rows.size();i++)
{
//Do stuffs with each row
}
You need to include my library for this. Documentations here:
https://github.com/sangeethnandakumar/TestTube
I'm developing directly on the mobile device, and I have some questions you hopefully could help me clarify about development using a database:
My app is meant to use a SQLite database (readonly mode), so I'd like
to know where I should place the .sqlite file created on the pc, in
order for the app to read or even directly.
Later, the app is supposed to download the db file from a
centralized server. So, the idea is to keep putting that file in the
same location, one the app will surely know and could check if it
exists just before trying to use it.
Thanks!
You will need to package your SQLite database as a resource (e.g., res/raw) or asset with your application. However, you won't be able to use the packaged SQLite database directly. You will need to copy it to where Android expects your app's database files to be located and then use it from there. The best way to do this is to use Context.getDatabasePath(String) (passing the name of the database file) to determine the file path. That's also where you should place a database file that your app downloads at run time.
You need to copy the database file into your assets folder, then write it to memory to access in the app using the following code:
public class DataBaseHelper extends SQLiteOpenHelper{
private static final String TAG = "DataBaseHelper";
//The Android's default system path of your application database.
private static String DB_PATH = "/data/data/" + Constants.package_name + "/databases/";
private static String DB_NAME = "YourDatabaseName.db";
public 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() throws IOException{
boolean dbExist = checkDataBase();
if(dbExist){
//do nothing - database already exist
}else{
//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.getWritableDatabase();
try {
copyDataBase();
} catch (IOException e) {
throw new Error("Error copying database");
}
}
}
/**
* 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_READWRITE);
}catch(SQLiteException e){
//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{
//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;
//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[2048];
int length;
while ((length = myInput.read(buffer))>0){
myOutput.write(buffer, 0, length);
}
//Close the streams
myOutput.flush();
myOutput.close();
myInput.close();
}
public void openDataBase() throws SQLException{
//Open the database
String myPath = DB_PATH + DB_NAME;
myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);
}
#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) {
}
Hope this helps.
I put my initial database in 'assets' directory and then copy it on user-accessable path - like external memory (sdcard and so on). I hadn't any troubles using this way :)
I would suggest if you want to insert data as well rather just fetching values
you can make database inside the application
which will always have the path
like
/data/data/your_project_name/databases/yourdatabase_name
http://www.anotherandroidblog.com/2010/08/04/android-database-tutorial/
I have a pre-existing sqlite database that is about 5mb in size. I use this code to copy from my assets folder to the packages/databases folder on the device.
The database copies to the device but the data inside the database has been deleted or is missing. The only table inside is called android_metadata.
Here is the code:
try{
InputStream myInput = myContext.getAssets().open(DB_NAME);
// Path to the just created empty db
String outFileName = DB_PATH + DB_NAME;
//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();
}catch(SQLiteException e){
If your database (tables) is (are) not appearing / loading, then it is likely that you have created it inproperly. I would go back and ensure that you have set it up correctly.
Make sure your database is in YourAppName\assets\databases folder.
For example, if your database name is: app.db, it should be in that folder to be copied.
You need to reinstall your app whenever you want to release a new copy of the database.
If you are using the SQLiteAssetHelper, your class file will look somewhat like this:
package com.mycompany.myapp;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import com.readystatesoftware.sqliteasset.SQLiteAssetHelper;
public class MyDatabase extends SQLiteAssetHelper {
private static final String DATABASE_NAME = "app.db";
private static final int DATABASE_VERSION = 1;
public MyDatabase(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
// you can use an alternate constructor to specify a database location
// (such as a folder on the sd card)
// you must ensure that this folder is available and you have permission
// to write to it
// super(context, DATABASE_NAME, context.getExternalFilesDir(null).getAbsolutePath(), null, DATABASE_VERSION);
}
public Cursor mymethod (String param) {
SQLiteDatabase db = getReadableDatabase();
String sql;
sql = "...";
Cursor c = db.rawQuery(sql, new String[] { param });
c.moveToFirst();
return c;
}}