After countless hours of watching YouTube videos and tutorials, and reading up on info and advice, I've come to the conclusion that doing a bible app by using a SQLite database is the way to go.
I've got no knowledge of coding whatsoever and just by taking bits and pieces of tutorial code and advice from someone I've got this far, so please be specific when answering.
I've now created 3x tables.
table_book, table_chapter, and table_verse.
The tables are in one database.
The database gets installed with oncreate when the first Activity is clicked to open.
table_book has 2x columns _id, book_name
table_chapter has 3x columns, _id, id_of_book, chapter_number
table_verse has 4x columns, _id, id_of_chapter, verse_number, verse_text
Furthermore,
I've got 3x Activities, 1 for each table
I've got 3x DBClasses, 1 for each table
I've got 3x DBHandlers, 1 for each table
I've got 3x Adapters, 1 for each table
The idea is that when you open the app and call the class to open the bible, it opens the book class and has a ListView, in the listview is all the bible books, when clicked, it should open the chapter activity and in its ListView display all the book's chapters, when selecting a chapter it should open the verse Activity and in its ListView display all the verses.
So far, the book Activity displays the book names, but when I click on it, it only displays a white screen...
Nothing shows errors in the logcat.
I think I might be messing something up in the way the Activity sends the selected info to the new Activity to open the new ListView?
How should this code look like?
Currently it's like this in the book class:
//Get bible list in db when db exists
DBClassBibledbBookList= DBHelperBook.getListBible();
//Init adapter
adapter_customAdapterBooktext = new customAdapterBooktext(this, DBClassBibledbBookList);
//Set adapter for listview
listviewBible.setAdapter(adapter_customAdapterBooktext);
#Override
public void onItemClick (AdapterView<?> arg0, View view, int arg2, long arg3){
//on selecting a book
//BookActivity will be launched to show chapters inside
Intent bookid = new Intent (getApplicationContext(), ChapterActivity.class);
//send book_id to ChapterActivity to get chapters under that book
String book_id = ((TextView)view.findViewById(R.id.book_id)).getText().toString();
bookid.putExtra("book_id", book_id);
startActivity(bookid );
}
}
);
And in the chapter Activity:
//Get bible list in db when db exists
DBClassBibledbChapterList = DBHelperChapter.getListChapter();
//Init adapter
adapter_customAdapterChaptertext = new customAdapterChaptertext (this,DBClassBibledbChapterList );
//Set adapter for listview
listviewChapter.setAdapter(customAdapterChaptertext );
//Get book id
Intent i = getIntent();
book_id = i.getStringExtra("book_id");
//hashmap for listview
ChapterList = new ArrayList<HashMap<String, String>>();
listviewChapter.setOnItemClickListener(new android.widget.AdapterView.OnItemClickListener(){
#Override
public void onItemClick (AdapterView<?> arg0, View view, int arg2, long arg3){
//on selecting chapter get verse text
Intent chapterid = new Intent(getApplicationContext(),BibleActivityVerse.class);
//to get verse both book_id and chapter_id is needed
String book_id = ((TextView) view.findViewById(R.id.book_id)).getText().toString();
String chapter_id = ((TextView)view.findViewById(R.id.chapter_id)).getText().toString();
chapterid.putExtra("book_id", book_id);
chapterid.putExtra("chapter_id", chapter_id);
startActivity(chapterid);
}
});
The DBClass:
public List<DBClassBibledbChapter> getListChapter(){
DBClassBibledbChapter DBClassBibledbChapter = null;
List<DBClassBibledbChapter> DBClassBibledbChapterList = new ArrayList<>();
opendatabase();
Cursor cursor = mDatabase.rawQuery("SELECT * FROM table_chapter", null);
cursor.moveToFirst();
while (!cursor.isAfterLast()){
DBClassBibledbChapter = new DBClassBibledbChapter (cursor.getInt(0), cursor.getInt(1),cursor.getInt(2));
DBClassBibledbChapterList.add(DBClassBibledbChapter);
cursor.moveToNext();
}
cursor.close();
closeDatabase();
return DBClassBibledbChapterList;
Just try to get the book_id from your list of the DBClassBibledbBookList arraylist on the onItemClick listener as below and then pass it to another activity.
Also check you get the correct book id on your ChapterActivity and fetch the list of chapters from the table_chapter based on the book id from your database.
//Set adapter for listview
listviewBible.setAdapter(adapter_customAdapterBooktext);
#Override
public void onItemClick (AdapterView<?> arg0, View view, int arg2, long arg3){
//on selecting a book
//BookActivity will be launched to show chapters inside
Intent bookid = new Intent (getApplicationContext(), ChapterActivity.class);
//send book_id to ChapterActivity to get chapters under that book
String book_id = DBClassBibledbBookList.get(arg2).getbook_id().toString();
bookid.putExtra("book_id", book_id);
startActivity(bookid );
}
});
Check out the String book_id in the above code.
Hope this will help you.
So far, the book activity displays the book names, but when I click on it, it only displays a white screen...
I think I might be messing something up in the way the activity sends the selected info to the new activity to open the new listview? How should this code look like?
You probably want to get the chapters by a certain book, yes?
So, do this
//Get book id
Intent i = getIntent();
book_id = i.getStringExtra("book_id");
Then use that ID to query the database in a way that gets the chapters
//Get bible list in db when db exists
chapterList = DBHelperChapter.getListChapter(book_id);
//Init adapter
chapterAdapter = new customAdapterChaptertext (this, chapterList);
//Set adapter for listview
listviewChapter.setAdapter(chapterAdapter);
Where DBHelperChapter.getListChapter(book_id) could return the results of this query
mDatabase.rawQuery("SELECT * FROM table_chapter WHERE id_of_book = " + book_id);
Sidenote: since you are using a SQLite database, I may suggest trying to look into using a CursorAdapter rather than an ArrayAdapter for loading a ListView
Related
Here is what I am trying to do and would like some advice on the best methods to do it:
have a database that contains a word, and the name of an image file associated with that word.
the words from the database will be displayed in a listview
when the word is selected, a new activity will start displaying the word and the image in an image view.
Would it be best to store the terms in an array and have the list view populate from this array and then pull from the database onitemclick? Or can the list view be populated with the terms from the database?
Will android be able to display the image if the name of the file is stored in the db?
The best way to achieve what you're looking for is to store the term and image path in the DB, then use the path to fetch the image from whatever location you have put it in.
Images can be stored in the DB, but the general consensus is that it is better to store the image outside the DB and a path to said image in the DB.
Your DB can then be as simple as three columns... "_id", "term" and "term_image".
You can do a simple query to fetch all the info at once (thus only querying the DB once).
Then use the cursor returned by that query to populate your list of terms, and onListItemClick to start a new activity to display the associated image using the path from the list that is in the same record as the term from the list.
Query to fetch data:
public Cursor fetchAllTerms() {
return mDb.query(TERMS_TABLE, new String[] { "_id", "term", "term_img" }, null, null, null, null, null);
}
Using it in your list:
mTermCursor = mDbHelper.fetchAllTerms();
getActivity().startManagingCursor(mTermCursor);
String[] from = new String[] { YourDBClass.term };
int[] to = new int[] { android.R.id.Text1 };
SimpleCursorAdapter ranks = new SimpleCursorAdapter(getActivity(),
android.R.layout.simple_list_item_1, mRankCursor, from, to);
setListAdapter(ranks);
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
String imagePath = mTermCursor.getString(mTermCursor.getColumnIndexOrThrow("term");
// code to start your new activity and put the image path into the bundle to be passed
}
I FOUND A SOLUTION FOR RESTORING MY VALUES, SEE MY NEW VERSION of populateFields()
Okay so I have been reading through all the Spinner and SQlite posts on here and cannot seem to find a good answer for what I am looking for so I am posting this scenario.
My app has two screens and uses the sqlite database on my device saving a name and weight fields from editTexts as strings like so
String eName = name.getText().toString();
String eWeight = weight.getText().toString();// where name and weight are EditTexts
and I have two spinners as follows
String eReps = spinReps.getSelectedItem().toString();
String eSets = spinSets.getSelectedItem().toString();
Then I call this to add to the database
long id = mDbHelper.createExercise(eName, eWeight, eReps, eSets);
Here is where my issue is, upon someone selecting to create a new exercise my app crashes because it is trying to populate a spinner incorrectly. Here is what I have currently.
private void populateFields(){
if(mRowId != null){ // where mRowId is the selected row from the list
Cursor exercise = mDbHelper.fetchExercise();
name.setText(exercise.getString(exercise.
getColumnIndexOrThrow(ExerciseDbAdapter.KEY_NAME)));
weight.setText(exercise.getString(exercise.
getColumnIndexOrThrow(ExerciseDbAdapter.KEY_WEIGHT)));
// this is the part that i need help with, I do not know how to restore
// the current items spinner value for reps and sets from the database.
spinReps.setSelection(exercise.getString(exercise.
getColumnIndexOrThrow(ExerciseDbAdapter.KEY_REPS)));
spinSets.setSelection(exercise.getString(exercise.
getColumnIndexOrThrow(ExerciseDbAdapter.KEY_SETS)));
}
I assume I need to use some sort of adapter to restore my list items along with the current value from the database, I am just not sure how.
Can someone please help me with this???
** BELOW IS MY SOLUTION**
I had to move my ArrayAdapters repsAdapter, spinAdapter out of my onCreate()
and then implement this new populateFields()
private void populateFields(){
if(mRowId != null){
Cursor exercise = mDbHelper.fetchExercise(mRowId);
// same as before
name.setText(exercise.getString(exercise.
getColumnIndexOrThrow(ExerciseDbAdapter.KEY_NAME)));
// get the string for sReps and sSets from the database
String sReps = exercise.getString(exercise.
getColumnIndexOrThrow(ExerciseDbAdapter.KEY_REPS));
String sSets = exercise.getString(exercise.
getColumnIndexOrThrow(ExerciseDbAdapter.KEY_SETS));
// use the strings to get their position in my adapters
int r = repsAdapter.getPosition(sReps);
int s = setsAdapter.getPosition(sSets);
// set their returned values to the selected spinner Items
spinReps.setSelection(r);
spinSets.setSelection(s);
// same as before
weight.setText(exercise.getString(exercise.
getColumnIndexOrThrow(ExerciseDbAdapter.KEY_WEIGHT)));
}
}
The way to set a Spinner to a value, not a position, depends on what adapter you are using.
ArrayAdapter, this one is easy:
int position = adapter.getPosition(exercise.getString(exercise.
getColumnIndexOrThrow(ExerciseDbAdapter.KEY_REPS)));
spinReps.setSelection(position);
SimpleCursorAdapter, this one is a little harder:
String match = exercise.getString(exercise.getColumnIndexOrThrow(ExerciseDbAdapter.KEY_REPS));
Cursor cursor = adapter.getCursor();
cursor.moveToPosition(-1);
int columnIndex = cursor.getColumnIndexOrThrow(ExerciseDbAdapter.KEY_REPS);
while(cursor.moveToNext()) {
if(cursor.getString(columnIndex).equals(match))
break;
}
spinReps.setSelection(cursor.getPosition());
If you are using a different type of adapter and can't modify the code above to fit it, let me know. Hope that helps!
I'm trying to open the System SMS application with a sms body that is taken from a database.
I'm using Cursor to retrieve titles and messages from a SQLite database. I have a smsButton which will be clicked. When clicked, it will create the sms intent.
My problem is with the body of the message. I want the body to be the msg_content which is retrieved from the database. I tried to have a reference to it but I believe I failed.
here is my last attempt, trying to have a TextView that will take the id of the msg_content layout :
//First: DataBase Retrieving :
//fetch a msg from table `t` with id `id`
Cursor cursor = myDbHelper.fetchMessage(t, id);
String[] columns = {cursor.getColumnName(1), cursor.getColumnName(2)};
int[] columnsLayouts = {R.id.title, R.id.msg_content}; //the columns styles
ca = new SimpleCursorAdapter(this.getBaseContext(), R.layout.msg_items_layout, cursor,columns , columnsLayouts);
lv = (ListView) findViewById(android.R.id.list);
lv.setAdapter(ca);
//Here is MY PROBLEM :
TextView msgText = (TextView) findViewById(R.id.msg_content); //same Id as the msg_content column above
smsButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
String uri= "smsto:";
Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.parse(uri));
intent.putExtra("sms_body", msgText.getText());
intent.putExtra("compose_mode", true);
startActivity(intent);
}
});
Any way to reference the string of the content ?
You are calling findViewById() on an activity... to get data out of database?
You should be using your Cursor to get at your information.
Since you did not bother to provide the actual source code (just a couple of dis-contiguous snippets, AFAICT), it is difficult to give you concrete advice. Taking a random stab at an answer, I would delete smsButton, and instead listen for ListView item clicks (e.g., onListItemClick() if you are implementing a ListActivity), then use the supplied position to move to the right spot in the Cursor and read out the data.
I am having some trouble implementing a sqlite database in my simple android application:
a user is displayed a list of animals in a Listview.Upon selecting an animal the user is brought to an activity "Animal",which will display a picture of the animal and give them options to
view Animal Bio
Back
All very simple so far, right?
I have working the database, which will populate the listView of animals.Database currently looks like
Table Animal-
_ID,
Name
Table Biography-
_ID,
Bio
This is where I would welcome any helpful advice on my problem, or on how to improve my implementation.
Currently populating the DB as follows
long populateDB(){
String[] animalName = {"Lion" "Zebra", "Tiger", "Gorilla",...};
String[] animalBios = {"Found in the "...}
ContentValues animalNameVals = new ContentValues();
ContentValues animalBioVals = new ContentValues();
long[] rowIds = new long[animalName.length];
// Populate the animal table
for(int i = 0; i < animalName.length; i++){
animalNameVals.put(KEY_ANIMALNAME, animalName[i]);
rowIds[i] = db.insert(ANIMAL_TABLE, null, animalNameVals);
}
// Populate the Bio table
for(int j = 0; j < bios.length; j++){
animalBioVals.put(KEY_BIO, bios[j]);
rowIds[j] = db.insert(BIOS_TABLE, null, animalBioVals);
}
return rowIds[0];
}
And had planned on being able to tell database which animal on list was selected by passing extras with the intent, eg if position on listItemClick == 1, pass in tiger and retrieve tiger bio from db.
Problems:
Then on the Animal activity page is getExtra() == tiger, telling the activity that tiger was selected from the list and to load this bio from the DB..well, I cannot see an efficient method of implementation for this idea and am struggling to do so.
My second headache comes from adding the bio to the application from the Db.Originally I had a test bio hardcoded in a string, shown in a TextView.Is there a way to retrieve a string from a cursor and add it to the TextView id?I understand I will need some adapter, what I do not understand is why cant it be as simple as setResource(R.id.bio) = bio.
Thanks you for reading and any help is much appriciated.
First problem: First of all, I'm not sure why you don't have the column Bio in the Animal-table? As no Bio would fit to any other animal than itself, you can safely do this. By doing this you can query the database upon selection and pass the entire object (including name of animal and bio) to the next Activity and use this to get your information. If this was somewhat unclear, let me know and I'll try to explain it better.
Second problem: You can get values from tables (there of also Strings) using a Cursor. To get the String you can do something like this where cursor is the Cursor with your result from the database:
String bio;
// Move Cursor to its first element
if(cursor.moveToFirst()) {
// Make sure the cursor is not null
if(cursor != null) {
bio = cursor.getString(cursor.getColumnIndex("Bio")));
}
}
Sidenote: If I read the code correctly, it seems that you use long for ID's? The usual thing to go about ID's is integers as far as I know.
I have a query in my android app that pulls all image paths from a custom table and displays them to a gallery. The problem is with my database I cant seem to get a row of the database to a String[]. I can easily get the results to a listArray but I need the image path in a string or string array. I want to be able to click on an image in the gallery and have it pull up full screen to be able to zoom in on it or delete it etc. This is the basic query i use
public void listimages() {
SimpleCursorAdapter adapter;
String[] columns = {"Image", "ImageDate", "_id"};
query = new TableImages(this);
queryString = query.getData("images", columns, null, null, null, null, "ImageDate", "DESC");
int to[] = {R.id._id1, R.id._id2};
adapter = new SimpleCursorAdapter(this, R.layout.imagelist, queryString, columns, to);
Gallery g = (Gallery) findViewById(R.id.gallery);
g.setAdapter(adapter);
g.setOnItemClickListener(this);
try {
query.destroy();
} catch (Throwable e) {
e.printStackTrace();
}
}
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent i = new Intent(ViewAllImages.this, ImageViewer.class);
Bundle b = new Bundle();
//I want to be able to use this -> b.putString("image_path", Image);
b.putlong("id", id);
i.putExtras(b);
startActivity(i);
}
This passes the ID to my next activity and the next activity queries the DB pulling that one image path. I still have to use a listview to display the image which makes the app crash on the phone due to memory usage (image is too large).
I can compress the image but I need the path as a string and I cant figure out how to do that without creating a custom content provider or adding a textview and using gettext.toString and thats just getto. My head is killing me as it is with all the reading and coding I have done lol. I have searched all over Google and different forums but I am having problems finding an answer.
Is there a way to use the existing query and get a string or a string array as the result?
Thanks.
I just ended up building a custom content provider. Now I have alot more flexability in my queries.