Java SQLiteOpenHelper不从资源安装数据库文件

Java SQLiteOpenHelper不从资源安装数据库文件,java,android,sqliteopenhelper,Java,Android,Sqliteopenhelper,安装应用程序时,is将创建一个与DBHelper类中指定的名称相同的空数据库,而不是从资产/数据库复制数据库文件并将其安装到设备上的应用程序目录中 创建的Sqlite文件具有相同的名称,但它只包含一个名为android\u metadata的表和一个名为android\u metadata的行。我知道这一点,因为我使用设备监视器检索了文件 之前一切正常,资产数据库自动安装,然后突然出现这种情况 DBHelper: public class DBHelper extends SQLiteOpenH

安装应用程序时,is将创建一个与DBHelper类中指定的名称相同的空数据库,而不是从资产/数据库复制数据库文件并将其安装到设备上的应用程序目录中

创建的Sqlite文件具有相同的名称,但它只包含一个名为android\u metadata的表和一个名为android\u metadata的行。我知道这一点,因为我使用设备监视器检索了文件

之前一切正常,资产数据库自动安装,然后突然出现这种情况

DBHelper:

public class DBHelper extends SQLiteOpenHelper {

private static String TAG = "DBHelper";
private static final String DB_PATH = "/data/data/com.borehog.express.bhexpress/databases/";
private static String DB_NAME = "BHMock.db";
private static int DB_VERSION = 1;

private static DBHelper db;
private static Context context;

/**
 * Constructor should be private to prevent direct instantiation.
 * Make a call to the static method "getInstance()" instead.
 */
private DBHelper(Context context) {
    super(context, DB_NAME, null, DB_VERSION);
}

public static synchronized DBHelper getInstance(Context context) {
    // Use the application context, which will ensure that you
    // don't accidentally leak an Activity's context.
    if (db == null) {
        db = new DBHelper(context.getApplicationContext());
    }

    Log.d(TAG, "getInstance()");
    return db;
}


public DBHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
    super(context, name, factory, version);

    this.context = context;
    Log.d(TAG, "DBHelper() Init");

}

@Override
public void onCreate(SQLiteDatabase db) {

    try {

        if(dbExist()) {
            Log.d(TAG, "DB Exists");
        }

        Log.d(TAG, "onCreate()");

    } catch (Exception ex) {
        Log.d(TAG, "onCreate: " + ex.getMessage());
    }

}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    try {
        Log.d(TAG, "onUpgrade()");

    } catch (Exception ex) {
        Log.d(TAG, "onUpgrade: " + ex.getMessage());
    }

}
}
我按如下方式初始化数据库:

db=DBHelper.getInstance(getApplicationContext())

但由于某些原因,它没有安装来自资产的嵌入式数据库。
有什么想法吗?

这里是满足您需求的最佳方法

这样使用:

public class DbAdapter {

    private static final String TAG = DbAdapter.class.getSimpleName();

    public static Context context;
    public static DataBaseHelper DBHelper;
    public static SQLiteDatabase mDb;
    private static String DB_PATH = "";
    private static final String DATABASE_NAME = "BHMock.sqlite";
    private static final String ASSETS_DATABASE_NAME = "BHMock.sqlite";
    private static final int DATABASE_VERSION = 1;

    /**
     * This is singleton pattern means : There is one instance of DBHelper in
     * all application : If object created then it will return old instance : If
     * not then create new DBHelper instance
     */
    public DbAdapter(Context ctx) {
        context = ctx;

        if (DBHelper == null) {
            DBHelper = new DataBaseHelper(context);
        }

    }

    /**
     * This is database helper class where all db table is created and
     * drop if there is any update
     */
    public static class DataBaseHelper extends SQLiteOpenHelper {

        private DataBaseHelper(Context mcontext) {
            super(context, DATABASE_NAME, null, DATABASE_VERSION);

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
                DB_PATH = context.getApplicationInfo().dataDir + "/databases/"+DATABASE_NAME;
            } else {
                DB_PATH = "/data/data/" + context.getPackageName() + "/databases/"+DATABASE_NAME;
            }
        }

        @Override
        public void onCreate(SQLiteDatabase db) {

            Log.e(TAG, "onCreate Database");

        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            try {

                Log.e(TAG, "Upgrading database from version " + oldVersion
                        + " to " + newVersion);

                // we want both updates, so no break statement here...
                switch (oldVersion) {
                    case 1:

                    case 2:
                }

            } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }

        // If database not exists copy it from the assets
        public void CopyAndCreateDataBase() throws IOException {

            boolean mDataBaseExist = checkDataBase();
            if (!mDataBaseExist) {
                this.getReadableDatabase();
                this.getWritableDatabase();
                this.close();
                try {
                    // Copy the database from assests
                    copyDataBase();

                    String mPath = DB_PATH + DATABASE_NAME ;

                    Log.v(TAG, "Database created :  " + mPath);

                } catch (IOException mIOException) {
                    throw new Error("ErrorCopyingDataBase");
                }
            }
        }


        // Check that the database exists here: /data/data/your package/databases/DatabaseName
        private boolean checkDataBase() {
            File dbFile = new File(DB_PATH + DATABASE_NAME);
            Log.e(Constants.TAG, dbFile + "   "+ dbFile.exists());
            return dbFile.exists();
        }

        // Copy the database from assets
        private void copyDataBase() throws IOException {
            InputStream mInput = context.getAssets().open(ASSETS_DATABASE_NAME);
            String outFileName = DB_PATH + DATABASE_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();
        }

        public static void copyDatabaseToSdCard() {
            try {
                File f1 = new File(DB_PATH);
                if (f1.exists()) {
                    File f2 = new File(Environment
                            .getExternalStorageDirectory().getAbsoluteFile()
                            + "/" + DATABASE_NAME);
                    f2.createNewFile();
                    InputStream in = new FileInputStream(f1);
                    OutputStream out = new FileOutputStream(f2);
                    byte[] buf = new byte[2048];
                    int len;
                    while ((len = in.read(buf)) > 0) {
                        out.write(buf, 0, len);
                    }
                    in.close();
                    out.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

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

        @Override
        public void onOpen(SQLiteDatabase db) {
            super.onOpen(db);

        }
    }

    // opens the database
    public synchronized SQLiteDatabase openDatabase() throws SQLException {

        if (mDb == null) {
            mDb = DBHelper.getWritableDatabase();

             Log.e(Constants.TAG, "Database opened");
        }

        return mDb;
    }

    // close the database
    public synchronized void closeDatabase() {

        // db.setTransactionSuccessful();
        // db.endTransaction();
         DBHelper.close();
    }

    public synchronized void exit() {
        try {
            if (DBHelper != null)
                DBHelper = null;

            if (mDb != null) {
                mDb.close();
                mDb = null;
            }
                Log.e(TAG, "dbhelper : " + DBHelper + " Db " + mDb);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
和呼唤

DbAdapter mAdapter = new DbAdapter(this);
如果您需要任何帮助,请参阅此

,您可以使用此代码,它正在我的应用程序中运行
导入java.io.File;
导入java.io.FileOutputStream;
导入java.io.IOException;
导入java.io.InputStream;
导入java.io.OutputStream;
导入java.util.ArrayList;
导入android.content.Context;
导入android.database.Cursor;
导入android.database.SQLException;
导入android.database.sqlite.SQLiteDatabase;
导入android.database.sqlite.SQLiteOpenHelper;
公共类SqlLiteDbHelper扩展了SQLiteOpenHelper{
私有静态最终int数据库_VERSION=1;
私有静态最终字符串数据库\u NAME=“mydb.sqlite”;
私有静态最终字符串DB_PATH_SUFFIX=“/databases/”;
静态上下文ctx;
公共SqlLiteDbHelper(上下文){
super(上下文、数据库名称、null、数据库版本);
ctx=上下文;
}
公共阵列列表getDetails(){
SQLiteDatabase db=this.getReadableDatabase();
ArrayList contList=新的ArrayList();
Cursor Cursor=db.rawQuery(“从演示中选择*”,null);
如果(光标!=null){
while(cursor.moveToNext()){
Contact cont=新联系人(cursor.getInt(0)、cursor.getString(1)、cursor.getString(2));
contList.add(cont);
}
cursor.close();
db.close();
}
返回控制列表;
}
public void CopyDataBaseFromAsset()引发IOException{
InputStream myInput=ctx.getAssets().open(数据库名称);
//刚创建的空数据库的路径
字符串outFileName=getDatabasePath();
//如果路径不存在,首先创建它
文件f=新文件(ctx.getApplicationInfo().dataDir+DB\u路径\u后缀);
如果(!f.exists())
f、 mkdir();
//打开空数据库作为输出流
OutputStream myOutput=新文件OutputStream(outFileName);
//将字节从输入文件传输到输出文件
字节[]缓冲区=新字节[1024];
整数长度;
而((长度=myInput.read(缓冲区))>0){
写入(缓冲区,0,长度);
}
//关闭溪流
myOutput.flush();
myOutput.close();
myInput.close();
}
私有静态字符串getDatabasePath(){
返回ctx.getApplicationInfo().dataDir+DB\u PATH\u后缀
+数据库名称;
}
公共SQLiteDatabase openDataBase()引发SQLException{
File dbFile=ctx.getDatabasePath(数据库名称);
如果(!dbFile.exists()){
试一试{
CopyDataBaseFromAsset();
System.out.println(“从资产文件夹复制成功”);
}捕获(IOE异常){
抛出新的RuntimeException(“创建源数据库时出错”,e);
}
}
返回SQLiteDatabase.openDatabase(dbFile.getPath(),null,SQLiteDatabase.NO_本地化的| SQLiteDatabase.CREATE_如果需要);
}
@凌驾
public void onCreate(SQLiteDatabase db){
}
@凌驾
public void onUpgrade(SQLiteDatabase db,int-oldVersion,int-newVersion){
}
}
有关更多详细信息,请访问此链接
http://androideve.com/2017/02/android-read-sqlite-databse-assets-folder/

getInstance(activityname.this)
@IntelliJAmiya谢谢你的回复,我尝试了你的建议,但它仍然在做同样的事情。@SnakeByte请参考我的帖子。没有代码将文件从资产文件夹复制到需要的地方。无论如何,只要使用。谢谢你的回复,我尝试了你的代码,但有些无法解决方法错误。这是.getReadableDatabase();这个.getWriteableDatabase();super.close();super.open();无法解决方法错误。
You can use this code, It is working in my app

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 android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class SqlLiteDbHelper extends SQLiteOpenHelper {

private static final int DATABASE_VERSION = 1;
 private static final String DATABASE_NAME = "mydb.sqlite";
 private static final String DB_PATH_SUFFIX = "/databases/";
 static Context ctx;
public SqlLiteDbHelper(Context context) {
 super(context, DATABASE_NAME, null, DATABASE_VERSION);
 ctx = context;
 }
public ArrayList<Contact> getDetails() {
 SQLiteDatabase db = this.getReadableDatabase();
 ArrayList<Contact> contList = new ArrayList<>();
 Cursor cursor = db.rawQuery("SELECT * FROM demo", null);
 if (cursor != null) {
 while (cursor.moveToNext()) {
Contact cont = new Contact(cursor.getInt(0), cursor.getString(1), cursor.getString(2));
 contList.add(cont);
}
 cursor.close();
 db.close();
 }
 return contList;
 }
public void CopyDataBaseFromAsset() throws IOException {
InputStream myInput = ctx.getAssets().open(DATABASE_NAME);
// Path to the just created empty db
 String outFileName = getDatabasePath();
// if the path doesn't exist first, create it
 File f = new File(ctx.getApplicationInfo().dataDir + DB_PATH_SUFFIX);
 if (!f.exists())
 f.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();

}
private static String getDatabasePath() {
 return ctx.getApplicationInfo().dataDir + DB_PATH_SUFFIX
 + DATABASE_NAME;
 }
public SQLiteDatabase openDataBase() throws SQLException {
 File dbFile = ctx.getDatabasePath(DATABASE_NAME);
if (!dbFile.exists()) {
 try {
 CopyDataBaseFromAsset();
 System.out.println("Copying sucess from Assets folder");
 } catch (IOException e) {
 throw new RuntimeException("Error creating source database", e);
 }
 }
return SQLiteDatabase.openDatabase(dbFile.getPath(), null, SQLiteDatabase.NO_LOCALIZED_COLLATORS | SQLiteDatabase.CREATE_IF_NECESSARY);
 }
@Override
 public void onCreate(SQLiteDatabase db) {
}
@Override
 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
 }
}

For more details visit this link
http://androideve.com/2017/02/android-read-sqlite-databse-assets-folder/