How do I access the same database from different activities? - android

I am writing an app and I want to store the high scores. I have it working to show the high score on the end activity. However, I want to have a highscores activity to show all the highscores. I am doing this by, in the highscores activity, calling the end activity to return the high score, so the database doesn't change. After running a debug, I saw that it got to the databasehandler but got caught on getReadableDatabase(), saying that it was unable to invoke the method on a null object reference.
This is my highscores method(I didn't include the whole thing, and the ifs are because there are different difficulties of the game)
public class highscores extends Activity {
TextView mode, score;
Button right, back;
int modenum;
end get=new end();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_highscores);
mode =(TextView)findViewById(R.id.scorebar);
score =(TextView)findViewById(R.id.score);
right =(Button)findViewById(R.id.button14);
back =(Button)findViewById(R.id.highscores);
mode.setText("Easy");
score.setText(get.datatostring(1));
modenum =1;
}
public void right(View view){
if(modenum==1) {
modenum = 2;
mode.setText("Hard");
score.setText(get.datatostring(2));
}else if(modenum==2) {
modenum = 3;
mode.setText("X-Mode");
score.setText(get.datatostring(3));
}else {
modenum = 1;
mode.setText("Easy");
score.setText(get.datatostring(1));
}
}
This is in the end method
public String datatostring(int difficulty){
MyDBHandler db = new MyDBHandler(this, null,null,1);
return db.datatostring(difficulty);
}
And this is in the databasehandler
public String datatostring(int difficulty){
SQLiteDatabase db = getReadableDatabase();
String dbString = "";
String c;
if(difficulty==1)
c = COLUMN_SCORE;
else if(difficulty==2)
c = COLUMN_HARD;
else
c = COLUMN_X;
String query = "SELECT "+c+" FROM "+TABLE_SCORES;
Cursor cursor = db.rawQuery(query,null);
cursor.moveToFirst();
if(!cursor.isAfterLast()){
int index = cursor.getColumnIndex(c);
String value = cursor.getString(index);
if(value!=null){
dbString += cursor.getString(cursor.getColumnIndex(c));
}
}
db.close();
cursor.close();
return dbString;
}

I suggest to use a SQLiteOpenHelper to handle this.
You should see this example:
Android Sqlite DB
Hope that helps, i personally works in this way.
The other option is to use som ORM, i recommend to use GreenDao, its good, and lets handle easy way this kind of actions.
Regards.

Follow this tutorial to create a concurrent and scalable database
Remember :
You should always make database queries through one instance (Singleton) of your database adapter else you will face a lot of issues when accessing your database concurrently from different classes.
Use SQLiteOpenHelper class for accessing your database. As it gives you many useful functions eg. upgrading user's database when you publish app updates with schema changes.

The short answer is yes.
But as you see you have no clear concept of the connection.
Bd in the android is SQLite (recommendation) Always be on the same route, you need to create a class that allows you to manage and connect to the database. The class will be SQLiteOpenHelper
Check THIS
You can connect one or more times to the database, since activity A, B or activity you want.
The important thing is to define the handler to connect, close, make request to the database.

Related

Android - Running multiple Database Instances

