I'm looking to create a sqlite database on the sd card (don't want to use up the user's internal storage). I'm familiar with the OpenHelper pattern:
public DatabaseFoo(Context context) {
OpenHelper openHelper = new OpenHelper(context);
mDb = openHelper.getWritableDatabase();
}
private static class OpenHelper extends SQLiteOpenHelper {
public OpenHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
...
so if we want to create on the sd card, I think instead we have to use:
public static SQLiteDatabase openOrCreateDatabase (String path,
SQLiteDatabase.CursorFactory factory);
But what is the "factory" argument supposed to be, what factory should be used?
Also a bit worried about what happens if the user removes the SD card while my app is in use..
Thanks
I haven't tried to do what you describe there, but presumably it could be done and might work -- with a few caveats. First, the external storage (SD card) is not secure, so any other application, or the user, could read/write to it. Second, as you noted, when it's unmounted the DB goes away.
Because of these disadvantages, you would probably be better off to try to use an internal storage database (the default), that is small and possibly includes pointers to external data (like images or files) -- that themselves can be on the external storage (and that have placeholders, or other handling, when the external storage is not available).
Still, if you want to try it, you might be better off override the getDatabasePath method of Context, such as with your own Application object, and then pass that into a regular SQLiteOpenHelper. Then you wouldn't have to worry about the cursor factory (which is optional, as the source confirms -- so just pass null if instead you want to go that route).
Do this in your SQLiteOpenHelper constructor:
DatabaseHelper(Context context) {
super(context, context.getExternalFilesDir(null).getAbsolutePath() + "/" + DATABASE_NAME, null, DATABASE_VERSION);
}
It will create the database in the app's folder on the sdcard: /sdcard/Android/data/[your_package_name]/files.
In that way the database will be seen as part of the app by android and removed automatically if the user uninstalls the app.
I my app I have a large database and it will in most cases not fit on old phones internal memory, e.g. HTC Desire. It runs great on the sdcard, and most apps are "moved to sdcard" themselves anyway so don't worry about the database not being accessible, because the app won't be accessible it self.
Cursor factory is used to return an instance of your custom Cursor implementation.
Generally you just use SQLiteCursor, in which case null is passed as factory argument.
Then make your own flat database - most people have very little internal memory, and its annoying that they eat it up with huge database.
And as for the 'what if they remove the SD' scenario - if the user removes the card obviously its not going to work! Clearly. Just check you didn't get an error when trying to interact with the base, and if you did, just tell you user - problem solved.
public DataBaseHelper(final Context context) {
super(context, Environment.getExternalStorageDirectory()
+ File.separator+ MYDATABASE_NAME, null, MYDATABASE_VERSION);
}
Also Add permission in android Manifest
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
I would recommend against putting a database onto an SD card - you will significantly decrease the lifespan of the card, since it has a (large, but still existent) limit on the number of writes possible and databases require quite a few writes.
Related
I am trying to use SQLiteAssetHelper and it requires me to create database on PC and copy it to assets/databases/databasename.db. I do that, but when I check on the device, nor the database, nor the databases folder is there under my app's data folder.
I did this based on a video, and the guy there doesn't do anything else to make the copy work.
So, are the files supposed to be automatically copied over to device?
If not, how can I copy the files?
So, are the files supposed to be automatically copied over to device? If not, how can I copy the files?
Yes it will BUT only when an attempt is made to access the database. Just instantiating the class that extends SQLiteAssetHelper will not copy the database and thus if that is all you do then the database will not be visible.
The steps when using SQliteAssetHelper to take should be :-
Create your project.
Amend the build.gradle to include implementation 'com.readystatesoftware.sqliteasset:sqliteassethelper:+' in the dependencies section.
Create the assets folder and then the databases folder in the assets folder and
Copy the database file into the databases folder.
Create the Database Helper class that extends SQliteAssetHelper.
Instantiate the Database Helper
Access the database (this is when the database is copied).
If when doing step 5 you use, as an example (based upon the information in the question) :-
public class DatabaseHelper extends SQLiteAssetHelper {
public static final String DATABASENAME = "databasename.db"; //<<<<<<<<< MUST match file name in assets/databases
public static final int DATABASEVERSION = 1;
public DatabaseHelper(Context context) {
super(context, DATABASENAME, null, DATABASEVERSION);
this.getWritableDatabase(); //<<<<< will force database access and thus copy database from assets
}
}
Then when doing 6 (instantiating the database helper), then 7 is done because this.getWritableDatabase(); accesses (implicitly opens) the database.
e.g.
public class MainActivity extends AppCompatActivity {
DatabaseHelper mDBHelper; //<<<<< declares the database helper
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDBHelper = new DatabaseHelper(this); // instantiates the database helper
}
}
The procedure you're explaining requires root access to the app storage on the device which is impossible on a normal non-rooted device due to security considerations. For this, you need a rooted device OR you could use emulator in Android Studio, that's much easier and user friendly approach:
Open emulator from Android Studio -> Settings -> Memory -> Internal Storage -> Others
A pop-up window will open. Click explore. You will get access to your app's internal storage so you can manage the database folder as well.
P.S.: Also, you might just package your app with the database table you have, just as with any other file, simply place it under your src/main/assets folder and access from code in runtime. Code samples are available in this thread : Android - Copy assets to internal storage (suggested by #Ezaldeen sahb)
Can anyone can create a database from SD card using Jellybean API 18?
but i should call this path like /storage/sdcard1. there are some many tutorials but does not work. Actually im using SQLiteOpenHelper.Some people says that if you create database from SD card, you dont need SQLiteOpenHelper.
Solution: You just have to modify the constructor in order to change it's path:
public class MySQLiteOpenHelper extends SQLiteOpenHelper {
MySQLiteOpenHelper(Context context) {
super(context, "/mnt/sdcard/mydb.db", null, 0);
}
}
You can also get the folder string path and change it accordingly as you require. Ex: "/storage/emulated/0/folder/mydb.db"
Don't forget to add Write and Read Storage Permissions.
Try it, Hope it's helpful.
We are tying to use Secondary EXTERNAL storage on the emulator and this works great. The user can select external or internal storage. Android build 26.0.2
YES manifest has permissions. When this line of code is included in the launcher Activity the storage is defaulted to INTERNAL helper = new DBHelper(this);
helper is declared static. The big benefit of using that line of code is that when the app is stopped or when we close the app with Clear All in the emulator the bound data in the ArrayList that is backed by a RecyclerAdapter persists. So not using the helper declaration except when needed in the Activity creates the need to reload data from the database and populate the ArrayList. This is where we have become lost. We have tried to call the method in the DBhelper that loads the ArrayList. To no avail code below is in the ListActivity. The app always returns to the MainActivity after being closed. So the question is where and how do I place the code to repopulate the ArrayList from the database ?
}// End of onCreate Bundle
#Override
protected void onResume() {
super.onResume();
helper = new DBHelper(this);
dbList = new ArrayList<>();
dbList = helper.getDataFromDB();
}
I tried to test this and discovered that you do not need the line of code
helper = new DBHelper(this); The issue is somewhere in your MainActivity your code is making a trip over to the DBHelper BEFORE the variable THE_PATH is set where ever you are defining that variable. In my testing I found you need to establish the contents of the variable THE_PATH that is being passed to DBHelper before that trip is made. While testing I changed the config.ini to excluded the SD CARD from the emulator and Android would just use internal storage.
So as of now my testing still did not permit the user to select storage type.
If the DB is beyond the storage capacity of internal memory than just set the default to EXTERNAL storage. As you know the data is not real secure on the SD CARD
quick background - I have no real programming knowledge so think complete beginner!
I used the below guide to load a database from the assets folder and it worked fine
http://www.javahelps.com/2015/04/import-and-use-external-database-in.html.
I now want to adjust this slightly so it loads a different SQLite database which I have created using DB Browser for SQLite but it is throwing the following error:
Missing databases/Exercisesthree.db file (or .zip, .gz archive) in assets, or target folder not writable
I have placed the new database (Excercisesthree.db.zip) in the same assets folder as the database that works (I have also left the unzipped file there too (Excercisesthree.db).
I altered the DatabaseOpenHelper class to open the Excercisesthree.db instead of the other db (code below) but for some reason it doesnt work. I suspect its something to do with the format of the database as I've hardly changed the code
package com.example.mat.externaldatabasedemo;
/**
* Created by Mat on 24-Jan-17.
*/
// http://www.javahelps.com/2015/04/import-and-use-external-database-in.html
import android.content.Context;
import com.readystatesoftware.sqliteasset.SQLiteAssetHelper;
public class DatabaseOpenHelper extends SQLiteAssetHelper {
private static final String DATABASE_NAME = "Exercisesthree.db";
private static final int DATABASE_VERSION = 1;
public DatabaseOpenHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
}
Here's a link to the database file:
https://1drv.ms/u/s!AupGvbDoJdp9i26l9oO5CcCGf2I0
This is the location of the database files:
C:\Users\Mat\AndroidStudioProjects\ExternalDatabaseDemo\app\src\main\assets\databases
Ok I've sorted it and confirm it was nothing to do with the Database format. In the end I created a new project and followed the original guide but changed it to the new database.
I think what must of happened is I'd changed some part of the code somewhere along the way and it stopped working. When testing it however it appeared to be working because the original databse had already been loaded onto the emulator and so it masked the fact that the database was no longer loading from the assets folder.
I would have like to have found out exactly what part of the code was missing and stopping it to work to understand a little more and report back but dont think I'll have time
In my application, I'm using a database to store some data, but if I close my app, my database will be deleted too. So I want to know if there is any mean to save my database and re-use it for the next launch of my app.
I use for the moment
public DatabaseHandler(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
in order to create my database.
Thanks for your help
If you are creating database using SQLiteOpenHelper it won't be deleted unless you do it purposely. They are used for persistent memory storage, therefore Android framework doesn't delete it itself unless user clears app data and cache from Application Settings.
To create a database in your Android application you usually subclass SQLiteOpenHelper. In the constructor of your subclass you call the super() method of SQLiteOpenHelper, specifying the database name and the current database version.
In this class you need to override the onCreate() method.
Refer: http://www.vogella.de/articles/AndroidSQLite/article.html#sqliteoverview
use sqliteopenhelper
check this link http://thenewboston.org/list.php?cat=6
It contains tutorials with code included which you can easily understand for the purpose you want to accomplish