How to use .db file on an android device?

2019-08-14 19:51发布

问题:

In emulator db file is located inside the /data/data/com.example.app_name/databases/data.db. But in real device no such directory exists. Due to which application crashes. Application is running smoothly in emulator.

In real device android/data folder exists but it does not contain my application named folder.

Also, when I displayed the directory for application through this.getDatabasePath() inside the device via toast it displays //data/data/com.example.My_App but as soon as database activity starts application crashes. And the com.example.My_App folder does not exists in android/data.

I have tried creating data folder inside android/data and put up all the database files in it but still did not worked. Also tried on creating it at phone memory where android folder exists but nothing happened. Please help me out. Answers will be appreciated.

回答1:

For overcoming this problem You can create Your database in SD card of mobile. It work smoothly and also accessed by user. If security is concerned then Use res/raw folder so that User did not access it. for Creating database on SD card you can use following Code(It is Sample Code)...

public static void saveExpanseForm(Context con,NewExpenseForm newexpanse) throws Exception {        
    SQLiteDatabase sampleDB = null;

    try {

        File sdcard;
        if (android.os.Environment.getExternalStorageState().equals( android.os.Environment.MEDIA_MOUNTED)){
            sdcard = new File(Environment.getExternalStorageDirectory(), "ROIApp");
            sdcard.mkdirs();
        } else {
            /* save the folder in internal memory of phone */
            sdcard = new File(Environment.getRootDirectory(),"ROIApp");
            sdcard.mkdirs();

        }

        String dbfile = sdcard.getAbsolutePath() + File.separator+ "RoiAppDB" + File.separator + NETNOTENABLE_DB_NAME;
        sampleDB = con.openOrCreateDatabase(dbfile, MODE_PRIVATE,null);

        sampleDB.execSQL("CREATE TABLE IF NOT EXISTS " + Expense_TABLE_NAME +
                " (id INTEGER PRIMARY KEY AUTOINCREMENT, Currentdate varchar, dateFormat varchar, Name varchar, Category varchar,"+
                " Location varchar,Cost varchar,Sex INTEGER, Tags varchar, Notes varchar, In1 varchar, In2 varchar, " +
                "Remindme INTEGER, ImagePath varchar);");

        sampleDB.execSQL("INSERT INTO " + Expense_TABLE_NAME +
                "(Currentdate, dateFormat, Name, Category, Location,Cost, Sex, Tags, Notes, In1, In2, Remindme, ImagePath ) Values ('"
                +newexpanse.getDates()+"','"+newexpanse.getDateFormat()+"','"+newexpanse.getName()+"','"+
                newexpanse.getCategory()+"','"+newexpanse.getLocation()+"','"+newexpanse.getCost()+"','"+newexpanse.getSex()+"','"+newexpanse.getTag()+"','"
                +newexpanse.getNotes()+"','"+newexpanse.getInstr1()+"','"+newexpanse.getInstr2()+"','"
                +newexpanse.getRemindme()+"','"+newexpanse.getImageName()+"');");

        Log.e("ExpanseTable", " ExpanseInsert "+"INSERT INTO " + Expense_TABLE_NAME +
                "(Currentdate, dateFormat, Name, Category, Location,Cost, Sex, Tags, Notes, In1, In2, Remindme,ImagePath ) Values ('"
                +newexpanse.getDates()+"','"+newexpanse.getDateFormat()+"','"+newexpanse.getName()+"','"+
                newexpanse.getCategory()+"','"+newexpanse.getLocation()+"','"+newexpanse.getCost()+"','"+newexpanse.getSex()+"','"+newexpanse.getTag()+"','"
                +newexpanse.getNotes()+"','"+newexpanse.getInstr1()+"','"+newexpanse.getInstr2()+"','"
                +newexpanse.getRemindme()+"','"+newexpanse.getImageName()+"');");

        insertNewExpanseForm(sampleDB);

    } catch (SQLiteException e) {
        // TODO: handle exception
        e.printStackTrace();
    }
    finally {
        if (sampleDB != null)
            sampleDB.close();
    }
}


回答2:

Try this sample class to copy database from assets to application package and to pull data base from application package to sd card path

DBHelper.java

    import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.channels.FileChannel;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Environment;
import android.util.Log;

public class DBHelper extends SQLiteOpenHelper {

    private static String DB_PACKAGE_PATH = "/data/data/applicationPackageName/databases/";

    private static String DATABASE_NAME = "data.db";

    private SQLiteDatabase db;

    private final Context context;

    /**
     * 
     * @param context
     */
    public DBHelper(final Context context) {
        super(context, DATABASE_NAME, null, 1);
        this.context = context;
        DB_PACKAGE_PATH = "/data/data/" + context.getPackageName()
                + "/databases/";
    }

