I have a callog(displayed in an alert dialog) in an arraylist that has been sorted using an hashmap, any time I try to view this callog it shows just the result of the calllog query but in my logcat it shows the numbers properly sorted. Please how can I append this result in the logcat to the alert dialog? I have been battling with it for days and I can't seem to figure it out.
final List<String> allNumbers = new ArrayList<String>();
public void onClick(View v) {
String[] strFields = { android.provider.CallLog.Calls._ID,
android.provider.CallLog.Calls.NUMBER,
android.provider.CallLog.Calls.CACHED_NAME, };
String strOrder = android.provider.CallLog.Calls.DATE + " DESC LIMIT 10 ";
final Cursor cursorCall = EmergencyButtonActivity.this.getContentResolver().query(
android.provider.CallLog.Calls.CONTENT_URI, strFields,
null, null, strOrder);
this.sortNumber();
while (cursorCall.moveToNext()){
String names = cursorCall.getString(cursorCall.getColumnIndex(android.provider.CallLog.Calls.CACHED_NAME));
allNumbers.add(names)
}
AlertDialog.Builder builder = new AlertDialog.Builder(EmergencyButtonActivity.this);
builder.setTitle("Frequent Contacts");
android.content.DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialogInterface, int item) {
cursorCall.moveToPosition(item);
EditText phoneInput = (EditText) findViewById(R.id.txtPhoneNo);
String selectedNumber =cursorCall.getString(cursorCall.getColumnIndex(android.provider.CallLog.Calls.NUMBER));
selectedNumber = selectedNumber.replace("-", "");
phoneInput.setText(selectedNumber);
Toast.makeText(EmergencyButtonActivity.this, cursorCall.getString(cursorCall.getColumnIndex(android.provider.CallLog.Calls.NUMBER)),
Toast.LENGTH_LONG).show();
cursorCall.close();
}
};
builder.setCursor(cursorCall, listener, android.provider.CallLog.Calls.CACHED_NAME);
builder.create().show();
}
public void sortNumber() {
Map<String, Integer> map = new HashMap<String, Integer>();
for (String temp : allNumbers) {
Integer count = map.get(temp);
map.put(temp, (count == null) ? 1 : count + 1);
}
printMap(map);
}
public static void printMap(Map<String, Integer> map){
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println( entry.getKey() + entry.getValue());
}
}
There is so much wrong with this it is hard to know where to begin :-(
First of all, you cannot "sort" anything using a HashMap. These 2 concepts are mutually exclusive.
Secondly, you have a while loop where you are creating and showing an AlertDialog for each row in your cursor. That can't be right.
Next, you are calling setCursor() on the AlertDialog.Builder and passing the Cursor. The dialog builder is using the data in this Cursor to build the content to be shown in the dialog. The fact that you have "sorted" the data is irrelevant, as you have given the dialog builder the data from your raw query.
Next, your method sortNumber() creates a HashMap and fills it, but this HashMap is a local variable to this method, so after the method returns, the HashMap is gone. You don't return the HashMap from the method, or store it anywhere.
If you really want the data "sorted", you should just add an "ordered by" clause to your query.
You might want to consider returning your HashMap from the sortNumber() method and then building an array of Strings out of that and then calling setItems() on the dialog builder instead of using setCursor().
Related
I have a JSON Array which consists of some contacts in my phonebook who are also users of my app. For example, the JSON Array might look like :
[{"contact_phonenumber":"11111"},{"contact_phonenumber":"22222"},{"contact_phonenumber":"33333"}]
phoneNumberofContact is a string which, in the do statement in my code below, returns every contact in my phone. How can I check which phoneNumberofContact numbers appear in my JSON Array and then, besides those contacts in the ListView put the words '- app user'. My ListView is working fine, I just want to add this feature in.
So, for example, for the number 11111 I would have in my ListView :
Joe Blogs - app user
11111
Here's my code:
JSONArray jsonArrayContacts = response;
//response is something like [{"contact_phonenumber":"11111"}, etc...]
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new_contact);
//selectPhoneContacts is an empty array list that will hold our SelectPhoneContact info
selectPhoneContacts = new ArrayList<SelectPhoneContact>();
listView = (ListView) findViewById(R.id.listviewPhoneContacts);
}
//******for the phone contacts in the listview
// Load data in background
class LoadContact extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... voids) {
// we want to delete the old selectContacts from the listview when the Activity loads
// because it may need to be updated and we want the user to see the updated listview,
// like if the user adds new names and numbers to their phone contacts.
selectPhoneContacts.clear();
// we have this here to avoid cursor errors
if (cursor != null) {
cursor.moveToFirst();
}
try {
// get a handle on the Content Resolver, so we can query the provider,
cursor = getApplicationContext().getContentResolver()
// the table to query
.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
null,
null,
// display in ascending order
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " COLLATE LOCALIZED ASC");
// get the column number of the Contact_ID column, make it an integer.
// I think having it stored as a number makes for faster operations later on.
// get the column number of the DISPLAY_NAME column
int nameIdx = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME);
// get the column number of the NUMBER column
int phoneNumberofContactIdx = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
cursor.moveToFirst();
// We make a new Hashset to hold all our contact_ids, including duplicates, if they come up
Set<String> ids = new HashSet<>();
do {
System.out.println("=====>in while");
// get a handle on the display name, which is a string
name = cursor.getString(nameIdx);
// get a handle on the phone number, which is a string
phoneNumberofContact = cursor.getString(phoneNumberofContactIdx);
//----------------------------------------------------------
// get a handle on the phone number of contact, which is a string. Loop through all the phone numbers
// if our Hashset doesn't already contain the phone number string,
// then add it to the hashset
if (!ids.contains(phoneNumberofContact)) {
ids.add(phoneNumberofContact);
SelectPhoneContact selectContact = new SelectPhoneContact();
selectContact.setName(name);
selectContact.setPhone(phoneNumberofContact);
selectPhoneContacts.add(selectContact);
}
} while (cursor.moveToNext());
} catch (Exception e) {
Toast.makeText(NewContact.this, "what the...", Toast.LENGTH_LONG).show();
e.printStackTrace();
// cursor.close();
} finally {
}
if (cursor != null) {
cursor.close();
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
adapter = new SelectPhoneContactAdapter(selectPhoneContacts, NewContact.this);
// we need to notify the listview that changes may have been made on
// the background thread, doInBackground, like adding or deleting contacts,
// and these changes need to be reflected visibly in the listview. It works
// in conjunction with selectContacts.clear()
adapter.notifyDataSetChanged();
listView.setAdapter(adapter);
}
}
In the first, you can parse the jsonArrayContacts to a List:
final List<String> responseContacts = new ArrayList<String>();
try {
JSONArray responseObject = new JSONArray(response);
for (int i = 0; i < responseObject.length(); i++) {
final JSONObject obj = responseObject.getJSONObject(i);
responseContacts.add(obj.getString("contact_phonenumber"));
}
// System.out.println("the matching contacts of this user are :" + responseContacts);
} catch(Exception e) {
e.printStackTrace();
}
after you get your local contacts, then you have two sets of contacts, so it's easy to check which number appears in your json array contacts.
And then you can pass the responseContacts into SelectPhoneContactAdapter during you initialize it, and in getView() method of the adapter, you can know whether you need to put the words '- app user' to your item view or not.
I have a ListView with each row containing a TextView. On user click, I'm getting the value of the TextView and storing it in a String variable, and the user is navigated to another activity where he / she needs to input some data on said TextView. In order to not lose the information state of the first activity, I had to use startActivityForResult() and later get the information from the second activity with the method onActivityResult().
The problem is this: I need to compare a value with that of the TextView in question, however the String variable which supposedly contains the TextView's value is null.
Before starting up the second activity I toasted the String value and it returned the correct string, however not in the onActivityResult(), where it returns null.
Why is this happening? Isn't the Intent I used suppose to retain all information of the opened activity?
ListView's onItemClick
#Override
public void onItemClick(AdapterView<?> listView, View itemView, int itemPosition, long itemID)
{
clickedError = ((TextView)itemView).getText().toString();
String errorIDQuery = "SELECT _id FROM " + TABLE_ERROR + " WHERE error_description LIKE '" + clickedError + "';";
Cursor getErrorID = db.rawQuery(errorIDQuery, null);
getErrorID.moveToFirst();
errorID = getErrorID.getInt(0);
Intent intent = new Intent(Repair.this, Material.class);
intent.putStringArrayListExtra("materialList", materialList);
startActivityForResult(intent, 1);
Toast.makeText(getApplicationContext(), clickedError, Toast.LENGTH_LONG).show();
}
onActivityResult
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
if(resultCode == RESULT_OK)
{
#SuppressWarnings("unchecked")
HashMap <String, String> materialDetails = (HashMap <String, String>)data.getSerializableExtra("map");
Set<?> set = materialDetails.entrySet();
Iterator<?> i = set.iterator();
ArrayList<String> materialNames = new ArrayList<String>();
ArrayList<String> materialAmounts = new ArrayList<String>();
do
{
#SuppressWarnings("rawtypes")
Map.Entry me = (Map.Entry)i.next();
materialNames.add(me.getKey().toString());
materialAmounts.add(me.getValue().toString());
}
while (i.hasNext());
for(Error e : errorList)
{
// ----- COMPARING THE VALUES -----
// here clickedError is null
if(e.description.equals(clickedError))
{
for(int j = 0; j < materialNames.size(); j++)
{
MaterialClass mc = new MaterialClass();
mc.setName(materialNames.get(j));
mc.setAmount(Integer.parseInt(materialAmounts.get(j)));
e.materialList.add(mc);
}
if (e.materialList.size() != 0)
e.checked = true;
else
e.checked = false;
}
}
My guess: the activity is destroyed and restarted while moving to the second activity. This is easy to confirm with log messages in the activity life cycle methods(onCreate/onRestart/etc).
The following link might be of use to persist data during activity switching: http://developer.android.com/training/basics/activity-lifecycle/recreating.html
Make your String value as static so that it will retain its value. or you can use shared preference to save value and use it later.
This is working if its not ask me
TextView textviewDate=(TextView)findViewById(R.id.yourtextviewid);
clickedError=textviewDate.getText().toString();
I am writing an android app in that main activity starts and populates a list of contacts, and needs to prompt the user for today's rating of all the contacts(promptUserForInput) and immediately process received rating of all the contacts. I thought i can use a dialogue box that prompt for every contact and gets the rating from the user. But below code fails as the main thread is not waiting for the user to finish enter rating of all the users.
Here is my function which I am calling in the main activity in a do while loop for all the contact names. rating is a global variable.
double rating=0;
private synchronized void promptUserForInput(String firstName, String lastName) {
final String fname = firstName;
final String lName = lastName;
AlertDialog.Builder alert = new AlertDialog.Builder(this);
String custName = firstName + " " + lastName;
final EditText input = new EditText(this);
alert.setTitle(custName);
alert.setView(input);
Log.v("Diva: in promptUserForInput", "setting positive buton");
alert.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface arg0, int arg1) {
Editable res = input.getText();
if(res == null) {
Log.v("Diva..", "In positivebutton..befoer getting rating res is null");
}
rating = Double.valueOf(input.getText().toString());
}
});
alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
rating=0;
}
});
alert.show();
}
My caller of this promptUserForInput() looks like below.
// get list of contacts in a cursor
Cursor cursor = ManageDataBaseActivity.queryDataBase(this,
ManageDataBaseActivity.CONTACT_INFO_TABLE);
if(cursor.getCount()>0) {
double totalRatingForStats=0;
cursor.moveToFirst();
do {
String[] colNames = cursor.getColumnNames();
Log.v("Diva Colum names = ", colNames[0] + " " + colNames[1] + " " + colNames[2] + " " + colNames[3]);
String firstName = cursor.getString(cursor.getColumnIndex("FirstName"));
Log.v("Diva ..:", firstName);
String lastName = cursor.getString(cursor.getColumnIndex("LastName"));
String key = ManageDataBaseActivity.getDbKey(firstName, lastName,
date, ManageDataBaseActivity.CUSTOMER_DATA_TABLE);
promptUserForInput(firstName, lastName);
double ratingReceived = rating;
totalRatingForStats = totalRatingForStats+ratingReceived;
// some more processing
ManageDataBaseActivity.insertValueToDB(ManageDataBaseActivity.
CONTACT_DATA_TABLE+" ", .....);
} while(cursor.moveToNext());
The short answer: Don't.
The long answer: You should never block the main thread of a GUI program while waiting for user input.
Instead you should provide a continue button, which fires a event which causes the program to continue. There are several ways to accomplish this, the one that comes to mind first is signals and semaphores.
I'm not that well versed in Android programming - but there should be something similar in the API, perhaps dependent on Intents.
Looping in the main thread of an Activity is generally not a very good idea. But you could implement something like a pollNext() method that gets the next dataset from the cursor and change your click-methods to this:
#Override
public void onClick(DialogInterface dialog, int which) {
// do your rating stuff
// reads the next dataset
pollNext();
// shows the next dialog
// of course, firstName and lastName must be membervariables to make this work
promptUserForInput(firstName, lastName);
}
The idea behind that is very common and also used in the MVC-pattern
Hoping someone might be able to shine a little light on this for me to help out. I have a EditText field where a user will input a serial number and or reference number, then hit the load Button.
http://i.stack.imgur.com/95iWI.png
I made a method to check and see if that number has already been added to the Database. If it hasn't then i have a Yes/No dialog that pops up asking if they want to add to the database. Then if it is in the DB it will load that number's data into the four TextViews.
http://i.stack.imgur.com/dHbCQ.png
If they select yes then it runs the new intent, switching to the form screen(haven't yet looked into passing the user input to another class yet). but to get back on to my little issue, when testing this in the emulator everything runs fine. Then when i enter a number that i already entered in it still opens the dialog, (i have it in a if statement).
Load button code
String s = input.getText().toString();
int l = Integer.parseInt(s);
Db load = new Db(this);
load.open();
y = load.dbCheck(l);
if (y != 0) {
DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog,int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
Intent i = new Intent("android.intent.action.FORM");
startActivity(i);
break;
case DialogInterface.BUTTON_NEGATIVE:
break;
}
}
};
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Would you like to add to Database?")
.setTitle("Not in Database:")
.setPositiveButton("Yes", dialogClickListener)
.setNegativeButton("No", dialogClickListener)
.show();
}
else
{
final Dialog dbentery = new Dialog(this);
dbentery.setTitle("Entry Exists!");
TextView tv = new TextView(this);
tv.setText("The serial number you have entered is already in database");
dbentery.setContentView(tv);
dbentery.show();
final Timer t = new Timer();
t.schedule(new TimerTask() {
public void run() {
dbentery.dismiss();
t.cancel();
}
}, 2000);
}
load.close();
Now with the method i created I thought I had it right, but something just isn't working. I have it returning a integer back to the load button code where the if statement uses wither 0 or 1 to validate if it is in the DB and what it should do. I figured since it is running the Dialog that it is returning 0, that it might be with the cursor. I looked at a few other posts on here that were similar but didn't seem to help me and or i wasn't comprehending what was being done. So here's the checking method in my DBHelper class
/* this is to check to see if entry is in db or not */
public int dbCheck(int l) throws SQLException {
String[] cols = new String[] { KEY_ROWID, KEY_ONE, KEY_TWO, KEY_THREE, KEY_FOUR };
Cursor c = ourDB.query(KEY_TABLE, cols, KEY_ONE + "=" + l, null,
null, null, null);
if (c == null) {
return 0;
}else {
return 1;
}
}
this might be a simple fix, but I'm not seeing it... thanks for any help or insight to what i might be doing wrong
c == null if the query throws an error, otherwise c != null, but c.getCount == 0
public int dbCheck(int l) throws SQLException {
String[] cols = new String[] { KEY_ROWID, KEY_ONE, KEY_TWO, KEY_THREE, KEY_FOUR };
Cursor c = ourDB.query(KEY_TABLE, cols, KEY_ONE + "=" + l, null,
null, null, null);
if (c == null) {
return 0;
}else {
return c.getCount() == 0 ? 0:1;
}
}
First, rewrite dbCheck() to return boolean, not int. No point in having an int if you only return two values, waste of space.
Second, rewrite your query. There is no point in selecting all those columns if you only filter on one of them, and then throw the result away. Rewrite it into this:
String s = String.format("SELECT count(*) FROM %s WHERE %s = %d",
KEY_TABLE, KEY_ONE, l);
Cursor c = ourDB.rawQuery(s, null);
c.moveToFirst();
return (c.getInt(0) > 0); // returns a boolean
This will cut down the number of quirks you have in your code, and it will help you debug it easier.
EDIT: corrected query() into rawQuery().
I'm using an AutoCompleteText for searching a location which would be connected to the database and the result would be shown. everything works fine when the inputed text is what is on the autocomplete list. But when i tried to input with a different text, which isnt available on the database, the application will get a force close.
here is my code
DataSPBU helper = new DataSPBU(this);
database = helper.getWritableDatabase();
Cursor dbCursor = database.query(TABLE_NAME, new String[] {SPBU, Alamat, JenisBensin, FasilitasUmum}, Alamat + "=?",new String[] {lokasi}, null, null, null);
if(dbCursor.moveToPosition(0)) {
String namaSpbu = dbCursor.getString(0);
String alamatSpbu = dbCursor.getString(1);
String jenisSpbu = dbCursor.getString(2);
String fasilitasSpbu = dbCursor.getString(3);
namaSpbuEdit.setText(namaSpbu);
alamatEdit.setText(alamatSpbu);
jenisBensinEdit.setText(jenisSpbu);
fasilitasEdit.setText(fasilitasSpbu);
}
else {
notFoundDialog = new AlertDialog.Builder(this)
.setTitle("RESULT NOT FOUND")
.setMessage("Hasil Tidak Ditemukan")
.setNegativeButton("close", new AlertDialog.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
})
.create();
notFoundDialog.show();
}
//
any help would be highly appreciated.
Hey man when ever you enter a new text first enter into database after fetch the data,
then the application does not force close .and the data also shown in autocomplete text view
code::
String s=Edittext.getText().toString();
db.insert(s);
after bind the data with your resource