I am developing an android app. In that app, I have to add and get the data from my database constantly.
I using three separate threads to do so. I do not think I have a thread problem as in my DDMS I can monitor the threads opening But what I think, I am failing to grasp is the Database instances.
For example,
I have a method which shall construct a filename which is made up of the value in a cell of one table + "_" + value of a cell in another table. So, I have this method which calling two other methods each with the task to go to the database and get that value.
Problem is that I am not sure how I should create an instance.Below you can see that for each method I have created a separate instance of the same database and then closed that.
In this AsyncTaskRunner class I have many methods of the same as below which are doing their own task, but open a different instance name for the same database each time.
This seems very wrong.I would imagine that as soon as the class opens I could open ONE single instance of the database and then not close it until Destroy() so that all methods can do their thing.
What can I do better?
Here is my code :
public String evaluateATable(String filenamePrefix){
SQLDatabase getATableData = new SQLDatabase(mContext);
getATableData.open();
String aRowId = SQLDatabase.evalATable(filenamePrefix);
getATableData.close();
if(aRowId != null){
return aRowId;
}
return null;
}
public String evaluateLTable(String filenamePrefix){
SQLDatabase getLtabledata = new SQLDatabase(mContext);
getLtabledata.open();
String lRowId = SQLDatabase.evalLTable(filenamePrefix);
getLtabledata.close();
if(lRowId != null){
return lRowId;
}
return null;
}
you can do one thing ,you have to declare SQLDatabase and create instance of it once, and then use that in all method
just like below
Public class test extends Activity {
SQLDatabase getATableData;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SQLDatabase getATableData = new SQLDatabase(this);
}
public String evaluateATable(String filenamePrefix){
getATableData.open();
String aRowId = SQLDatabase.evalATable(filenamePrefix);
getATableData.close();
if(aRowId != null){
return aRowId;
}
return null;
}
public String evaluateLTable(String filenamePrefix){
getLtabledata.open();
String lRowId = SQLDatabase.evalLTable(filenamePrefix);
getLtabledata.close();
if(lRowId != null){
return lRowId;
}
return null;
}

Globally defined instance of SQLite generates error

I want to declare an instance of SQLite Database globally as a private final variable.
1)why the way i used in the below posted code causes the logcat to generate erros and the app crashes.
2)is there any other way so I can define an instance of my DB globally and final?
Java_Code:
public class SQLiteTest00 extends Activity {
final MyDB myDB = new MyDB(this);
final SQLiteDatabase mySQLiteDB = myDB.getWritableDatabase();
final ContentValues myContVals = new ContentValues();
private final String TABLE_NAME = "MYDATA";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sqlite_test00);
myContVals.put("name", "loc00");
myContVals.put("lat", 33);
myContVals.put("lng", 53);
myContVals.put("time", "12:30");
myContVals.put("date", "11/05/2014");
lodgeIntoDB(myContVals);
}
private void lodgeIntoDB(ContentValues cv) {
long newID = mySQLiteDB.insert(TABLE_NAME, null, cv);
if (newID == -1) {
Toast.makeText(getBaseContext(), "Error Commiting Record(s)", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getBaseContext(), "Data Commited Successfully", Toast.LENGTH_SHORT).show();
}
}
}
Is MyDB your extended version of SQLiteOpenHelper? Also, why are you creating a final version of a ContentValues? Could you explain why you need a final copy of the db? The db will be private to your app by default, that is the way Android does it. If you extend SQLiteOpenHelper, then you can call the getWritableDatabase() in the onCreate of your main activity and if your db variable is a member variable you will have it. Maybe I am missing something. Also, from what I have read, it is best to close the db if you are not using it and then to use the helper class later to get it again if you need to read from or write to it. Thanks. Ps. one other thing, anytime I have seen the helper class called to get a copy of the db, it is done inside onCreate or another method not at the top in the variable declartions. Try moving it into onCreate.

Proper implementation of DbOperations in Async Task

