How to prompt user for text input in a loop? - android

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

Related

Hashmap values not appended to Alertdialog

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().

How do I separate a country code from a phone number in Android?

I have an XML list of country codes and their corresponding countries ready to use, but first I need to separate them from the phone numbers. Is there an easy way to do this in the Android API?
I've used ridsatrio's answer with an older question here
I'm getting the country code out of the string array below it with the following class:
import android.widget.TextView;
/**
* Created by Friso on 14/11/21.
*/
public final class PhoneFunctions {
private static PhoneFunctions instance;
private PhoneFunctions(){}
public static PhoneFunctions getInstance() {
if (instance == null) {
instance = new PhoneFunctions();
}
return instance;
}
public String getCountry(String[] argStringArray, TextView argText){
String country="";
if (argText.getText().toString().length() >= 4){
for(int i=0;i<argStringArray.length;i++){
String[] g=argStringArray[i].split(",");
if(g[0].equals(getFirstFourChar(argText))){
country=g[1];
break;
}
if (g[0].equals(getFirstThreeChar(argText))){
country=g[1];
break;
}
if (g[0].equals(getFirstTwoChar(argText))){
country=g[1];
break;
}
}
}
return country;
}
public String getFirstFourChar(TextView argText){
String threeChar;
String text = argText.getText().toString();
threeChar = text.substring(0,4);
return threeChar;
}
public String getFirstThreeChar(TextView argText){
String twoChar;
String text = argText.getText().toString();
twoChar = text.substring(0,3);
return twoChar;
}
public String getFirstTwoChar(TextView argText){
String oneChar;
String text = argText.getText().toString();
oneChar = text.substring(0,2);
return oneChar;
}
}
The country codes consist of 1-3 numbers and because this app had to have + string at the beginning of the phone number I thought it faster to just add a + to codes in the string array that I'm comparing to instead of adding more code to separate the +.
<string-array name="CountryCodes" >
<item>+93,AF</item>
<item>+355,AL</item>
<item>+213,DZ</item>
<item>+376,AD</item>
<item>+244,AO</item>
<item>+672,AQ</item>
<item>+54,AR</item>
<item>+374,AM</item>
<item>+297,AW</item>
<item>+61,AU</item>
<item>+43,AT</item>
<item>+994,AZ</item>
<item>+973,BH</item>
<item>+880,BD</item>
<item>+375,BY</item>
<item>+32,BE</item>
<item>+501,BZ</item>
<item>+229,BJ</item>
<item>+975,BT</item>
<item>+591,BO</item>
<item>+387,BA</item>
<item>+267,BW</item>
<item>+55,BR</item>
<item>+673,BN</item>
<item>+359,BG</item>
<item>+226,BF</item>
<item>+95,MM</item>
<item>+257,BI</item>
<item>+855,KH</item>
<item>+237,CM</item>
<item>+1,CA</item>
<item>+238,CV</item>
<item>+236,CF</item>
<item>+235,TD</item>
<item>+56,CL</item>
<item>+86,CN</item>
<item>+61,CX</item>
<item>+61,CC</item>
<item>+57,CO</item>
<item>+269,KM</item>
<item>+242,CG</item>
<item>+243,CD</item>
<item>+682,CK</item>
<item>+506,CR</item>
<item>+385,HR</item>
<item>+53,CU</item>
<item>+357,CY</item>
<item>+420,CZ</item>
<item>+45,DK</item>
<item>+253,DJ</item>
<item>+670,TL</item>
<item>+593,EC</item>
<item>+20,EG</item>
<item>+503,SV</item>
<item>+240,GQ</item>
<item>+291,ER</item>
<item>+372,EE</item>
<item>+251,ET</item>
<item>+500,FK</item>
<item>+298,FO</item>
<item>+679,FJ</item>
<item>+358,FI</item>
<item>+33,FR</item>
<item>+689,PF</item>
<item>+241,GA</item>
<item>+220,GM</item>
<item>+995,GE</item>
<item>+49,DE</item>
<item>+233,GH</item>
<item>+350,GI</item>
<item>+30,GR</item>
<item>+299,GL</item>
<item>+502,GT</item>
<item>+224,GN</item>
<item>+245,GW</item>
<item>+592,GY</item>
<item>+509,HT</item>
<item>+504,HN</item>
<item>+852,HK</item>
<item>+36,HU</item>
<item>+91,IN</item>
<item>+62,ID</item>
<item>+98,IR</item>
<item>+964,IQ</item>
<item>+353,IE</item>
<item>+44,IM</item>
<item>+972,IL</item>
<item>+39,IT</item>
<item>+225,CI</item>
<item>+81,JP</item>
<item>+962,JO</item>
<item>+7,KZ</item>
<item>+254,KE</item>
<item>+686,KI</item>
<item>+965,KW</item>
<item>+996,KG</item>
<item>+856,LA</item>
<item>+371,LV</item>
<item>+961,LB</item>
<item>+266,LS</item>
<item>+231,LR</item>
<item>+218,LY</item>
<item>+423,LI</item>
<item>+370,LT</item>
<item>+352,LU</item>
<item>+853,MO</item>
<item>+389,MK</item>
<item>+261,MG</item>
<item>+265,MW</item>
<item>+60,MY</item>
<item>+960,MV</item>
<item>+223,ML</item>
<item>+356,MT</item>
<item>+692,MH</item>
<item>+222,MR</item>
<item>+230,MU</item>
<item>+262,YT</item>
<item>+52,MX</item>
<item>+691,FM</item>
<item>+373,MD</item>
<item>+377,MC</item>
<item>+976,MN</item>
<item>+382,ME</item>
<item>+212,MA</item>
<item>+258,MZ</item>
<item>+264,NA</item>
<item>+674,NR</item>
<item>+977,NP</item>
<item>+31,NL</item>
<item>+599,AN</item>
<item>+687,NC</item>
<item>+64,NZ</item>
<item>+505,NI</item>
<item>+227,NE</item>
<item>+234,NG</item>
<item>+683,NU</item>
<item>+850,KP</item>
<item>+47,NO</item>
<item>+968,OM</item>
<item>+92,PK</item>
<item>+680,PW</item>
<item>+507,PA</item>
<item>+675,PG</item>
<item>+595,PY</item>
<item>+51,PE</item>
<item>+63,PH</item>
<item>+870,PN</item>
<item>+48,PL</item>
<item>+351,PT</item>
<item>+1,PR</item>
<item>+974,QA</item>
<item>+40,RO</item>
<item>+7,RU</item>
<item>+250,RW</item>
<item>+590,BL</item>
<item>+685,WS</item>
<item>+378,SM</item>
<item>+239,ST</item>
<item>+966,SA</item>
<item>+221,SN</item>
<item>+381,RS</item>
<item>+248,SC</item>
<item>+232,SL</item>
<item>+65,SG</item>
<item>+421,SK</item>
<item>+386,SI</item>
<item>+677,SB</item>
<item>+252,SO</item>
<item>+27,ZA</item>
<item>+82,KR</item>
<item>+34,ES</item>
<item>+94,LK</item>
<item>+290,SH</item>
<item>+508,PM</item>
<item>+249,SD</item>
<item>+597,SR</item>
<item>+268,SZ</item>
<item>+46,SE</item>
<item>+41,CH</item>
<item>+963,SY</item>
<item>+886,TW</item>
<item>+992,TJ</item>
<item>+255,TZ</item>
<item>+66,TH</item>
<item>+228,TG</item>
<item>+690,TK</item>
<item>+676,TO</item>
<item>+216,TN</item>
<item>+90,TR</item>
<item>+993,TM</item>
<item>+688,TV</item>
<item>+971,AE</item>
<item>+256,UG</item>
<item>+44,GB</item>
<item>+380,UA</item>
<item>+598,UY</item>
<item>+1,US</item>
<item>+998,UZ</item>
<item>+678,VU</item>
<item>+39,VA</item>
<item>+58,VE</item>
<item>+84,VN</item>
<item>+681,WF</item>
<item>+967,YE</item>
<item>+260,ZM</item>
<item>+263,ZW</item>
</string-array>
Java's String.substring() might be useful for this use-case:
yourString.substring(int beginIndex, int endIndex);
You might have to take out the XML list first, substring the first 3 numbers of your user's input, then compare it with the list's entries.
Please checkout libphonenumber; https://code.google.com/p/libphonenumber/.
This is Google's common Java, C++ and Javascript library for parsing, formatting, storing and validating international phone numbers. The Java version is optimized for running on smartphones, and is used by the Android framework since 4.0 (Ice Cream Sandwich).
you can split your mobile number by checking is started with "+" sign and Phone number should have length 10.
void splitMobilenumberMethod(){
String phoneNumb = MOBILE_NUMBER_TO_SPLIT;
String ext = "", phoneN = "";
if (phoneNumb.startsWith("+") || phoneNumb.length() > 10) {
ext=phoneNumb.substring(0, 3);
phoneN=phoneNumb.substring(3);
} else {
ext = "";
phoneN = phoneNumb;
}
showSelectedPhoneDialog(ext, phoneN);
}
void showSelectedPhoneDialog(String ext, String phone) {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(context);
alertDialog.setTitle("Verify Phone Number");
LinearLayout layout = new LinearLayout(context);
layout.setOrientation(LinearLayout.HORIZONTAL);
layout.setGravity(View.TEXT_ALIGNMENT_CENTER);
final EditText extEdit = new EditText(context);
final EditText phoneEdit = new EditText(context);
extEdit.setHint("Country");
phoneEdit.setHint("Mobile Number");
layout.addView(extEdit);
layout.addView(phoneEdit);
extEdit.setText(ext);
phoneEdit.setText(phone);
alertDialog.setView(layout);
alertDialog.setIcon(R.drawable.ic_message);
alertDialog.setPositiveButton("Done", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// do if split is correct or after make it corrent manually by user
}
});
alertDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
alertDialog.show();
}

