我如何读取我的Android应用程序中的数据库,我已经在我的电脑中修改并复制回我的应用程序的db文件夹

时间:2016-07-05 06:02:30

标签: android

我想要做的是我有一个我在我的应用程序中创建的数据库。我正在从我的手机复制相同的数据库(我的手机已植根,因此我很容易将其复制并粘贴到我的手机上)。在我的Mac上通过SQLite Manager我插入数据(这样做是因为我有需要将csv文件导入到db中)以后我将相同的db文件复制到我的app数据库文件夹中。

问题是每当我尝试插入或读取db文件时,我的应用程序都会崩溃。

这是我的清单档案:

    <?xml version="1.0" encoding="utf-8"?>

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.uttara.dbpull">
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

这是我的DBhelper课程。

    public class DHelper extends SQLiteOpenHelper {
    private static final String DATABASE_NAME = "sampledata1";
    private static final String TABLE_NAME="sampledata1";
    private static final int DATABASE_VERSION = 1;
    private static final String NUMBER="NUMBER";
    private static final String NAME = "NAME";
    private static final String SURNAME = "SURNAME";
    private static final String MARKS = "MARKS";
    private static final String SQL_CREATE_TABLE_SAMPLE = "CREATE TABLE     sampledata1 (NUMBER INTEGER PRIMARY KEY, NAME TEXT, SURNAME TEXT, MARKS INTEGER)";

    public DHelper(Context applicationcontext ) {
    super(applicationcontext, DATABASE_NAME, null, DATABASE_VERSION);
}

    @Override
    public void onCreate(SQLiteDatabase db) {
    db.execSQL(SQL_CREATE_TABLE_SAMPLE);

}

@Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    db.execSQL("DROP TABLE IF EXISTS sampledata1");
    onCreate(db);

}
    public boolean insertData(String name,String surname,String marks){
    SQLiteDatabase db=this.getWritableDatabase();
    ContentValues contentValues=new ContentValues();
    contentValues.put(NAME,name);
    contentValues.put(SURNAME,surname);
    contentValues.put(MARKS,marks);
    long result = db.insert(TABLE_NAME,null,contentValues);
    if (result == -1)
        return false;
    else
        return true;

}
    public Cursor getAllData(){
    SQLiteDatabase db=this.getWritableDatabase();
    Cursor res=db.rawQuery("SELECT * FROM " +TABLE_NAME,null);
    return res;
}
}

我的MainActivity.class

    public class MainActivity extends AppCompatActivity {
DHelper myDb;
EditText editname,editsurname,editmarks;
Button btnadd,btnview;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    myDb=new DHelper(this);
    editname= (EditText) findViewById(R.id.editText_name);
    editsurname= (EditText) findViewById(R.id.editText_surname);
    editmarks= (EditText) findViewById(R.id.editText_marks);
    btnadd= (Button) findViewById(R.id.button_add);
    btnview= (Button) findViewById(R.id.button_view);
    viewAll();
    addData();

}
public void addData(){
    btnadd.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
          boolean isInserted=  myDb.insertData(editname.getText().toString(),editsurname.getText().toString(),editmarks.getText().toString());
            if (isInserted==true)
                Toast.makeText(MainActivity.this,"Data inserted",Toast.LENGTH_SHORT).show();

            else
                Toast.makeText(MainActivity.this,"Data not inserted",Toast.LENGTH_SHORT).show();

        }
    });

}
public void viewAll(){
    btnview.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
           Cursor res= myDb.getAllData();
            if (res.getCount()==0){
                showMessage("Error","NO DATA FOUND");
                return;

            }

            StringBuffer buffer=new StringBuffer();
            while (res.moveToNext()){
                buffer.append("NUMBER :"+ res.getString(0)+"\n");
                buffer.append("NAME :"+ res.getString(1)+"\n");
                buffer.append("SURNAME :"+ res.getString(2)+"\n");
                buffer.append("MARKS :"+ res.getString(3)+"\n\n");

            }
            showMessage("Alert",buffer.toString());
        }
    });
}
public void showMessage(String title,String Message){
    AlertDialog.Builder builder=new AlertDialog.Builder(this);
    builder.setCancelable(true);
    builder.setTitle(title);
    builder.setMessage(Message);
    builder.show();
    }
}

logcat的:

E/SQLiteDatabase: Failed to open database '/data/user/0/com.uttara.dbpull/databases/sampledata1'.
android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:237)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:221)
at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:468)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:190)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:182)
at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:876)
at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:856)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:754)
at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:579)
at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:269)
at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:223)
at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:163)
at com.uttara.dbpull.DHelper.getAllData(DHelper.java:55)
at com.uttara.dbpull.MainActivity$2.onClick(MainActivity.java:50)
at android.view.View.performClick(View.java:5226)
at android.view.View$PerformClick.run(View.java:21266)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:168)
at android.app.ActivityThread.main(ActivityThread.java:5845)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:797)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:687)

    --------- beginning of crash
    07-05 11:29:06.732 16734-16734/com.uttara.dbpull E/AndroidRuntime:         FATAL EXCEPTION: main Process: com.uttara.dbpull, PID: 16734
