代码改变世界

创建数据库的时候就将数据库保存到SDcard中

  雪夜&流星  阅读(2102)  评论(0编辑  收藏  举报

我们知道数据库创建的时候默认保存到系统data/data/项目名 下面了,有没有一种方法保存到自己指定的SDCard上的文件夹里面呢?答案是可以的。我们只需要找到SQLiteOpenHelper这个类,了解一下就不难发现其保存的路径是固定了的,那么我们只需要改动一下getWritableDatabase(),即写入的时候的路径:
public synchronized SQLiteDatabase getWritableDatabase() {
        if (mDatabase != null && mDatabase.isOpen() && !mDatabase.isReadOnly()) {
            return mDatabase;  // The database is already open for business
        }

 

        if (mIsInitializing) {
            throw new IllegalStateException("getWritableDatabase called recursively");
        }

        // If we have a read-only database open, someone could be using it
        // (though they shouldn't), which would cause a lock to be held on
        // the file, and our attempts to open the database read-write would
        // fail waiting for the file lock.  To prevent that, we acquire the
        // lock on the read-only database, which shuts out other users.

        boolean success = false;
        SQLiteDatabase db = null;
        if (mDatabase != null) mDatabase.lock();
        try {
            mIsInitializing = true;
            if (mName == null) {
                db = SQLiteDatabase.create(null);
            } else {
                db = mContext.openOrCreateDatabase(mName, 0, mFactory);
            }

            int version = db.getVersion();
            if (version != mNewVersion) {
                db.beginTransaction();
                try {
                    if (version == 0) {
                        onCreate(db);
                    } else {
                        onUpgrade(db, version, mNewVersion);
                    }
                    db.setVersion(mNewVersion);
                    db.setTransactionSuccessful();
                } finally {
                    db.endTransaction();
                }
            }

            onOpen(db);
            success = true;
            return db;
        } finally {
            mIsInitializing = false;
            if (success) {
                if (mDatabase != null) {
                    try { mDatabase.close(); } catch (Exception e) { }
                    mDatabase.unlock();
                }
                mDatabase = db;
            } else {
                if (mDatabase != null) mDatabase.unlock();
                if (db != null) db.close();
            }
        }
    }

注意标志的红色的部分,这是创建数据库的地方,我们再看看openOrCreateDatabase()

这个方法,openOrCreateDatabase()这个方法存在于package android.content;下面的public abstract class Context{}类里面,
public abstract SQLiteDatabase openOrCreateDatabase(String name,int mode, CursorFactory factory);
我们发现在package android.database.sqlite;包下的public class SQLiteDatabase extends SQLiteClosable {}里面也有一个
public static SQLiteDatabase openOrCreateDatabase(String path, CursorFactory factory) {
        return openDatabase(path, factory, CREATE_IF_NECESSARY);
    }
相同的方法,只是参数不同,这个可以传一个路径进去,我们就调用这个方法。
  然后我们还要有一个我们指定文件夹的路径的方法:
public File getDatabasePath(String name) {
      String EXTERN_PATH = null;
       //判断是否有SDcard
        if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)==true)
        {
           //判断是否存在指定的文件夹,如果没有就创建它
            EXTERN_PATH = android.os.Environment.getExternalStorageDirectory().getAbsolutePath()
            + "/database/";
            File f=new File(EXTERN_PATH);
            if(!f.exists())
            {
              f.mkdirs();
            }
        }
        return new File(EXTERN_PATH+ name);
    }
及对SDcard进行写和读的权限:
<!-- 在SDCard中创建于删除文件权限 -->  
     <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />  
     <!-- 往SDCard写入数据权限 -->  
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

最后当我们创建数据库的时候直接继承我们自己定义的SDSQLiteOpenHelper(),不用系统自带SQLiteOpenHelper()即可。

参考我在eoeAndroid中文章:http://www.eoeandroid.com/thread-53985-1-1.html

自已定义的SDSQLiteOpenHelper():

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
public abstract class SDSQLiteOpenHelper {
    private static final String TAG = SDSQLiteOpenHelper.class.getSimpleName();
 
    @SuppressWarnings("unused")
    private final Context mContext;
    private final String mName;
    private final CursorFactory mFactory;
    private final int mNewVersion;
 
    private SQLiteDatabase mDatabase = null;
    private boolean mIsInitializing = false;
 
    /**
     * Create a helper object to create, open, and/or manage a database. 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
     * @param name
     *            of the database file, or null for an in-memory database
     * @param factory
     *            to use for creating cursor objects, or null for the default
     * @param version
     *            number of the database (starting at 1); if the database is
     *            older, {@link #onUpgrade} will be used to upgrade the database
     */
    public SDSQLiteOpenHelper(Context context, String name,
            CursorFactory factory, int version) {
        if (version < 1)
            throw new IllegalArgumentException("Version must be >= 1, was "
                    + version);
 
        mContext = context;
        mName = name;
        mFactory = factory;
        mNewVersion = version;
    }
 
