1

在模拟器中,db 文件位于 /data/data/com.example.app_name/databases/data.db 内。但在真实设备中不存在这样的目录。由于哪个应用程序崩溃。应用程序在模拟器中运行顺利。

在真实设备中存在 android/data 文件夹,但它不包含我的应用程序命名文件夹。

此外,当我通过 toast 通过设备内部的 this.getDatabasePath() 显示应用程序的目录时,它会显示 //data/data/com.example.My_App 但是一旦数据库活动开始应用程序就会崩溃。并且 com.example.My_App 文件夹在 android/data 中不存在。

我尝试在 android/data 中创建数据文件夹并将所有数据库文件放入其中,但仍然无法正常工作。还尝试在存在 android 文件夹但没有发生任何事情的手机内存中创建它。请帮帮我。答案将不胜感激。

4

5 回答 5

2

为了克服这个问题,您可以在手机的 SD 卡中创建您的数据库。它工作顺利,用户也可以访问。如果涉及安全性,则使用 res/raw 文件夹,以便用户无法访问它。要在 SD 卡上创建数据库,您可以使用以下代码(它是示例代码)...

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();
    }
}
于 2013-07-29T10:08:31.833 回答
2

尝试使用此示例类将数据库从资产复制到应用程序包,并将数据库从应用程序包拉到 sd 卡路径

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) {
    }
}

调用创建数据库和复制数据库

@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();
    }
}
于 2013-07-29T11:21:24.757 回答
0

您必须 root 手机才能访问应用程序 db 文件,即便如此,您也必须更改对 data/ 文件夹的访问权限。如果您想打开并读取 sd 卡或资产文件夹中的一些 db 文件,您可以在不生根的情况下执行此操作。

于 2013-07-29T10:01:19.513 回答
0

在真正的 android 设备中,您将无法访问数据文件夹。为此,您需要一个有根设备。

于 2013-07-29T09:24:25.937 回答
0

我建议您压缩您的数据库文件,并将其放在应用程序的 res/raw 目录中。做这样的事情;

// 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;
}
于 2013-07-29T09:29:00.537 回答