android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:237)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:221)
at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:468)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:190)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:182)
at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:856)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:754)
at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:579)
at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:269)
at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:223)
at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:163)
at com.uttara.dbpull.DHelper.getAllData(DHelper.java:55)
at com.uttara.dbpull.MainActivity$2.onClick(MainActivity.java:50)
at android.view.View.performClick(View.java:5226)
at android.view.View$PerformClick.run(View.java:21266)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:168)
at android.app.ActivityThread.main(ActivityThread.java:5845)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:797)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:687)

1 个答案:

答案 0 :(得分:0)

首先,我将解释如何复制Android应用中的现有数据库架构以及处理SQLite DB的良好实践,以便它对其他人也有帮助。当您具有静态数据库模式时,这种方法很有用。

在Android应用程序中使用数据库对象的推荐方法是,在应用程序级别创建它并在整个应用程序中使用它。

public class MyApplication extends Application{
    public DBHelper dbHelper;
    @Override
    public void onCreate() {
        super.onCreate();
        dbHelper = new DBHelper(getApplicationContext());
            try {
                dbHelper.createDataBase();
            } catch (IOException e) {
                e.printStackTrace();
            }
    }
}

不要忘记在application标记的AndroidManifest文件中提及您的应用程序名称。假设您的应用程序类名称是MyApplication,它位于com.app包中,然后应该是: -

  

机器人:名称= “com.app.MyApplication”

下面是DBHelper类,它作为我们的应用程序和本地数据库之间的桥梁。

public class DBHelper extends SQLiteOpenHelper{
    public static final String DATABASE_NAME = "Your database name";
    public static final int DATABASE_VERSION = 1;
    private static String DB_PATH = "";
    private SQLiteDatabase mDataBase;
    private final Context mContext;

/**
     * Called when the database is created for the first time. This is where the
     * creation of tables and the initial population of the tables should happen.
     *
     * @param db The database.
     */
    @Override
    public void onCreate(SQLiteDatabase db) {

}

/**
 * Called when the database needs to be upgraded. The implementation
 * should use this method to drop tables, add tables, or do anything else it
 * needs to upgrade to the new schema version.
 * <p/>
 * <p>
 * The SQLite ALTER TABLE documentation can be found
 * <a href="http://sqlite.org/lang_altertable.html">here</a>. If you add new columns
 * you can use ALTER TABLE to insert them into a live table. If you rename or remove columns
 * you can use ALTER TABLE to rename the old table, then create the new table and then
 * populate the new table with the contents of the old table.
 * </p><p>
 * This method executes within a transaction.  If an exception is thrown, all changes
 * will automatically be rolled back.
 * </p>
 *
 * @param db         The database.
 * @param oldVersion The old database version.
 * @param newVersion The new database version.
 */
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

}

 /**
     * Create a helper object to create, open, and/or manage a database.
     * This method always returns very quickly.  The database is not actually
     * created or opened until one of {@link #getWritableDatabase} or
     * {@link #getReadableDatabase} is called.
     *
     * @param context to use to open or create the database
     */
    public DBHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
        if(android.os.Build.VERSION.SDK_INT >= 17){
            DB_PATH = context.getApplicationInfo().dataDir + "/databases/";
        }
        else
        {
            DB_PATH = "/data/data/" + context.getPackageName() + "/databases/";
        }
        this.mContext = context;
    }

/**
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
     */
    public boolean checkDataBase(){

    SQLiteDatabase checkDB = null;

    try{
        String myPath = DB_PATH + DATABASE_NAME;
        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;
}
/**
 * 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.getReadableDatabase();

        try {

            copyDataBase();

        } catch (IOException e) {

            throw new Error("Error copying database");

        }
    }

}
/**
 * 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 = mContext.getAssets().open(DATABASE_NAME+".sqlite");

    // Path to the just created empty db
    String outFileName = DB_PATH + DATABASE_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();

}

public void openDataBase() throws SQLException {
    //Open the database
    String myPath = DB_PATH + DATABASE_NAME;
    mDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);

}

@Override
public synchronized void close() {

    if(mDataBase != null)
        mDataBase.close();

    super.close();
}
}

现在这可能是解决您问题的方法。您只需要从您的活动中打开数据库,执行数据库操作,完成后再关闭它。以下是代码段: -

MyApplication application = (MyApplication) getApplicationContext();
application.dbHelper.openDataBase();
boolean isInserted=application.dbHelper.insertData(editname.getText().toString(),editsurname.getText().toString(),editmarks.getText().toString());
application.dbHelper.close();

我希望这会对你有所帮助。