    /**
     * Create and/or open a database that will be used for reading and writing.
     * Once opened successfully, the database is cached, so you can call this
     * method every time you need to write to the database. Make sure to call
     * {@link #close} when you no longer need it.
     *
     * <p>
     * Errors such as bad permissions or a full disk may cause this operation to
     * fail, but future attempts may succeed if the problem is fixed.
     * </p>
     *
     * @throws SQLiteException
     *             if the database cannot be opened for writing
     * @return a read/write database object valid until {@link #close} is called
     */
    public synchronized SQLiteDatabase getWritableDatabase() {
        if (mDatabase != null && mDatabase.isOpen() && !mDatabase.isReadOnly()) {
            return mDatabase; // The database is already open for business
 
        }
 
        if (mIsInitializing) {
            throw new IllegalStateException(
                    "getWritableDatabase called recursively");
        }
 
        // If we have a read-only database open, someone could be using it
 
        // (though they shouldn't), which would cause a lock to be held on
 
        // the file, and our attempts to open the database read-write would
 
        // fail waiting for the file lock. To prevent that, we acquire the
 
        // lock on the read-only database, which shuts out other users.
 
        boolean success = false;
        SQLiteDatabase db = null;
        try {
            mIsInitializing = true;
            if (mName == null) {
                db = SQLiteDatabase.create(null);
            } else {
                String path = getDatabasePath(mName).getPath();
                db = SQLiteDatabase.openOrCreateDatabase(path, mFactory);
            }
 
            int version = db.getVersion();
            if (version != mNewVersion) {
                db.beginTransaction();
                try {
                    if (version == 0) {
                        onCreate(db);
                    } else {
                        onUpgrade(db, version, mNewVersion);
                    }
                    db.setVersion(mNewVersion);
                    db.setTransactionSuccessful();
                } finally {
                    db.endTransaction();
                }
            }
 
            onOpen(db);
            success = true;
            return db;
        } finally {
            mIsInitializing = false;
            if (success) {
                if (mDatabase != null) {
                    try {
                        mDatabase.close();
                    } catch (Exception e) {
                    }
                }
                mDatabase = db;
            } else {
                if (db != null)
                    db.close();
            }
        }
    }
 
    /**
     * Create and/or open a database. This will be the same object returned by
     * {@link #getWritableDatabase} unless some problem, such as a full disk,
     * requires the database to be opened read-only. In that case, a read-only
     * database object will be returned. If the problem is fixed, a future call
     * to {@link #getWritableDatabase} may succeed, in which case the read-only
     * database object will be closed and the read/write object will be returned
     * in the future.
     *
     * @throws SQLiteException
     *             if the database cannot be opened
     * @return a database object valid until {@link #getWritableDatabase} or
     *         {@link #close} is called.
     */
    public synchronized SQLiteDatabase getReadableDatabase() {
        if (mDatabase != null && mDatabase.isOpen()) {
            return mDatabase; // The database is already open for business
 
        }
 
        if (mIsInitializing) {
            throw new IllegalStateException(
                    "getReadableDatabase called recursively");
        }
 
        try {
            return getWritableDatabase();
        } catch (SQLiteException e) {
            if (mName == null)
                throw e; // Can't open a temp database read-only!
 
            Log.e(TAG, "Couldn't open " + mName
                    + " for writing (will try read-only):", e);
        }
 
        SQLiteDatabase db = null;
        try {
            mIsInitializing = true;
            String path = getDatabasePath(mName).getPath();
            db = SQLiteDatabase.openDatabase(path, mFactory,
                    SQLiteDatabase.OPEN_READWRITE);
            if (db.getVersion() != mNewVersion) {
                throw new SQLiteException(
                        "Can't upgrade read-only database from version "
                                + db.getVersion() + " to " + mNewVersion + ": "
                                + path);
            }
 
            onOpen(db);
            Log.w(TAG, "Opened " + mName + " in read-only mode");
            mDatabase = db;
            return mDatabase;
        } finally {
            mIsInitializing = false;
            if (db != null && db != mDatabase)
                db.close();
        }
    }
 
    /**
     * Close any open database object.
     */
    public synchronized void close() {
        if (mIsInitializing)
            throw new IllegalStateException("Closed during initialization");
 
        if (mDatabase != null && mDatabase.isOpen()) {
            mDatabase.close();
            mDatabase = null;
        }
    }
 
    public File getDatabasePath(String name) {
        String EXTERN_PATH = null;
        if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)==true)
        {
            EXTERN_PATH = android.os.Environment.getExternalStorageDirectory().getAbsolutePath()
            + "/db/";
            File f=new File(EXTERN_PATH);
            if(!f.exists())
            {
              f.mkdirs();
            }
        }
        return new File(EXTERN_PATH+ name);
    }
 
    /**
     * 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.
     */
    public abstract 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>
     * 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.
     *
     * @param db
     *            The database.
     * @param oldVersion
     *            The old database version.
     * @param newVersion
     *            The new database version.
     */
    public abstract void onUpgrade(SQLiteDatabase db, int oldVersion,
            int newVersion);
 
    /**
     * Called when the database has been opened. Override method should check
     * {@link SQLiteDatabase#isReadOnly} before updating the database.
     *
     * @param db
     *            The database.
     */
    public void onOpen(SQLiteDatabase db) {
    }
}

编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
点击右上角即可分享
微信分享提示