In my android application, I have various "entities" such as user defined. I'm using a single DbOperations class that has the default Select, Insert, Update and Delete functionality.
An async task is used as an intermediary. It sits in between my entities and DbOperations class and performs everything asynchronously. Here's an example.
ASYNC CLASS - with Insert Method code
private DbResponse InsertUser() {
ContentValues cntValues = GetCrmUserContentVal();
long result = _dbConn.InsertRecord(cntValues, TABLE_NAME);
DbResponse dbResponse = new DbResponse();
if(result == -1)
{
dbResponse.setStatus(false);
}
else {
dbResponse.setStatus(true);
dbResponse.setID(result);
}
return dbResponse;
}
CRM USER Entity Class - Insert Method
public void InsertintoDb()
{
new CRMUserDbOperations(this,this,DbOperationType.Insert,getCurrentContext()).execute();
}
DbResponse - Return type class is a seperate class -
private Boolean Status;
private String ErrorMessage;
private Cursor Data;
private long ID;
private DbOperationType dbOpType;
In the doBackground process of the async task, I have this switch code -
switch (_DbOpType) { // Enum type.
case Insert:
dbResponse = InsertUser();
break;
case Select:
dbResponse = SelectUser();
break;
case Update:
dbResponse = UpdateUser();
break;
default:
throw new InvalidParameterException(
_Context.getString(R.string.invalid_io));
}
As you can notice this asynchronous task has code for all the various operations I might have to perform on the entity. For other entities, I'll have the same structure as well...
Now my question is, could I be doing this in a better manner?
Yes it can be done in a better way. Let me give you an example of how we are handling it in our current app. You just need 4 AsyncTasks in total for insert, update, delete and select operations. Let me give you an example.
You have an interface and every entity will implement it:
public interface DbOps {
public int delete(String where);
public void insert();
public void update();
public Cursor select();
}
NOTE: Arguments and return types will be of your choice that fits your need but must also fit for every entity class. I am going to use delete() method as an example.
Now you need only one DeleteTask for all entitites:
private static class DeleteTask extends AsyncTask<String, Void, Integer> {
private final DbOps mOps;
public RowDeleteTask(DbOps ops) {
mOps = ops;
}
#Override
protected Integer doInBackground(String... wheres) {
String where = wheres[0];
int rowsDeleted = mOps.delete(where);
return rowsDeleted;
}
}
Fire it like this:
new DeleteTask(mUserEntity).execute("id = 4");
new DeleteTask(mMoviesEntity).execute("name = x-man");
and obviously you will have something similar to this if we take UserEntitiy for example:
public UserEntity implements DbOps{
#Override
public int delete(String where){
return _dbConn.delete(mTable, where, null);
}
.
.
.
}
This isn't product placement or anything, it is open source, I have been working on Async databases for a while now, and have recently created a library for it.
It is hosted on Github at http://fabiancook.github.io/AndroidDbHelper/
It covers a more general need for async database usage, you can either do one thing async if you want, or the whole lot.
It will have an implementation for a entity framework in the coming months as I am working on a Ubuntu touch version at this moment.
Any info needed just ask.
For small amounts of objects entities are great, but when you want to report on them they get really slow, which is even apparent in microsofts entity framework. For the most it is usually a heck of a lot faster (performance wise) to use straight SQL in an async way as it takes out the need for that middle object.
Note, between android 1.6 and 3.0 the AsyncTask class would execute sometimes in parallel, which would cause some problems in any database. So when using those versions you there would have to some differences, this is being worked into my DbHelper :)
http://developer.android.com/reference/android/os/AsyncTask.html#execute(Params...)

SQLite usage from activity and service

I have created a databaseprovider class which uses single instance of db object. Object is created in main activity and closed onDestroy method. This seems ok (but get some errors such as: db already closed or db is not open on some users devices that I cannot simulate).
I want to add a service to the application for the content download and this service can run with scheduler which make me think about single instance of db object will not work. Should I use another object for the service, will it result consistency problems? Can you kindly advice what would be the best way?
Databaseprovider class exm:
public class DatabaseProvider {
private static DatabaseHelper helperWriter;
public static SQLiteDatabase db_global;
public DatabaseProvider(Context c) {
helperWriter = DatabaseHelper.getHelper(c, true);
}
private static SQLiteDatabase getDB() {
if(db_global == null)
db_global = helperWriter.getWritableDatabase();
else if(!db_global.isOpen()) {
try {
db_global.close();
}
catch(Exception ex) {
ex.printStackTrace();
}
db_global = helperWriter.getWritableDatabase();
}
return db_global;
}
public String GetVersion() {
SQLiteDatabase db = getDB();
Cursor c = db.query(DatabaseHelper.PARAMETER_TABLE_NAME, new String[] {"VALUE"}, "KEY='Version'", null, null,null,null);
String version = "";
if(c.moveToNext())
{
version = c.getString(0);
}
else
version = "0";
c.close();
return version;
}
public long UpdateVersion(String value) {
ContentValues initialValues = new ContentValues();
initialValues.put(DatabaseHelper.PARAMETER_COLUMN_VALUE, value);
SQLiteDatabase db = getDB();
long r = db.update(DatabaseHelper.PARAMETER_TABLE_NAME, initialValues, "KEY='Version'", null);
if(r <= 0)
r = helperWriter.AddParameter(db, "Version", value);
//db.close();
return r;
}
public void CloseDB() {
if (db_global != null)
db_global.close();
db_global = null;
helperWriter.close();
}
}
Not sure if this will help, but...
you can't rely on onDestroy() in case the app crashes. Android may also keep your app in RAM, even if you exit it. Also, your main activity may get destroyed while the app is getting used if you are on a subactivity. It can also get recreated.
Sometimes it's better to have calls that open the DB, does stuff to it, and then closes it within the same function. If you are using a service, it may actually help things. I also am not sure if you should have a situation where a DB can be opened and/or accessed from a variety to different places at once without some management code
I see a couple questions:
A)
(but get some errors such as: db already closed or db is not open on some users devices that I cannot simulate).
...
Start an activity, then update content and some db operations in AsyncTask. While update is in progress go back and start the same activity again.
To work around these errors have you considered using a [Loader][1]? It's a callback based framework around ContentProviders.
B)
add a service to the application for the content download and this service can run with scheduler which make me think about single instance of db object will not work. Should I use another object for the service, will it result consistency problems?
This post by #commonsware from this website, suggests not to use Service for long running tasks. Instead the AlarmManager is suggested. I've only worked with short running services (for audio IO) myself.

