0

I am experiencing some unusual behaviour from my app - I cannot fathom why, but when a user selects a contact from my listview, the contact which is later retrieved from the handset is somehow not the one the user chose...

UPDATED New code, still not working.

    public class nominateContactsActivity extends ListActivity {
public String strName;
public String strTelNo;
public static final String PREFS_NAME = "locationPrefs";
public static final ArrayList<NameValuePair> contactsArray = new ArrayList<NameValuePair>();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);

setContentView(R.layout.nominatecontactsactivitytest);

this.getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
this.getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);

//String[] projection = new String[] { ContactsContract.PhoneLookup.NUMBER};
String selection = ContactsContract.Contacts.HAS_PHONE_NUMBER + " = '1'";
Cursor cursor = managedQuery(ContactsContract.Contacts.CONTENT_URI,null, selection, null, null);
startManagingCursor(cursor);
String[] columns = new String[] { 
        ContactsContract.Contacts.DISPLAY_NAME
        };

int[] to = new int[] { android.R.id.text1 };

SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_multiple_choice, cursor, columns, to);
this.setListAdapter(adapter);

Button finishButton = (Button) this.findViewById(R.id.finishButton);
finishButton.setOnClickListener(new OnClickListener() {

    public void onClick(View v) {

        SimpleCursorAdapter adapter = (SimpleCursorAdapter) nominateContactsActivity.this.getListAdapter();
        ListView lv = nominateContactsActivity.this.getListView();
        SparseBooleanArray selectedItems = lv.getCheckedItemPositions();
        Cursor contactsCursor = adapter.getCursor();

        /*for (long id : lv.getCheckedItemIds()) {
            String selection = ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?";
            String[] args = new String[] { String.valueOf(contactId) };
            Cursor cursor=managedQuery(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, selection, args, null);
        }*/


        for (long id : lv.getCheckedItemIds()) {
            long contactId = contactsCursor.getInt(contactsCursor.getColumnIndex(BaseColumns._ID));
            String selection = ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?";
            String[] args = new String[] { String.valueOf(contactId) };
            Cursor cursor=managedQuery(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, selection, args, null);
            if (cursor.moveToFirst()) {
                strName=cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
                strTelNo = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));                                                      
            }
        ;}
            try {
                //Name not operationally useful - why bother storing it - keep this in case later implemented.
                //contactsArray.add(new BasicNameValuePair ("name", strName));
                contactsArray.add(new BasicNameValuePair("number", strTelNo));
            } catch(Exception e){
                e.printStackTrace();
            }

        try {
            storeContacts();
        } catch (ClientProtocolException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    });
}

