现有SQLite数据库的完整Android数据库助手类是什么?

14

我正在尝试部署一个带有现有SQLite数据库的应用程序。

我已经阅读并尝试了几个在线示例,但发现它们总是缺少一些代码,要么无法编译,要么不能像广告中所说的那样工作。

有没有完整的Android数据库助手类,可以在Android上部署现有的SQLite数据库?


我尝试使用你的代码,但它在这一部分卡住了: ActivityManager: Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.mdegges/.MicheleActivity. 数据/data/com.mdegges/database文件从未被创建。 - mdegges
@mdegges,我不确定那里出了什么问题。从你的其他问题来看,似乎你也卡在了LAUNCHER部分。在包含db代码之前,你能否执行一个hello world测试? - Biff MaGriff
是的,我已经能够在开发网站上完成了很多教程(包括hello world)。很奇怪的是,我尝试过的所有指南都没有起作用。数据库在我的资产文件夹中,我将DB_PATH更改为正确的输出文件夹,并将数据库名称更改为我的数据库(带或不带扩展名),但没有运气! - mdegges
我已经成功让它运行了。 :) - mdegges
这基本上是在要求“为SQLLite给我一个数据库帮助类”,并符合“过于宽泛”的定义。我没有投反对票,而是关闭了问题。根据关闭结果,NARQ下关闭的问题会自动获得-1票。答案很好,但问题本身很糟糕,需要大量工作。自问自答是可以的(甚至是受到鼓励的),但这使您负担更重,既要提供优质的答案还要提供高质量的问题。 - casperOne
2个回答

27

这是我想到的,希望能帮助其他遇到问题的人。

package com.MyPackage;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;

import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

public class AnyDBAdapter {

    private static final String TAG = "AnyDBAdapter";
    private DatabaseHelper mDbHelper;
    private static SQLiteDatabase mDb;

    //make sure this matches the 
    //package com.MyPackage;
    //at the top of this file
    private static String DB_PATH = "/data/data/com.MyPackage/databases/";

    //make sure this matches your database name in your assets folder
    // my database file does not have an extension on it 
    // if yours does
    // add the extention
    private static final String DATABASE_NAME = "data";

    //Im using an sqlite3 database, I have no clue if this makes a difference or not
    private static final int DATABASE_VERSION = 3;

    private final Context adapterContext;

    public AnyDBAdapter(Context context) {
        this.adapterContext = context;
    }

    public AnyDBAdapter open() throws SQLException {
        mDbHelper = new DatabaseHelper(adapterContext);

        try {
            mDbHelper.createDataBase();
        } catch (IOException ioe) {
            throw new Error("Unable to create database");
        }

        try {
            mDbHelper.openDataBase();
        } catch (SQLException sqle) {
            throw sqle;
        }
        return this;
    }
    //Usage from outside
    // AnyDBAdapter dba = new AnyDBAdapter(contextObject); //in my case contextObject is a Map
    // dba.open();
    // Cursor c = dba.ExampleSelect("Rawr!");
    // contextObject.startManagingCursor(c);
    // String s1 = "", s2 = "";
    // if(c.moveToFirst())
    // do {
    //  s1 = c.getString(0);
    //  s2 = c.getString(1);
    //  } while (c.moveToNext());
    // dba.close();
    public Cursor ExampleSelect(string myVariable)
    {
        String query = "SELECT locale, ? FROM android_metadata";
        return mDb.rawQuery(query, new String[]{myVariable});
    }

    //Usage
    // AnyDBAdatper dba = new AnyDBAdapter(contextObjecT);
    // dba.open();
    // dba.ExampleCommand("en-CA", "en-GB");
    // dba.close();
    public void ExampleCommand(String myVariable1, String myVariable2)
    {
        String command = "INSERT INTO android_metadata (locale) SELECT ? UNION ALL SELECT ?";
        mDb.execSQL(command, new String[]{ myVariable1, myVariable2});
    }

    public void close() {
        mDbHelper.close();
    }

    private static class DatabaseHelper extends SQLiteOpenHelper {

        Context helperContext;

        DatabaseHelper(Context context) {
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
            helperContext = context;
        }

        @Override
        public void onCreate(SQLiteDatabase db) {
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            Log.w(TAG, "Upgrading database!!!!!");
            //db.execSQL("");
            onCreate(db);
        }

