I am working on Android application and want to ask if it might be possible for a SQLiteDatabase object, which is the object used to interact with the underlying SQLite db, to be Open (as in returns TRUE on db.isOpen()), but still not be readable?
What scenarios are possible? Locking?
Example:
SQLiteAppHelper sqliteHelper = SQLiteAppHelper.getInstance(context);
SQLiteDatabase appDB = sqliteHelper.getReadableDatabase();
Note: The code above is using a class that extends SQLiteOpenHelper.
Related
I need to be able to perform a some operations that would be easily done with SQLiteDatabase but I'm using Room. Is there a way for me to get an instance of a SQLiteDatabase object for that Room database? I've already tried the RoomDatabase object but the operations available are pretty limited compared to SQLiteDatabase.
RoomDatabase has getOpenHelper(), which returns a SupportSQLiteOpenHelper. As with SQLiteOpenHelper, SupportSQLiteOpenHelper offers getReadableDatabase() and getWritebleDatabase() methods. Those return a SupportSQLiteDatabase.
SupportSQLiteDatabase is not identical to SQLiteDatabase, but it is close, and it is supported by more SQLite implementations than just the framework SQLite.
Yes, you can easily get an SQLiteDatabase BUT NOT via Room.
e.g. assuming the Database Name passed to the databaseBuilder is defined as a constant DATABASE_NAME in the TheDatabase class then you can use. Also that a_context is a context (e.g. by using this in an activity)
SQLiteDatabase sqlitedb = SQLiteDatabase.openDatabase(a_context.getDatabasePath(TheDatabase.DATABASE_NAME).getPath(), null, SQLiteDatabase.OPEN_READWRITE);
Obviously, you need to be careful using both Room and the above (probably ensuring that the each issues a close before the other opens).
I hope I'm not asking something that has a direct answer in embedded database programming. If I am, please direct me to the answer and I will close this question.
My question is the following: suppose I have a subclass of SQLiteOpenHelper in my android application. This subclass overrides the appropriate methods, and also creates a database (say database.db) and I want it to have some functionality for inserting things into the database (i.e to each table). How can I write these methods so that there is little code duplication? The reason I ask this is because each insertion method does exactly the same thing in general: get the database for writing, create the ContentValues object, fill it with the right data, and use the insert method in SQLiteOpenHelper.
The other option, if I don't want to have an insert method per table, is to just run raw queries from a reference I have to this subclass of SQLiteOpenHelper. To be honest, neither seem to be good solutions to the problem of having an easy to use API to insert/delete/query a database via this class. I would love some help, thanks!
I hope I understood you correctly. You need to move your SQLiteOpenHelper class in another class file and reuse code of it every time you need to open your db, get query or insert values?
If yes - I can provide links for you to read abroad SO, also some snippets for you.
Lets suggest you have subclass
class DBHelper extends SQLiteOpenHelper {
public DBHelper(Context context) {...}
public void onCreate(SQLiteDatabase db) {...}
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {...}
}
Create new java class in your package named DBHelper and move whole code of DBHelper inside of it. Than, when you need reference of db in your code, use this:
public class MainActivity extends AppCompatActivity{
DBHelper dbHelper;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dbHelper = new DBHelper(this);
SQLiteDatabase db = dbHelper.getWritableDatabase();
//rest of your code goes here
}
If you want to get data from db without typing code for cursor and query each time, you can go and read answer, provided by OschtärEi (link)
In my app, I have implemented multiple content providers for a single db, one per table, as there are a lot of tables and having the logic of all of them in a single content provider is going to be quite messy.
I followed the advice given by Simo in this link:
Content provider for multiple tables
So there is an abstract AbsShopContentProvider that has a SQLiteOpenHelper member variable. This abstract content provider is then extended by multiple content providers like Table1Provider, Table2Provider,...
So now I have one instance of my SQLiteOpenHelper per Content Provider. Will this create any issues regarding thread safety?
Is it a good idea to make this SQLiteOpenhelper variable "static" in my abstract Content Provider and create an instance of it in onCreate() of the Abstract Provider only if it is null? Will it solve the issue of having many DB helper objects?
All you need is to make sure that you share one instance of SQLiteDatabase , SQLite automatically takes care of locking for same database.
To make a database globally available, extend Application class:
public class App extends Application {
private static SQLiteDatabase db;
public static SQLiteDatabase getDb() {
return db;
}
#Override
public void onCreate() {
super.onCreate();
db = new MySQLiteOpenHelper(getApplicationContext()).getWritableDatabase();
}
}
and add it to manifest:
<application
android:name=".App"
Now, you can access the database from any Activity/Fragment/Service by calling App.getDb()
I was watching android tutorial on databases. They create a class and extend SQLiteOpenHelper. Then they would create a static final string for the database name. When you request a writable database it will always select using the static string. What is the convention used for selecting a different database? Just create another class and extend SQLiteOpenHelper? Also can you pass SQLiteDatabase from one activity to another using intent.putExtra or similar method?
What is the convention used for selecting a different database?
The SQLiteOpenHelper handles more than just a database name. It handles schema version, creation, upgrades, etc... So I would expect the convention to be to define another class and extend SQLiteOpenHelper.
Can you pass SQLiteDatabase from one activity to another using intent.putExtra or similar method?
No, you can't. But you can create a new object of the class describing the database (that one that extends SQLiteOpenHelper, and request a database from it. Internally the SQLiteOpenHelper keeps a single writable connection to a database.
Currntly i am creating SQLite database in android using following code:
SQLiteDatabase db;
try{
SQLiteDatabase dbe = SQLiteDatabase.openDatabase("/data/data/bangla.rana.fahim/databases/dictionary", null,0);
dbe.close();
}
catch(SQLiteException e){
db = openOrCreateDatabase("dictionary", MODE_PRIVATE, null);
db.execSQL("CREATE TABLE IF NOT EXISTS LIST(wlist varchar,ex varchar);");
db.close();
}
And retrieving data using cursor like:
Cursor cc = db.rawQuery(q, null);//q is the desired query.
But i have seen many example of using helper and adapters for the very same purpose. So, my question is what are the benefits of using them?
I guess you are referring to SQLiteOpenHelper, the documentation is pretty clear:
A helper class to manage database creation and version management.
You create a subclass implementing onCreate(SQLiteDatabase),
onUpgrade(SQLiteDatabase, int, int) and optionally
onOpen(SQLiteDatabase), and this class takes care of opening the
database if it exists, creating it if it does not, and upgrading it as
necessary. Transactions are used to make sure the database is always
in a sensible state.
With this you don't have to manually create your database and take care of upgrading it. You just have to implement the two methods onCreate() and onUpgrade() with your database logic and android will make sure to call this methods when is needed. I don't know at what are you referring when you say adapter.
Well it is more concerned about software desing patters. In the SQLiteOpenHelper you do the tasks more related with creating and updating the database when user installs the app or in a db version change.
In an Adapter class which holds the previous class you usually hold a reference to the db and you have the methods to actually interact with it doing the different kind of queries (selects, inserts...).
This way you have you code well encapsulated and therefore it is much easier to maintain.