SQLite Update Not Applying Android

When I click on a ListItem, it opens up a custom dialog with 4 EditText fields. The fields are set with current data depending on the row that is clicked. The purpose of the dialog is to allow the user to update the data (it is a financial app). I am having trouble actually applying the update when the user clicks "submit" in the dialog. There are no errors in the app when I run. Here is the onclick method:
protected void onListItemClick(ListView l, View v, int position, long id) {
List<Debt> values = datasource.getAllDebt();
Debt item = values.get(position);
final long boxId = item.getId();
// final String BoxId = String.valueOf(boxId);
final String BoxName = item.getName();
final String BoxBalance = item.getBalance();
final String BoxApr = item.getApr();
final String BoxPayment = item.getPayment();
// set up dialog
final Dialog dialog = new Dialog(manageDebts.this);
dialog.setContentView(R.layout.custom_dialog);
dialog.setTitle("Edit Debt Details");
dialog.setCancelable(true);
// set up text
EditText et1 = (EditText) dialog.findViewById(R.id.editText1);
EditText et2 = (EditText) dialog.findViewById(R.id.editText2);
EditText et3 = (EditText) dialog.findViewById(R.id.editText3);
EditText et4 = (EditText) dialog.findViewById(R.id.editText4);
et1.setText(BoxName);
et2.setText(BoxBalance);
et3.setText(BoxApr);
et4.setText(BoxPayment);
// set up button
Button button = (Button) dialog.findViewById(R.id.button1);
button.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
datasource.updateDebt(boxId, BoxName, BoxBalance, BoxApr,
BoxPayment);
dialog.dismiss();
}
});
dialog.show();
}
The Update Method in my Database helper class is shown here:
public boolean updateDebt(long updateId, String debt_name, String debt_total, String apr, String payment)
{
ContentValues values = new ContentValues();
values.put(MySQLiteHelper.COLUMN_ID, updateId);
values.put(MySQLiteHelper.COLUMN_DEBT_NAME, debt_name);
values.put(MySQLiteHelper.COLUMN_DEBT_TOTAL, debt_total);
values.put(MySQLiteHelper.COLUMN_APR, apr);
values.put(MySQLiteHelper.COLUMN_PAYMENT, payment);
return database.update(MySQLiteHelper.TABLE_DEBT, values, MySQLiteHelper.COLUMN_ID + " = " + updateId, null) > 0;
}
I have verified that the COLUMN_ID and the updateId are pointing to the correct rows in the ListView and the SQL database.
Does someone see something I am not?
Perhaps you are violating a constraint with your update? Just a guess without seeing the DB code.
EDIT
Lose the single quotes around the row id variable, that is making the DB treat it as a string, and a string compared to a number is a fail.
This will work better:
String whereClause = MySQLiteHelper.COLUMN_ID + " = ?";
String[] whereArgs = new String[]{ String.valueOf(updateId) };
return database.update(MySQLiteHelper.TABLE_DEBT,
values, whereClause, whereArgs) > 0;
The String.valueOf() call simply converts the ID to a String value.
I test your code in my computer.
The update method works fine.
So I think you should post more code .
or You should check your logic.
I was missing a step between 2 and 3.
Setting the variable again, inside the onClick method. Once the user pressed the update button, the variable had to be RE-SET to the new value of the EditText field. Like this (simplified version):
String name = null;
EditText et;
name = debt.getName();
et.setText(name);
onclick {
***name = et.getText().toString();***
datasource.updateDebt(name);
}

