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


    我们知道数据库创建的时候默认保存到系统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():

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

  • 相关阅读:
    Microsoft Azure 的负载平衡器的Session Sticky
    MySQL Performance tuning
    集装箱码头智能理货方案
    Iphone 英语语言下通讯录排序问题
    mac安装Aws cli失败
    vbs操作excel
    Sharepoint 2010 工作流启动时处理出错
    2、easyUI-创建 CRUD可编辑dataGrid(表格)
    1、easyUI-创建 CRUD普通dataGrid(表格)
    0327定时执行--存储过程--dbms_job--dbms_scheduler.create_job
  • 原文地址:https://www.cnblogs.com/tanlon/p/1924819.html
Copyright © 2020-2023  润新知