Android saves the database to an SD card implementation

Source: Internet
Author: User

?? Sometimes the database is saved to an external storage or SD card for your needs (this can be done by encrypting data to prevent data from being cracked), such as an application that supports multiple data, every data needs a corresponding database, and the amount of information in the database is particularly large. This should obviously save the database in an external storage or SD card because the size of the RAM is limited, and secondly, it is easier to view the contents of the database by saving the database on the SD card when writing certain test programs.

?? By default when Android creates a database from Sqliteopenhelper, the database is saved in the '/data/data/Application name/databases ' directory, It is only necessary to pass in the database name in the constructor that inherits the Sqliteopenhelper class, but if you save the database under the specified path, you need to override the context in the constructor of the Sqliteopenhelper class by overriding the Because: in reading the source code of Sqliteopenhelper.java will find: the creation of the database is through the context of the Openorcreatedatabase method, if we need to create a database under the specified path, we need to write a class to inherit the context, and to replicate its ope Norcreatedatabase method, specify the path to the database store in the Openorcreatedatabase method, The following is the source code for Getwritabledatabase and Getreadabledatabase methods in class Sqliteopenhelper, and Sqliteopenhelper is to create the database by these two methods.

/** * Create and/or open a database that would be is used for reading and writing.  * The first time this is called, the database would be opened and * {@link #onCreate}, {@link #onUpgrade} and/or {@link     #onOpen} 'll be * called. * * * * <p>once opened successfully, the database is cached, so can * call this method every time you need t     o Write to the database.     * (make sure to call {@link #close} when longer need the database.) * Errors such as bad permissions or a full disk could cause this method * to fail, but the future attempts may succeed if th  E problem is fixed.</p> * * <p class= "Caution" >database upgrade could take a long time, you * should The "not" method from the application main thread, including * from {@link Android.content.contentprovider#oncrea     Te contentprovider.oncreate ()}. * * @throws Sqliteexception If the database cannot is opened for writing * @return a read/write database object va LID until {@link #close} is called */public synchronized Sqlitedatabase getwritabledatabase () {if (Mdatabas E! = null) {if (!mdatabase.isopen ()) {//darn! the user closed the database by calling Mdataba            Se.close () mdatabase = null;  } else if (!mdatabase.isreadonly ()) {return mdatabase; The database is already open for business}} if (misinitializing) {throw new Ille        Galstateexception ("Getwritabledatabase called recursively");  }//If We have a read-only database open, someone could is using it//(though they shouldn ' t), which would Cause a lock to being held on//the file, and we attempts to open the database read-write would//fail wait  ing for the file lock.        To prevent this, we acquire the//lock on the Read-only database, and which shuts out of 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, Merrorhandler);            } int version = Db.getversion ();                if (version! = mnewversion) {db.begintransaction ();                    try {if (Version = = 0) {onCreate (db); } else {if (Version > Mnewversion) {ondowngrade (db, Version, Mnewve                        Rsion);                        } 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 ();  }}}/** * Create and/or open a database.     This would be is the same object returned by * {@link #getWritableDatabase} unless some problem, such as a full disk,  * requires the database to be opened read-only.  In this case, a read-only * database object would be returned.     If the problem is fixed, a future call * to {@link #getWritableDatabase} may succeed, in which case the read-only     * Database object would be closed and the Read/write object is returned * in the future.* * <p class= "Caution" >like {@link #getWritableDatabase}, this method is * Take a long time to return, so Y OU should not call it from the * application main thread, including from * {@link android.content.contentprovider#     OnCreate contentprovider.oncreate ()}. * * @throws Sqliteexception If the database cannot be opened * @return a database object valid until {@link #getWr     Itabledatabase} * or {@link #close} is called. */Public synchronized Sqlitedatabase getreadabledatabase () {if (mdatabase! = null) {if (!mdatabase . IsOpen ()) {//darn! the user closed the database by calling Mdatabase.close () Mdatabase =            Null  } else {return mdatabase; The database is already open for business}} if (misinitializing) {throw new Ille        Galstateexception ("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 (would try Read-only):", e);        } sqlitedatabase db = null;            try {misinitializing = true;            String path = Mcontext.getdatabasepath (Mname). GetPath ();            db = Sqlitedatabase.opendatabase (path, mfactory, sqlitedatabase.open_readonly, Merrorhandler); 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 (); }    }


?? The above analysis can be used to write a custom context class that inherits the context, but it is recommended to use non-abstract classes because there are abstract functions other than the Openorcreatedatabase method in the context Contextwrapper , this class inherits from the context, the custom Databasecontext class source code is as follows:

public class Databasecontext extends Contextwrapper {public Databasecontext (context context) {super (context); /** * Gets the database path, if it does not exist, creates the object object * @param name * @param mode * @param factory */@Over Ride public File Getdatabasepath (String name) {//To determine if there is an SD card boolean sdexist = Android.os.Environment.MEDI        A_mounted.equals (Android.os.Environment.getExternalStorageState ());        if (!sdexist) {//If not present, return null;            }else{//if present//Get SD card path String dbdir= Fileutils.getflashbpath (); Dbdir + = "DB";//Database directory String DbPath = dbdir+ "/" +name;//database path//Determine if directory exists, does not exist create the directory File            Dirfile = new File (dbdir);            if (!dirfile.exists ()) {dirfile.mkdirs ();             }//Database file is created successfully boolean isfilecreatesuccess = false;            Determines whether the file exists, does not exist, and creates the file DBFile = new files (dbPath); if (!dbfile.exists ()){try {isfilecreatesuccess = Dbfile.createnewfile ();//Create File                } catch (IOException e) {e.printstacktrace ();            }}else{isfilecreatesuccess = true;            }//Returns the database file object if (isfilecreatesuccess) {return dbfile;            }else{return null;     }}}/** * Overloads this method, which is used to open the database on the SD card, Android 2.3 and the following will call this method. * * @param name * @param mode * @param factory */@Override public sqlitedatabase OPENORCR Eatedatabase (String name, int mode, Sqlitedatabase.cursorfactory Factory) {sqlitedatabase result = Sqlitedatabase.        Openorcreatedatabase (Getdatabasepath (name), NULL);    return result;     /** * Android 4.0 calls this method to get the database. * * @see android.content.contextwrapper#openorcreatedatabase (java.lang.String, int, * android.datab Ase.sQlite.    Sqlitedatabase.cursorfactory, * android.database.DatabaseErrorHandler) * @param name * @param Mode * @param factory * @param errorhandler * * @Override public sqlitedatabase Openorcreatedat Abase (String name, int mode, Cursorfactory factory, Databaseerrorhandler ErrorHandler) {sqlitedatabase result = SQ        Litedatabase.openorcreatedatabase (Getdatabasepath (name), NULL);    return result; }}


?? In the constructor of the subclass inheriting Sqliteopenhelper, replace the context with an instance of Databasecontext:

Databasecontext dbContext = new Databasecontext (context); Super (DbContext, mdatabasename, NULL, VERSION);

Description: This article is a great reference to other articles on the web, thanks in particular to the authors of these articles.

Resources:

    • Use Sqliteopenhelper to manage databases in an SD card in Android

Android saves the database to an SD card implementation

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.