just a simple error I have but I am really having a hard time trying to solve this problem. why is this getContext() are not applied?
public void ClearRecentPlayer() {
mDbHelper = new DataConn(getContext()); //<---getContext() in redline(not applied)
SQLiteDatabase db = mDbHelper.getWritableDatabase();
ContentValues v = new ContentValues();
v.put(FeedReaderContract.FeedEntry.COLUMN_NAME_STATS, 0);
String selection = FeedReaderContract.FeedEntry.COLUMN_NAME_STATS + " = ?";
String[] selectionArgs = { "0" };
int c = db.update(
FeedReaderContract.FeedEntry.TABLE_NAME_PLAYER,
v,
selection,
selectionArgs);
}
and with this...
public class DataConn extends SQLiteOpenHelper {
public static final int DATABASE_VERSION = 1;
public static final String DATABASE_NAME = "db_egame.db";
DataConn mDbHelper;
public DataConn(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(SQL_CREATE_EASY_ENTRIES);
db.execSQL(SQL_CREATE_HARD_ENTRIES);
db.execSQL(SQL_CREATE_DIFF_ENTRIES);
db.execSQL(SQL_CREATE_PLAYER_ENTRIES);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL(SQL_DELETE_EASY_ENTRIES);
db.execSQL(SQL_DELETE_HARD_ENTRIES);
db.execSQL(SQL_DELETE_DIFF_ENTRIES);
db.execSQL(SQL_DELETE_PLAYER_ENTRIES);
onCreate(db);
}
#Override
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
onUpgrade(db, oldVersion, newVersion);
onCreate(db);
}
As explained here (https://stackoverflow.com/a/10641257/2319627)
•View.getContext(): Returns the context the view is currently
running in. Usually the currently active Activity.
•Activity.getApplicationContext(): Returns the context for the
entire application (the process all the Activities are running inside
of). Use this instead of the current Activity context if you need a
context tied to the lifecycle of the entire application, not just the
current Activity.
•ContextWrapper.getBaseContext(): If you need access to a Context
from within another context, you use a ContextWrapper. The Context
referred to from inside that ContextWrapper is accessed via
getBaseContext.
So, it will be better to use getApplicationContext() when you are trying to use a DataBaseHelper.
And, you can call getApplicationContext from activity or service only, or from an instance of context. Like activity.getApplicationContext()
You need an application context for a Database helper class. So, pass a context to the database on initialization
ClearRecentPlayer method is in an activity? else, you have to pass the application context to the class from which you call ClearRecentPlayer method.
you can either create a member variable .Context in that class, or you can call the ClearRecentPlayer method as ClearRecentPlayer (Context context)
getContext() is only an available method of a View.
If your method is in that database class, you don't actually need the Context. Or any instance of DataConn within its own class.
public class DataConn extends SQLiteOpenHelper {
public static final int DATABASE_VERSION = 1;
public static final String DATABASE_NAME = "db_egame.db";
private Context mContext;
public DataConn(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
this.mContext = context;
}
public void clearRecentPlayer() {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues v = new ContentValues();
v.put(FeedReaderContract.FeedEntry.COLUMN_NAME_STATS, 0);
String selection = FeedReaderContract.FeedEntry.COLUMN_NAME_STATS + " = ?";
String[] selectionArgs = { "0" };
int c = db.update(
FeedReaderContract.FeedEntry.TABLE_NAME_PLAYER,
v,
selection,
selectionArgs);
}
Try getApplicationContext() instead of getContext() for activity/AppCompactActivity,
Related
I have a static, singleton instance of a SQLiteOpenHelper implementation.
public class MyDbHelper extends SQLiteOpenHelper {
public static final int DATABASE_VERSION = 5;
public static final String DATABASE_NAME = "myapp.db";
public static SQL_CREATE_MY_TABLE ="some correct table creation sql";
public static SQL_DELETE_MY_TABLE="some correct table delete sql";
...
public MyDbHelper (Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
public void onCreate(SQLiteDatabase db) {
db.execSQL(SQL_CREATE_MY_TABLE);
db.execSQL(SQL_CREATE_OTHER_TABLE);
}
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL(SQL_DELETE_MY_TABLE);
db.execSQL(SQL_DELETE_OTHER_TABLE);
onCreate(db);
}
}
I have another wrapper over the helper as:
public class MyAppDb {
private static MyDbHelper mydbHelper;
public static MyDbHelper getDbHelper(){
if(null == mydbHelper){
mydbHelper= new MyDbHelper(ctx);
return mydbHelper;
}else{
return mydbHelper;
}
}
}
I am using the mydbHelper from this getDbHelper() in my main Ui code(at various places), as well as in a BroadcastReceiver of an Alarmmanager that executes every 5 mins, and in another system BroadcastReceiver.
Sample usage:
SQLiteDatabase db = MyAppDb.getDbHelper().getReadableDatabase();
Intermittently, I get SQLiteDatabaseLockedException and SQLiteException on the the db implementations from the above mydbHelper.
It seems as though although static, there are two different instances of the MyDbHelper occuring at the same time.
What is happening? Can a static object have a separate instance created from BroadCastReceiver?
Or I am doing it wrong?
I am trying to implement simple database CRUD operations, in case of UPDATE operation user moves to another screen where he inputs the new and old values for the column he wants to update, So while moving to next activity I want to pass the object of database class created in MainActivity to UpdateActivity, I tried it by implementing the Database class Serializbale but it crashes.
java.lang.RuntimeException: Parcelable encountered IOException reading a Serializable object
Here is the code i tried
MainActivity
MyDbHandler dbObj = new MyDBHandler(this, null, null, 1);
public void updateBtnClicked(View view)
{
Intent intent = new Intent(MainActivity.this, ActivityUpdate.class);
intent.putExtra("Object", dbObj);
startActivity(intent);
}
ActivityUpdate
intent = getIntent();
dbObj2 = (MyDBHandler) intent.getSerializableExtra("Object");
public void doneButtonClicked(View view)
{
String str1 = newValue.getText().toString();
String str2 = oldValue.getText().toString();
dbObj2.updateProduct(str1, str2);
finish();
}
So how could the database class object be passed from one to another activity? Thanks
how could the database class object be passed from one to another activity
You don't serialize Database objects. You request them again.
MyDbHandler dbHandler = new MyDbHandler(MainActivity.this); // pass your Activity here
dbHandler.update(new Foo(42));
Where MyDbHandler is some extension of SQLiteOpenHelper written like so
public class MyDbHandler extends SQLiteOpenHelper {
// Database Info
private static final String DATABASE_NAME = "DatabaseName";
private static final int DATABASE_VERSION = 1;
public MyDbHandler(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
// TODO
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion != newVersion) {
// TODO
}
/**
* Update method defined here
**/
public void update(Foo bar) {
SQLiteDatabase db = getWritableDatabase();
// TODO: Write to & close the database
}
}
MyDbHandler must extend Serializable to be correctly serialized.
I'm facing some issues with my SQLite Database. I have about 5activities in my application, but i can access to it from only one activity.
On this activity, i can fully use my DB and do all i want to.
On other activities, i cannot use it. I get an empty DB.
Of course, i use the same code to access my DB, regardless of the activity.
I use a homemade class to access the DB, derivated from SQLiteOpenHelper, and another class to manipulate the first one. The DB is downloaded from an online server into the "/data/data/com.example.btc_pe/databases/" folder.
My first class, to access the DB.
public final class BtcDb extends SQLiteOpenHelper
{
public BtcDb(Context context, String name, CursorFactory factory, int version)
{
super(context, name, factory, version);
}
#Override
public void onCreate(SQLiteDatabase db)
{
// TODO Auto-generated method stub
Log.d("BTC","Db created");
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
// TODO Auto-generated method stub
//db.execSQL("DROP TABLE "+ TABLE_PRODUITS +";");
//onCreate(db);
}
}
And my manipulation class :
public final class DbHelper
{
public static int version=1;
private static final String nomDb="basesqlite.db";
private int num_id=0;
private int num_tension=1;
private int num_typeRacc=2;
private int num_nbCond=3;
private int num_technique=4;
private int num_typeConn=5;
private int num_conn=6;
private int num_desiConn=7;
private int num_refProd=8;
private int num_desiProd=9;
private int num_diamMin=10;
private int num_diamMax=11;
private int num_section=12;
private int num_diamConnMax1=13;
private int num_diamConnMax2=14;
private int num_diamConnMax3=15;
private int num_diamConnMax4=16;
private int num_diamConnMax5=17;
private String tableProduits = "produit";
private SQLiteDatabase bdd;
private BtcDb btcDb1;
public DbHelper(Context context)
{
btcDb1=new BtcDb(context,nomDb,null,version);
}
public void open()
{
bdd=btcDb1.getReadableDatabase();
}
public void close()
{
bdd.close();
}
public SQLiteDatabase getBdd()
{
return bdd;
}
public int getCountDb()
{
Cursor c = bdd.rawQuery("SELECT COUNT(*) FROM"+ tableProduits, null);
return cursorToCount(c);
}
public int cursorToCount(Cursor c)
{
c.moveToFirst();
int i=c.getInt(0);
return i;
}
}
In my activity, I have to instanciate the DBHelper Class, which instanciate BtcDB.
So all I should have to do is this :
DBHelper dbHelper1 = new DBHelper(this);
dbHelper1.open();
//Manipulation of the DB
int i=dbHelper1.getCountDB(); //In example...
Log.d("BTC","DB Count : "+i);
//Other manipulations of the DB.
dbHelper1.closer();
As i said, it works pretty well on one of my activities but not on the others.
I'm pretty lost here ^^".
So, in short, the problem came from my SQL syntaxe. Really frustrating thing when you see how many time i spent on it.
Thanks everyone for your time.
I found many stuff like close the connection and close the cursor, but I do all this stuff. Still the SQLite connection leaks and I get a warning like this:
A SQLiteConnection object for database was leaked!
I have a database manager this, which I call in my activities with the following code:
DatabaseManager dbm = new DatabaseManager(this);
The code of my database manager class follows now:
public class DatabaseManager {
private static final int DATABASE_VERSION = 9;
private static final String DATABASE_NAME = "MyApp";
private Context context = null;
private DatabaseHelper dbHelper = null;
private SQLiteDatabase db = null;
public static class DatabaseHelper extends SQLiteOpenHelper {
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
//create database tables
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//destroy and recreate them
}
}
public DatabaseManager(Context ctx) {
this.context = ctx;
}
private DatabaseManager open() throws SQLException {
dbHelper = new DatabaseHelper(context);
db = dbHelper.getWritableDatabase();
if (!db.isReadOnly()) {
db.execSQL("PRAGMA foreign_keys = ON;");
}
return this;
}
private void close() {
dbHelper.close();
}
}
When I call a database method, I do the following thing:
public Object getData() {
open();
//... database operations take place ...
close();
return data;
}
But as I said, I still get this SQLite connection leaked warning.
What am I doing wrong?
The bolded font in the citation corresponds to this part in your code:
private DatabaseManager open() throws SQLException {
dbHelper = new DatabaseHelper(context);
db = dbHelper.getWritableDatabase();
from: http://www.androiddesignpatterns.com/2012/05/correctly-managing-your-sqlite-database.html
Approach #1: Use an Abstract Factory to Instantiate the
SQLiteOpenHelper
Declare your database helper as a static instance variable and use the
Abstract Factory pattern to guarantee the singleton property. The
sample code below should give you a good idea on how to go about
designing the DatabaseHelper class correctly.
The static factory getInstance method ensures that only one
DatabaseHelper will ever exist at any given time. If the mInstance
object has not been initialized, one will be created. If one has
already been created then it will simply be returned.
You should
not initialize your helper object using with new DatabaseHelper(context).
Instead, always use
DatabaseHelper.getInstance(context), as it guarantees that only one
database helper will exist across the entire application's lifecycle.
public static class DatabaseHelper extends SQLiteOpenHelper {
private static DatabaseHelper mInstance = null;
private static final String DATABASE_NAME = "database_name";
private static final String DATABASE_TABLE = "table_name";
private static final int DATABASE_VERSION = 1;
public static DatabaseHelper getInstance(Context ctx) {
// Use the application context, which will ensure that you
// don't accidentally leak an Activity's context.
// See this article for more information: http://bit.ly/6LRzfx
if (mInstance == null) {
mInstance = new DatabaseHelper(ctx.getApplicationContext());
}
return mInstance;
}
/**
* Constructor should be private to prevent direct instantiation.
* make call to static factory method "getInstance()" instead.
*/
private DatabaseHelper(Context ctx) {
super(ctx, DATABASE_NAME, null, DATABASE_VERSION);
}
}
The complete example of the above-accepted answer:
It may help someone.
Helper Class:
public class DatabaseHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "sample.db";
private static final int DATABASE_VERSION = 1;
private static DatabaseHelper mInstance;
private DatabaseHelper(#Nullable Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
public static synchronized DatabaseHelper getInstance(Context context) {
if (mInstance == null) {
mInstance = new DatabaseHelper(context.getApplicationContext());
}
return mInstance;
}
#Override
public void onCreate(SQLiteDatabase db) {
// create table stuff
}
#Override
public void onUpgrade(SQLiteDatabase db, int i, int i1) {
// drop table stuff
onCreate(db);
}
}
Activity:
SQLiteDatabase database = DatabaseHelper.getInstance(getApplicationContext()).getWritableDatabase();
Cursor cursor = database.query("query");
if (cursor != null) {
while (cursor.moveToNext()) {
// stuff
}
cursor.close();
database.close();
}
private void method() {
Cursor cursor = query();
if (flag == false) { // WRONG: return before close()
return;
}
cursor.close();
}
Good practice should be like this:
private void method() {
Cursor cursor = null;
try {
cursor = query();
} finally {
if (cursor != null)
cursor.close(); // RIGHT: ensure resource is always recovered
}
}
This is the fist time I've used SQLiteOpenHelper (or databases on android). When I get a writeable database I was wondering why onCreate isnt being called on each new instance of the class. Am I doing something wrong?
public class DatabaseHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "MyDatabase.db";
private static final int DATABASE_VERSION = 1;
private String PrSQLcmd = "";
public DatabaseHelper(Context context)
{
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db)
{
db.execSQL("CREATE TABLE IF NOT EXISTS Contact(Firstname TEXT, LastName TEXT");
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
}
}
In SQLiteOpenHelper, the meaning of 'onCreate' is different from what it is in an Activity. Here,'onCreate' is called only once, which is the first time you create the database. The next time you run the app, the database is already there, so it won't call 'onCreate'. Your object level initialization should be done in the constructor and not in 'onCreate'
To see 'onCreate' being called, either manually delete the db file, or simply uninstall the app.