Looping code through database records

I have a database with some records in and i have the code i wish to execute on each row but I'm having trouble creating a suitable loop, ive been trying while(movetonext) but it hasnt been working.
cursor = getAppts();
cursor.moveToNext();
String titlefromdb = cursor.getString(3);
if (strTitle.equals(titlefromdb) && cursor.getString(1).equals(dateselforap))
{
// matching code update box
final Dialog matchdiag = new Dialog(CW2Organisor.this);
matchdiag.setContentView(R.layout.apptmatch);
matchdiag.setTitle("View/Edit Appointment");
matchdiag.setCancelable(true);
TextView matchtxt = (TextView) matchdiag.findViewById(R.id.matchtxt);
matchtxt.setText("Appointment \"" + titlefromdb + "\" already exists, please choose a different event title");
Button btnmatchok = (Button) matchdiag.findViewById(R.id.btnmatch);
btnmatchok.setOnClickListener(new OnClickListener() {
// on click for cancel button
#Override
public void onClick(View v) {
matchdiag.dismiss();
}
});
matchdiag.show();
}
else
{
addAppt(strTime, strTitle, strDet);
dialog.dismiss();
}
What I would need is for each row of my database i would need the titlefromdb to hold the title field of the current row and the for the if statement to run and then move to the next row.
You could try
cursor.moveToFirst();
loop with some sort of check
cursor.moveToNext();
end loop
... and I would also try to qualify your "it's not working" statement. What's not working?

Error in AutoCompleteText when the inputed text isnt on the autocomplete list for android

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

Categories

Resources