    public final void createDataBaseFromAppAssetsDir() throws IOException {

        final boolean dbExist = isDBExist();
        SQLiteDatabase db_Read = null;
        if (!dbExist) {
            // ****** required****
            // as it will create empty database file.
            // and assets file will be overwrite on this db file
            db_Read = this.getReadableDatabase();
            db_Read.close();
            try {
                copyDbFile();
            } catch (IOException e) {
                throw new Error("Error copying database");
            }

        }
    }

    public void copyFromDataPackgeToSdCard() throws IOException {
        try {
            File sdCard = Environment.getExternalStorageDirectory();
            File appDataDir = Environment.getDataDirectory();
            if (sdCard.canWrite()) {
                String currentDBPath = "//data//"
                        + this.context.getPackageName() + "//databases//"
                        + DATABASE_NAME;
                String backupDBPath = DATABASE_NAME;
                File currentDatabase = new File(appDataDir, currentDBPath);
                File backupDatabase = new File(sdCard, backupDBPath);

                if (currentDatabase.exists()) {
                    FileChannel src = new FileInputStream(currentDatabase)
                            .getChannel();
                    FileChannel dst = new FileOutputStream(backupDatabase)
                            .getChannel();
                    dst.transferFrom(src, 0, src.size());
                    src.close();
                    dst.close();
                }
            }
        } catch (Exception e) {
            Log.e("copyFromDataPackgeToSdCard", e.getMessage());
        }
    }

    private boolean isDBExist() {
        final File dbFile = new File(DB_PACKAGE_PATH + DATABASE_NAME);
        return dbFile.exists();
    }

    private void copyDbFile() throws IOException {

        final InputStream myInput = context.getAssets().open(DATABASE_NAME);
        final String outFileName = DB_PACKAGE_PATH + DATABASE_NAME;
        final OutputStream myOutput = new FileOutputStream(outFileName);
        final byte[] buffer = new byte[1024];
        int length;
        while ((length = myInput.read(buffer)) > 0) {
            myOutput.write(buffer, 0, length);
        }

        myOutput.flush();
        myOutput.close();
        myInput.close();

    }

    public final void openDataBase() throws Exception {
        final String myPath = DB_PACKAGE_PATH + DATABASE_NAME;
        db = SQLiteDatabase.openDatabase(myPath, null,
                SQLiteDatabase.OPEN_READONLY);
    }

    @Override
    public final synchronized void close() {
        if (db != null)
            db.close();
        super.close();
    }

    @Override
    public void onCreate(final SQLiteDatabase arg0) {
    }

    @Override
    public void onUpgrade(final SQLiteDatabase arg0, final int arg1,
            final int arg2) {
    }
}

Call Create DB & Copy DB

@Override
public void onClick(View v) {
    try {
        switch (v.getId()) {
        case R.id.btn_create_db_from_assets:
            // Create DataBase From Assets Folder to Application database
            // package . u can call this on startup.Use this onStart up
            clsHelper.createDataBaseFromAppAssetsDir();
            break;
        case R.id.btn_copy_to_sdcard:
            // Copy database from applicaiton data packages to sd card. to
            // avid root access and all for device
            clsHelper.copyFromDataPackgeToSdCard();
            break;
        default:
            break;
        }
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}


回答3:

In a real android device the you will not get access to data folder. You need a rooted device for that.



回答4:

I would suggest that you ZIP your database file, and put it in the res/raw directory of your application. And do something like this;

// Call this whenever the application starts, or at another suitable place, for example in a
// Content providers create method.

public void createDataBaseIfDoesNotExist() throws IOException {
        boolean dbExist = doesDatabaseExist();
        if (!dbExist) {
            try {
                copyDataBase();
            } catch (IOException e) {
                Log.e(TAG, e.getMessage(), e);
                throw new Error("Error copying database ");
            }
        }
    }

// Extracts the Compressed database file to the database directory of your application
private void copyDataBase() throws IOException {
    InputStream myInput = myContext.getResources().openRawResource(R.raw.abbrev);
    ZipInputStream zis = new ZipInputStream(myInput);
    zis.getNextEntry();

    File outFile  = myContext.getDatabasePath(DATABASE_NAME);
    OutputStream myOutput = new FileOutputStream(outFile);
    byte[] buffer = new byte[1024];
    int length;
    while ((length = zis.read(buffer)) > 0) {
        myOutput.write(buffer, 0, length);
    }
    myOutput.flush();
    myOutput.close();
    myInput.close();
}

// Checks if database exists
private boolean doesDatabaseExist() {
    SQLiteDatabase checkDB = null;
    try {
        String myPath =myContext.getDatabasePath(DATABASE_NAME).toString();
        checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
    } catch (SQLiteException e) {
    }
    if (checkDB != null) {
        checkDB.close();

    }
    return checkDB != null ? true : false;
}


回答5:

You must root your phone in order to access applications db files, and even then you will have to change access rights on folders in data/ . If you want to open and read some db file on sd card or in assets folder you can do that without rooting.