I am working on a project with 2 other people, and as you can probably guess its a bit tought working with someone elses code. The app we are developing gets info from the internet, each item consisting of a title, link, post, and date. This info is read into a cursor and then output all in a single string buffer. This is obviously useless if you want to display the info neatly in an emulator window. I was hoping someone could help me understand how to work with the info to make it easy to use (i.e. each entry in one TextView, with all entries in a listview).
private void showEvents() {
SQLiteDatabase db = post.getWritableDatabase();
Cursor cursor= db.rawQuery("SELECT "+TITLE+", "+LINK+", "+POST+", "+DATE+" FROM "+TABLE_NAME+" "+"ORDER BY "+DATE+" DESC;",null);
startManagingCursor(cursor);
TextView tv = new TextView(this);
// Stuff them all into a big string
StringBuilder builder = new StringBuilder("");
while (cursor.moveToNext()) {
String title = cursor.getString(0);
String link = cursor.getString(1);
String post = cursor.getString(2);
String date= cursor.getString(3);
builder.append(title).append(": " );
builder.append(link).append(": " );
builder.append(post).append(": " );
builder.append(date).append("\n" );
}
// Display on the screen
tv.setText(builder);
this.setContentView(tv);
}
This code basically just outputs everything, unformmatted onto the screen. I've been trying to figure how to enter the while loop to capture each entity (which is 1 of title, link,post,date) and go from there.
Any advice is appreciated.
I'd suggest you read a book. One that will cover these topics is "Android in Practice", from Manning Publications.
There are several important required elements for this, but the key concept is an "Adapter", which connects views with data. You would end up defining a POJO to represent the data in each record, and your custom Adapter maps from that POJO into view fields.
Every time you enter this while loop, you are reading another line (because of the moveToNext())
while (cursor.moveToNext()) {
String title = cursor.getString(0);
String link = cursor.getString(1);
String post = cursor.getString(2);
String date= cursor.getString(3);
builder.append(title).append(": " );
builder.append(link).append(": " );
builder.append(post).append(": " );
builder.append(date).append("\n" );
}
Related
I have a music application and its worked perfectly up until now.
I have more than 1000 songs inside my SD card. Which gets displayed inside a recycler view.
Before I didn't need the album art for a particular song but now I want to make my app a bit better and I found a way to get album art for every song.
What I tried:
ContentResolver contentResolver=getContentResolver();
Uri musicUri= MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
Cursor cursor=contentResolver.query(musicUri,null,MediaStore.Audio.Media.IS_MUSIC + "=1",null,null);
if(cursor!=null && cursor.moveToFirst()){
int titleColumn = cursor.getColumnIndex(MediaStore.Audio.Media.TITLE);
int artistColumn = cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST);
int idColumn = cursor.getColumnIndex(MediaStore.Audio.Media._ID);
int imgSrcColumn = cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID);
do {
long thisID = cursor.getLong(idColumn);
String thisTitle = cursor.getString(titleColumn);
String thisArtist = cursor.getString(artistColumn);
long thisImg = cursor.getLong(imgSrcColumn);
Cursor cursorx = contentResolver.query(MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI,
new String[] {MediaStore.Audio.Albums._ID, MediaStore.Audio.Albums.ALBUM_ART},
MediaStore.Audio.Albums._ID+ "=?",
new String[] {String.valueOf(thisImg)},
null);
try {
if (cursorx.moveToFirst()) {
String path = cursorx.getString(cursorx.getColumnIndex(MediaStore.Audio.Albums.ALBUM_ART));
this.songs.add(new Song(thisID, thisTitle, thisImg,thisArtist,path));
}
cursorx.close();
}
catch (NullPointerException e)
{
e.printStackTrace();
}
} while (cursor.moveToNext());
Now this thing works and I get the result as expected but this takes too much time for my app to load the songs i.e. the song list.
I think other music player very much do the same but their loading time is way less. Like if I say play music, it takes about 2-3 seconds at max. Mine takes about 10-12 seconds, even more so.
Maybe it's because I am querying my SD card every time I need the album art.
Cursor cursorx = contentResolver.query(MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI,
new String[] {MediaStore.Audio.Albums._ID, MediaStore.Audio.Albums.ALBUM_ART},
MediaStore.Audio.Albums._ID+ "=?",
new String[] {String.valueOf(thisImg)},
null);
Any way to store the results and then loop through it? Like we do in php or any other language, get the results once from the DB and then loop through it. Instead of calling it every time.
Any better method is appreciated too!
P.s: Before using this thing ,app had the load time of 1 seconds at max.
I am stuck with a problem in which some contacts contain a country code while others don't.
I have code for fetching contact numbers which are being saved in list. The list looks like this:
[9999999999, 91-8888888888, 91-0000000000, 1111111111]
Now, I want to remove country code from those numbers which have it. I can't figure out a way to check this.
Here is my code for fetching contacts:
ContentResolver cr = getApplicationContext().getContentResolver(); //Activity/Application android.content.Context
Cursor cursor = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, "UPPER(" + ContactsContract.Contacts.DISPLAY_NAME + ") ASC");
if(cursor.moveToFirst())
{
do
{
String id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
if(Integer.parseInt(cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0)
{
Cursor pCur = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = ?",new String[]{ id }, null);
while (pCur.moveToNext())
{
String contactName = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME_PRIMARY));
String contactNumber = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
allContacts.add(contactName);
contactNumber = contactNumber.replaceAll("\\s+","");
allnumbers.add(contactNumber);
break;
}
pCur.close();
}
} while (cursor.moveToNext()) ;
}
}
Here, allnumbers contains the number (where some have country code with them and others don't). How can I remove the country code from those who have it?
Any help or keywords to search will be appreciated, thanks.
If you want to remove the first occurance of a string containing '91-', you could simply use the replaceFirst() method. So your code will end up like this:
contactNumber.replaceAll("\\s+","").replaceFirst("91-","");
If you want to check if a string starts with '91-', you could use this:
if (contactNumber.startsWith("91-")) {
}
In your sample with array of numbers you have dash(-) between countrycode. So you can just use indexOf to determine if number has country code. You can do the same thing using regexp([\d]+-[\d]+)
Also you can count degits. Usually numbers without country codes have only 10 digits. It depends on your situation
Just try
contactNumber = contactNumber.replace("+91", "");
Hope this helps...
I wish to have a auto-complete text-box which comes up with the users contact names. My code is as follows.
private void getContactNames()
{
Cursor cursor = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,null,null,null,null);
_contactAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_dropdown_item_1line);
while (cursor.moveToNext())
{
int nameIdx = cursor.getColumnIndex(ContactsContract.PhoneLookup.DISPLAY_NAME);
String tmp = cursor.getString(nameIdx);
_contactAdapter.add(tmp);
}
}
Setting the adapter:
AutoCompleteTextView contactName = (AutoCompleteTextView) findViewById(R.id.contactName);
contactName.setAdapter(_contactAdapter);
When I do this, the adapter has all the contact names in there (238 contacts). However, when I start typing into the text box, the auto complete does not show.
Funny, as when I test it out doing this:
String[] ab = new String[] {"aaaaa", "bbbbb"};
_contactAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_dropdown_item_1line,ab);
it will show "aaaaa" and "bbbbb" when typing in to the text box.
Any ideas?
Thanks,
Tom
*EDIT
Just thought I would follow up. It does seem to be the sheer amount of contacts that is preventing it from appearing. Any way to get around this?
while (cursor.moveToNext())
{
int nameIdx = cursor.getColumnIndex(ContactsContract.PhoneLookup.DISPLAY_NAME);
String tmp = cursor.getString(nameIdx);
//_contactAdapter.add(tmp);
// get all names in a new arraylist and then assign it to
arrayList.add(tmp);
}
and then assign it to your adapter as
_contactAdapter = new ArrayAdapter<String> this,android.R.layout.simple_dropdown_item_1line, arrayList);
my code here is horribly wrong, and i'm not sure how you would properly do this. i have a Spinner which is populated from a SQLite database query through a CursorAdapter. i need to get the text (value) of the currently selected item. i tried this garbage:
((Cursor)prdSpn.getItemAtPosition(prdSpn.getSelectedItemPosition())).getString(prdSpn.getSelectedItemPosition())
to get the text, but it crashes every time. what's the proper way to do this? here's some additional code that may be relevant:
/// qc defined above as a SimpleCursorAdapter
/////////setup product selection spinner from db
prdSpn = (Spinner)findViewById(R.id.prd_spn);
Cursor prdCur = null;
try {
prdCur = mDb.query(smsDbSchema.ProductSchema.TABLE_NAME, null, null, null, null, null, null);
} catch(Exception e) {
Log.e("smsdb", e.toString());
}
prdCur.moveToFirst();
startManagingCursor(prdCur);
qc = new SimpleCursorAdapter(
this,
android.R.layout.simple_spinner_item,
prdCur,
new String[] {smsDbSchema.ProductSchema.COLUMN_NAME},
new int[] {android.R.id.text1}
);
qc.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
prdSpn.setAdapter(qc);
Code similar to the following works for me...
Cursor theCursor = qc.getCursor();
String theString = theCursor.getString(theCursor.getColumnIndex(<your column name here>));
EDIT by moonlightcheese:
implementation:
Cursor theCursor = (Cursor)prdSpn.getSelectedItem();
Log.e("spnERRtest", "Item: " + theCursor.getString(theCursor.getColumnIndex(smsDbSchema.ProductSchema.COLUMN_NAME)));
//theCursor.getString(theCursor.getColumnIndex(smsDbSchema.ProductSchema.COLUMN_NAME)).contains("CAR")
((Cursor)prdSpn.getItemAtPosition(prdSpn.getSelectedItemPosition())).getString(prdSpn.getSelectedItemPosition())
I'm unclear why you are passing getSelectedItemPosition() to getString(). Shouldn't you pass the column number of the column that has the data you want? Isn't this column unrelated to the row that was selected in the spinner?
I'm new to java and I'm trying to run a method once a button is clicked and I am unsure if I'm on the right track. I am selecting 10 questions from a Sqlite database and would like to cycle through each question 0-9 everytime the button is clicked. Once all 10 questions are asked I will move to another activity. I have the app displaying the first question fine but I am having trouble calling the showQuestions method and increasing the questionNum int by one when the button is clicked and passing this onto the method. Any help would be appreciated!
This is the showQuestions method which I am trying to call.
public void showQuestions(Cursor cursor) {
cursor.moveToPosition(questionNum);
while (cursor.moveToNext()) {
// Collect String Values from Query
StringBuilder questiontxt = new StringBuilder("");
StringBuilder answertxt1 = new StringBuilder("");
StringBuilder answertxt2 = new StringBuilder("");
StringBuilder answertxt3 = new StringBuilder("");
StringBuilder answertxt4 = new StringBuilder("");
String question = cursor.getString(2);
String answer = cursor.getString(3);
String option1 = cursor.getString(4);
String option2 = cursor.getString(5);
String option3 = cursor.getString(6);
questiontxt.append(question).append("");
answertxt1.append(answer).append("");
answertxt2.append(option1).append("");
answertxt3.append(option2).append("");
answertxt4.append(option3).append("");
}
}
This is the code for the button which I am working on. There are 4 buttons.
public void onClick(View v) {
switch (v.getId()) {
case R.id.option1_button:
if (questionNum<9) {
questionNum ++;
}
Questions.this.showQuestions(null);
break;
}
And this is the XML code for the buttons.
<Button
android:id="#+id/option1_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="#+id/option3_button"/>
OnClick Listener for the button
View option1_button = findViewById(R.id.option1_button);
option1_button.setOnClickListener(this);
Database Query and Allocation to Cursor
//Get the questions and allocate them to the Cursor
public Cursor getQuestions() {
//Select Query
String loadQuestions = "SELECT * FROM questionlist ORDER BY QID LIMIT 10";
SQLiteDatabase db = questions.getReadableDatabase();
Cursor cursor = db.rawQuery(loadQuestions, null);
startManagingCursor(cursor);
return cursor;
}
Thanks in advance.
Questions.this.showQuestions(null);
Why you pass null to the showQuestions method?
Let me guess - it crashes with NullPointerException.
Did you tried
showQuestions(getQuestions())
EDIT:
Some general suggestions:
don't load the question every time when the button is clicked.
make some Question class containing all needed information for a question
when onCreate is invoked, open the database and load all needed questions in some Collection, like ArrayList<Question>
Every time when the user clicks a button, get the next Question element from the Collection and show it