Problem in creating a database in SQLite in Android

Hi I am new to android and I have a problem in creating a database.
public class database extends ListActivity {
/** Called when the activity is first created. */
private final String MY_DATABASE_NAME = "myCoolUserDB.db";
private final String MY_DATABASE_TABLE = "t_Users";
Context c;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ArrayList<String> results = new ArrayList<String>();
setContentView(R.layout.main);
SQLiteDatabase mydb=null;
try
{
mydb.openOrCreateDatabase(MY_DATABASE_NAME, null);
} catch(Exception e){}
}
}
When I run this code it throws a run time exception. Please help me.
If you are going to call a static method like openOrCreateDatabase, do it on the class (SQLiteDatabase.openOrCreateDatabase(...)), not an instance. It's a lot clearer - the way you've done it looks like you're calling an instance method, so looks like a sure NullPointerException, which of course is misleading.
As someone else has stated, the stack trace would be the most useful thing when asking for help with an exception.
(Almost) never catch an exception without at the very least logging it. Don't just do nothing with it. There are of course exceptions to every rule, but let's not go there for the moment. Anyway, if you don't at least log it, you're just throwing away information that would tell you what went wrong when everything goes to crap later.
You shouldn't be using that method directly, and should instead be extending SQLiteOpenHelper . See the android developers page on data storage to get started (I'd post a link but apparently I'm only allowed one link in my post ?!), and since you've probably had to download the SDK to get going, look in the samples that come with it for the Notepad sample application. That contains a NotePadProvider class, which is a good example of both a content provider and database access, which often go hand-in-hand on android. I'd suggest compiling that application and making some simple changes to it before you jump into making your own one.
For working with sqlite database you need to create class extended from SQLiteOpenHelper:
private class DBHelper extends SQLiteOpenHelper {
public DBHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_TABLES);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL(UPGRADE_TABLES);
}
}
Then you can get access to db using DbHelper object:
DBHelper dbHelper = new DBHelper(Activity.this);
SQLiteDatabase db = dbHelper.getReadableDatabase();
I run into the same problem. It figures out that two bugs happens during development
dir "databases" was not existent
accendently ".db" was created as directory.
They following code cover both
File dbFile = getDatabasePath ("abc.db");
if (dbFile.isDirectory ()) {
dbFile.delete();
}
if (! dbFile.exists()) {
String path = dbFile.getParent ();
new File (path).mkdirs ();
}
database = SQLiteDatabase.openDatabase (dbFile.getAbsolutePath (), this, SQLiteDatabase.OPEN_READWRITE | SQLiteDatabase.CREATE_IF_NECESSARY);
Hope this helps
I think SQLiteOpenHelper is only useful for "single table" databases. For multiple table applications I consider directly using SQLiteDatabase fit better to a good architecture.
This is a simple post which tells you how to insert data in to a SQLite database in Android and further more this links shows you how to retrieve data from a SQLite database in Android .

Categories

Resources