        public void createDataBase() throws IOException {
            boolean dbExist = checkDataBase();
            if (dbExist) {
            } else {

                //make sure your database has this table already created in it
                //this does not actually work here
                /*
                 * db.execSQL("CREATE TABLE IF NOT EXISTS \"android_metadata\" (\"locale\" TEXT DEFAULT 'en_US')"
                 * );
                 * db.execSQL("INSERT INTO \"android_metadata\" VALUES ('en_US')"
                 * );
                 */
                this.getReadableDatabase();
                try {
                    copyDataBase();
                } catch (IOException e) {
                    throw new Error("Error copying database");
                }
            }
        }

        public SQLiteDatabase getDatabase() {
            String myPath = DB_PATH + DATABASE_NAME;
            return SQLiteDatabase.openDatabase(myPath, null,
                    SQLiteDatabase.OPEN_READONLY);
        }

        private boolean checkDataBase() {
            SQLiteDatabase checkDB = null;
            try {
                String myPath = DB_PATH + DATABASE_NAME;
                checkDB = SQLiteDatabase.openDatabase(myPath, null,
                        SQLiteDatabase.OPEN_READONLY);
            } catch (SQLiteException e) {
            }
            if (checkDB != null) {
                checkDB.close();
            }
            return checkDB != null ? true : false;
        }

        private void copyDataBase() throws IOException {

            // Open your local db as the input stream
            InputStream myInput = helperContext.getAssets().open(DATABASE_NAME);

            // 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;
            mDb = SQLiteDatabase.openDatabase(myPath, null,
                    SQLiteDatabase.OPEN_READWRITE);
        }

        @Override
        public synchronized void close() {

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

            super.close();

        }
    }

}

1
你的类是否能打开存储在SD卡上的数据库? - Thiago
看起来是我的笔误。我已经将代码更正为helperContext。发现得好 :) - Biff MaGriff
我相信这是对你的活动的引用。我像这样使用它 public class MyClass extends MapActivity { public void doDBStuff() { new AnyDBAdapter(this).doDBThing(); } } - Biff MaGriff
2
数据库版本“DATABASE_VERSION”是您开发的数据库的当前版本。如果您在应用程序的第一个版本上工作,则数据库应该有V1,如果您更新应用程序到第2个版本并更新数据库,那么数据库版本应该有v2等。这个标志用于跟踪数据库更新,如果Android检测到数据库版本已增加,它会调用onUpdate()方法,该方法可以让您备份已存储在用户手机上的当前数据库,以便它不会被删除并替换为新的... - Cata
调用 AnyDBAdapter.close()SQLiteDatabase.close() 有什么区别? - aandis
显示剩余3条评论

5
DatabaseHelper dbHelper = new DatabaseHelper(getApplicationContext());

请确保在应用程序生命周期内仅创建一次DatabaseHelper对象并重复使用。

读取数据时:

SQLiteDatabase db = dbHelper.getReadableDatabase();

读取/修改数据:

SQLiteDatabase db = dbHelper.getWritableDatabase();

下一步使用SQLiteDatabase对象的insert()、query()、update()和delete()方法。请参考以下链接:http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html。在onCreate(...)方法中,不要直接访问sqlite文件来创建数据库。请使用SQLiteDatabase对象的execSQL()方法,在该方法中执行CREATE TABLE查询语句。

嗨radek-k,你能否详细说明一下你的第一个观点吗? 确保在应用程序生命周期内只创建一次DatabaseHelper对象并重复使用它。 - Biff MaGriff
1
如果您多次创建DatabaseHelper对象,请确保先关闭数据库 - getWritableDatabase.close()。在多线程应用程序模型中,当您没有关闭之前的DatabaseHelper时,您不能重新创建它。否则,您将会遇到一些异常。最好的方法是仅创建一次DatabaseHelper对象(例如在Application中),并始终使用相同的对象引用。 - plugmind
1
我不建议使用 getApplicationContext()。相反,使用这个,因为响应 getApplicationContext() 的任何内容都是一个 Context - CommonsWare
你可以在ActivityApplication内使用this。Commonsware和我都是正确的。只需查看api文档并传递任何扩展android.content.Context的内容。http://developer.android.com/reference/android/database/sqlite/SQLiteOpenHelper.html#SQLiteOpenHelper%28android.content.Context,%20java.lang.String,%20android.database.sqlite.SQLiteDatabase.CursorFactory,%20int%29 - plugmind

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接