In my activity I need to call to query different databases depending on which one the user chooses. Instead of calling each one individually I would like to have one code for a query and simply change the intent or class of the database from a string value. Basically I need to change my database name reference from my class "EmployeeDatabase" to whatever database the user currently has selected. I need to set the selected string x as class y and then have class y able to query. I'm trying to explain to the best of my knowledge, sorry if it is confusing. Thank you for your help!
Somehow I need to be able to set variable y as whichever class the user chooses and then be able to query like: c=db.query(y.EMP_TABLE4, null,null,null,null,null,null); It says EMP_TABLE4 cannot be resolved or is not a field.
How my database works right now with only one database option:
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.redlight2);
EmployeeDatabase db=null;
try{
ListContent = (ListView)findViewById(R.id.listView1);
db=new EmployeeDatabase(this);
c=db.query(EmployeeDatabase.EMP_TABLE4, null,
null,null,null,null,null);
mydisplayadapter4 adapter = new mydisplayadapter4(this, c);
ListContent.setAdapter(adapter);
}
catch(Exception e){System.out.println("problem");}
How I want it to work:
String x;
Class<?> y;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.redlight2);
String x = "my database class name";
try {
y = Class.forName(x);
} catch (ClassNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
// I want to replace everything that says EmployeeDatabase with y
EmployeeDatabase db=null;
try{
ListContent = (ListView)findViewById(R.id.listView1);
db=new EmployeeDatabase(this);
c=db.query(EmployeeDatabase.EMP_TABLE4, null,
null,null,null,null,null);
mydisplayadapter4 adapter = new mydisplayadapter4(this, c);// OWN ADAPTER
ListContent.setAdapter(adapter);
If you want to access various databases with all having the same schema ( from your code it seems like it is), then it should be very simple.
Make a derived class from SQLiteOpenHelper.
When you create this object, pass the database name. The other parts of the application do not need to know what database it is using.
Also make sure to make this class a singleton. So you can switch to other database easily by closing the currently used one and then opening the new one.
When you will be calling getWritableDatabase() for database operations from any place, it will return the correct db handle.
Related
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.
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.
While inserting my listview gets refreshed automatically but not update when the item in the listview is updated. It only updates on database. I can see the listview is updated when I close the application and open again, or come back from previous activity.
I found some discussion related to my problem. Like: Refresh ListView with ArrayAdapter after editing an Item . Her I found that make a new method to populate the Listview and call it in the onResume method of your activity.
And the problem has been solved using this. But I do not get how to make new method mentioned like there. Could anybody help me to make it understandable?
My code in activity class:
personNamesListView = (ListView) findViewById(R.id.traineeslist);
traineeListAdapter = new ArrayAdapter<Trainee>(this,
android.R.layout.simple_list_item_1,
currentTraining.getTraineeArrayList());
personNamesListView.setAdapter(traineeListAdapter);
protected void onResume() {
super.onResume();
}
And this way I populated my personNamesListView using method stringToString() in model class;
public void loadTraineeList() {
DatabaseHelper db = DatabaseHelper.getInstance();
this.traineeArrayList = new ArrayList <Trainee>();
Cursor cursor = db.select("SELECT * FROM person p JOIN attendance a ON p._id = a.person_id WHERE training_id="+Integer.toString(this.getId())+";");
while (cursor.moveToNext()) {
Trainee trainee = new Trainee();
trainee.setID(cursor.getInt(cursor.getColumnIndex(DatabaseHelper.PERSON_ID)));
trainee.setFirstname(cursor.getString(cursor.getColumnIndex(DatabaseHelper.PERSON_FIRSTNAME)));
trainee.setLastname(cursor.getString(cursor.getColumnIndex(DatabaseHelper.PERSON_LASTNAME)));
trainee.setJobTitle(cursor.getString(cursor.getColumnIndex(DatabaseHelper.PERSON_JOBTITLE)));
trainee.setEmail(cursor.getString(cursor.getColumnIndex(DatabaseHelper.PERSON_EMAIL)));
trainee.setCompany(cursor.getString(cursor.getColumnIndex(DatabaseHelper.PERSON_COMPANY)));
trainee.setDepartment(cursor.getString(cursor.getColumnIndex(DatabaseHelper.PERSON_DEPARTMENT)));
trainee.setBadgeNumber(cursor.getString(cursor.getColumnIndex(DatabaseHelper.PERSON_BADGE)));
// Pass to the arraylist
this.traineeArrayList.add(trainee);
}
}
public ArrayList<Trainee> getTraineeArrayList() {
return traineeArrayList;
}
public void setTraineeArrayList(ArrayList<Trainee> traineeArrayList) {
this.traineeArrayList = traineeArrayList;
}
I insert and Update data into database into one method:
public void storeToDB() {
DatabaseHelper db = DatabaseHelper.getInstance();
db.getWritableDatabase();
if (this.id == -1) {
// Person not yet stored into Db => SQL INSERT
// ContentValues class is used to store a set of values that the
// ContentResolver can process.
ContentValues contentValues = new ContentValues();
// Get values from the Person class and passing them to the
// ContentValues class
contentValues.put(DatabaseHelper.PERSON_FIRSTNAME, this
.getFirstname().trim().toUpperCase());
contentValues.put(DatabaseHelper.PERSON_LASTNAME, this
.getLastname().trim().toUpperCase());
contentValues.put(DatabaseHelper.PERSON_JOBTITLE, this
.getJobTitle().trim().toUpperCase());
contentValues.put(DatabaseHelper.PERSON_EMAIL, this.getEmail());
contentValues.put(DatabaseHelper.PERSON_COMPANY, this.getCompany()
.trim().toUpperCase());
contentValues.put(DatabaseHelper.PERSON_DEPARTMENT, this
.getDepartment().trim().toUpperCase());
contentValues.put(DatabaseHelper.PERSON_BADGE, this
.getBadgeNumber().trim().toUpperCase());
// here we insert the data we have put in values
this.setID((int) db.insert(DatabaseHelper.TABLE_PERSON,
contentValues));
} else {
// Person already existing into Db => SQL UPDATE
ContentValues updateTrainee = new ContentValues();
updateTrainee.put(DatabaseHelper.PERSON_FIRSTNAME, this
.getFirstname().trim().toUpperCase());
updateTrainee.put(DatabaseHelper.PERSON_LASTNAME, this
.getLastname().trim().toUpperCase());
updateTrainee.put(DatabaseHelper.PERSON_JOBTITLE, this
.getJobTitle().trim().toUpperCase());
updateTrainee.put(DatabaseHelper.PERSON_EMAIL, this.getEmail());
updateTrainee.put(DatabaseHelper.PERSON_COMPANY, this.getCompany()
.trim().toUpperCase());
updateTrainee.put(DatabaseHelper.PERSON_DEPARTMENT, this
.getDepartment().trim().toUpperCase());
updateTrainee.put(DatabaseHelper.PERSON_BADGE, this
.getBadgeNumber().trim().toUpperCase());
db.update(DatabaseHelper.TABLE_PERSON, updateTrainee,
DatabaseHelper.PERSON_ID+"= ?", new String[]{Integer.toString(this.getId())});
System.out.println("Data updated");
}
}
You should call traineeListAdapter.notifyDataSetChanged() whenever you update your ArrayList representing the items in the ListView.
There's a similar question here that can give you some help.
Although I've accomplished something similar using
yourlistview.invalidateViews()
after changing the data to show in the listview
when notifyDataSetChanged() didn't work.
EDIT:
After making all the operations in the data that I want to show i just set the adapter and try to refresh my listview by calling invalidateViews().
selectedStrings = new ArrayList<String>(typeFilterStrings);
adapter.setArrayResultados(selectedStrings);
listTypeFilter.invalidateViews();
It's not obligatory to set the adapter again in my case worked.
use like this:
Create an instance of your custom adapter, so you can use it anywhere you like...
public class ScoreList extends SherlockFragmentActivity {
private ListView listViewScore;
private ScoreListAdapter adapter;
static List<Score> listScore = new ArrayList<Score>();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.score_list);
ctx = this;
listScore = dbh.getAllScores();
listViewScore = (ListView) findViewById(R.id.score_list);
adapter = new ScoreListAdapter(ctx, R.layout.score_row_item, listScore);
listViewScore.setAdapter(adapter);
((BaseAdapter) listViewScore.getAdapter()).notifyDataSetChanged();
}
}
By the way, if your listScore array is already loaded, then you do not need to use
adapter.notifyDatasetChanged();
when button is pressed i want to the text to change to the database collumn values, i know its wrong but here is the code:
private void MostraDados() {
// TODO Auto-generated method stub
final TextView text = (TextView) findViewById(R.id.tvUSUARIO);
Button mostrar = (Button) findViewById(R.id.bMostrar);
mostrar.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
db = openOrCreateDatabase("dbtest.db", Context.MODE_PRIVATE, null);
String q = "SELECT * FROM dbtest.db WHERE usuarioorigem='";
text.setText(q);
//text.execSQL("DROP COLUMN IF EXISTS usuarioorigem");
}
});
}
Your code is missing some critical parts for example a DatabaseClass that manages the cursor and database.
private void MostraDados() {
final TextView text = (TextView) findViewById(R.id.tvUSUARIO);
Button mostrar = (Button) findViewById(R.id.bMostrar);
mostrar.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// our missing a database helper
MyDatabaseClass dbhelper = new MyDatabaseClass();
dbhelper.open();
Cursor result = dbhelper.doMyQuery();
String mystring = result.getString(0);
text.setText(mystring);
dbhelper.close();
}
});
....
public class WorkoutDbAdapter {
....
public Cursor doMyQuery()
{
return this.mDb.query( yourQuery );
}
}
This is the minimum you'd need and even with the above i'm missing a lot of the smaller detail. Search for some tutorials on creating and using Databases.
Essentially however you need to get the cursor back, set the position of the cursor, or cursor.moveNext() and then get the value that you can assign to the textField.
Your source code lacks a correct call to a database and access to the cursor. Hopefully you'll find some decent tutorials that will flesh the rest out for you.
The SQL is not written correctly. You must SELECT from a column. And you're passing the query string the the text view. You should first review how to query the database with the cursor, and how to retrieve what you want from the cursor.
So I would look into how to use the curosr, all of that's available in the Android docs, and you might want to try the API demos in the emulator I'm sure you can learn how to work with the cursor there as well. So look here, http://developer.android.com/reference/android/database/Cursor.html.
And here, Is Android Cursor.moveToNext() Documentation Correct?.
After getting the cursor, you could do something like this:
while(c.moveToNext(){
text.setText(c.getString(0))
}
Hai i created a DataBase and inserted the value in one Class,and i try to delete the record in another class but,the Whole table is Deleted.i need to delete the entire record only without deleteing the table.is it possible to delete all record without any condition?
kindly help me
Thanks in advance
public void deletePayment()
{
db.delete(DATABASE_TABLE3, "KEY_ROLLID=?",null);//i want to delete all row in KEY_ROLLID
}
You doesn't try DELETE Statement,
In android you can execute Sql Query with db.rawQuery also, in this you can pass Delete Statement for your table, as:
db.rawQuery("Delete FROM Table_Name");
Use this concept:
public static void deletedatafromtable(Context context) {
// TODO Auto-generated method stub
try {
SQLiteDatabase SQLITE_db;
SQLITE_db = context.openOrCreateDatabase("databaseName",
SQLiteDatabase.CREATE_IF_NECESSARY, null);
SQLITE_db.setVersion(1);
SQLITE_db.setLocale(Locale.getDefault());
SQLITE_db.setLockingEnabled(true);
String DELETEPASSCODE_DETAIL = "delete from tableName;";
SQLITE_db.execSQL(DELETEPASSCODE_DETAIL);
SQLITE_db.close();
} catch (Exception e) {
// TODO: handle exception
}
}