public void storeContacts() throws ClientProtocolException, IOException{
    SharedPreferences userPrefs = this.getSharedPreferences("PREFS_NAME", 0);
    Editor edit = userPrefs.edit();
    //edit.remove("contactsData").commit();
    String formattedString = contactsArray.toString()
            .replace("number=", "") //remove number name
            .replace(" ","")        //remove spaces
            .replace("[", "")       //remove the right bracket
            .replace("]", "");      //remove the left bracket
    edit.putString("contactsData", formattedString);
    edit.commit();
    String name = userPrefs.getString("Name", null);
    String test = userPrefs.getString("contactsData", null);
    Log.d("", formattedString);
    Log.d("test = ", test);
    Intent myIntent = new Intent(nominateContactsActivity.this, rootMenuActivity.class);
    startActivity(myIntent);
          String textSMS = "You have been nominated as a contact by " + name +". Check out www.mywebsite.com for info"; 
          String retrievedContacts = userPrefs.getString("contactsData", null);
          String textPhoneNo;
          textPhoneNo = retrievedContacts;
          //textSMS = "My current location is: " + currentLocation;
          String phoneNo = textPhoneNo;
          try {
                SmsManager smsManager = SmsManager.getDefault();
                smsManager.sendTextMessage(phoneNo, null, textSMS, null, null);
                Toast.makeText(getApplicationContext(), "SMS Sent!", Toast.LENGTH_LONG).show();
                Intent myIntent1 = new Intent(nominateContactsActivity.this, rootMenuActivity.class);
                startActivity(myIntent1);       
          } 
          catch (Exception e) {
                Toast.makeText(getApplicationContext(),
                "SMS failed, please try again later!",
                Toast.LENGTH_LONG).show();
                e.printStackTrace();
          } 

The above code works fine except from returning the wrong contact. Is this a scrolling problem, where the id of the checkbox is lost? Please help!!

Thank you

UPDATE -STACKTRACE

04-11 15:29:43.646: E/AndroidRuntime(3976): FATAL EXCEPTION: main
04-11 15:29:43.646: E/AndroidRuntime(3976): android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 1
04-11 15:29:43.646: E/AndroidRuntime(3976):     at android.database.AbstractCursor.checkPosition(AbstractCursor.java:424)
04-11 15:29:43.646: E/AndroidRuntime(3976):     at android.database.AbstractWindowedCursor.checkPosition(AbstractWindowedCursor.java:136)
04-11 15:29:43.646: E/AndroidRuntime(3976):     at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:50)
04-11 15:29:43.646: E/AndroidRuntime(3976):     at android.database.CursorWrapper.getString(CursorWrapper.java:114)
04-11 15:29:43.646: E/AndroidRuntime(3976):     at com.app.protect3d.nominateContactsActivity$1.onClick(nominateContactsActivity.java:123)
04-11 15:29:43.646: E/AndroidRuntime(3976):     at android.view.View.performClick(View.java:4204)
04-11 15:29:43.646: E/AndroidRuntime(3976):     at android.view.View$PerformClick.run(View.java:17355)
04-11 15:29:43.646: E/AndroidRuntime(3976):     at android.os.Handler.handleCallback(Handler.java:725)
04-11 15:29:43.646: E/AndroidRuntime(3976):     at android.os.Handler.dispatchMessage(Handler.java:92)
04-11 15:29:43.646: E/AndroidRuntime(3976):     at android.os.Looper.loop(Looper.java:137)
04-11 15:29:43.646: E/AndroidRuntime(3976):     at android.app.ActivityThread.main(ActivityThread.java:5226)
04-11 15:29:43.646: E/AndroidRuntime(3976):     at java.lang.reflect.Method.invokeNative(Native Method)
04-11 15:29:43.646: E/AndroidRuntime(3976):     at java.lang.reflect.Method.invoke(Method.java:511)
04-11 15:29:43.646: E/AndroidRuntime(3976):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:795)
04-11 15:29:43.646: E/AndroidRuntime(3976):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:562)
04-11 15:29:43.646: E/AndroidRuntime(3976):     at dalvik.system.NativeStart.main(Native Method)
anthonyhumphreys
  • 1,051
  • 2
  • 12
  • 25
  • you are displaying Contacts, but you are enumerating Phones. You have to find the contact id, then make a query on the phone table with this id. – njzk2 Apr 11 '13 at 13:13
  • Thank you, that is very helpful - the error is quite obvious now. How exactly to I go about resolving this? It took a solid week of hair-tearing to get this far! Thank you so much for your help – anthonyhumphreys Apr 11 '13 at 13:18

1 Answers1

0

in onClick, you have the adapter. From it, you can get the cursor of the contacts.

Cursor contactsCursor = adapter.getCursor();

in your loop, you can get the contact id :

contactsCursor.moveToPosition(selectedPosition);
long contactId = contactsCursor.get(contactsCursor.getColumnIndex(BaseColumn._ID));

From there, you can search the Phone like this :

String selection = ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?";
String[] args = new String[] { String.valueOf(contactId) };
Cursor cursor=managedQuery(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, selection, args, null);
if (cursor.moveToFirst()) {
    // Get content here
}

from there you can use the obtained cursor the way you already are.

edit - simplification (re-edit, id is really contactId)

you can simply loop on this:

for (long contactId : lv.getCheckedItemIds()) {
    String selection = ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?";
    String[] args = new String[] { String.valueOf(contactId) };
    Cursor cursor=managedQuery(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, selection, args, null);
    if (cursor.moveToFirst()) {
        // Get content here
    }
}
njzk2
  • 38,969
  • 7
  • 69
  • 107
  • Thank you - I have attempted to integrate this code, though no logcat shows an indexoutofbounds error. I have edited the code above. – anthonyhumphreys Apr 11 '13 at 14:32
  • can you post the stacktrace for that exception ? – njzk2 Apr 11 '13 at 15:37
  • also, i though of a simplification. you can directly obtain the contacts ids from the listview : getCheckedItemIds() and loop over these to query the Phone table – njzk2 Apr 11 '13 at 15:39
  • Updated my question. Ill change the contactID part. Thank you again for your help – anthonyhumphreys Apr 11 '13 at 16:04
  • we missed one part : you have to call cursor.moveToFirst when you create it before using it. (i've added it to my answer) – njzk2 Apr 11 '13 at 16:06
  • Thank you - Won't be able to try this out til later tonight - Will update then :) Thank you so much – anthonyhumphreys Apr 11 '13 at 16:58
  • Thank you - This appears to work perfectly. If I could buy you a beer I would :p – anthonyhumphreys Apr 12 '13 at 13:03
  • njzk2 i updated my answer above where I have attempted to integrate your code....I still can't get it working! I thought the problem was resolved, but i must have broken something... – anthonyhumphreys Aug 13 '13 at 18:18
  • when you loop over the selected ids, you don't need to use the contactCursor. the contact id is actually the `id` that you get from the listview. It is my mistake, I used id and contactId for the same thing. See my edit – njzk2 Aug 14 '13 at 07:42
  • Thank you very much - sanity restored! – anthonyhumphreys Aug 14 '13 at 10:51