Incorrect Contact Number Fetching in Contact Picker - Android

930 views Asked by At

I am using a contact picker to get the number to an editText. The saved contact numbers can be of three types based on how the user saved a particular number.

  1. +911234567899 (with +91 as prefix) [India CountryCode].
  2. 01234567899 (with 0 as prefix) [Common STD Code used to call mobile numbers].
  3. 1234567899 (without any prefix).

I need to get remove the prefixes (if any) and get the actual 10 digit number without spaces to my editText (some devices put spaces between the numbers for better readability).

Now the issue I am facing is, this works perfect only for the first time you pick each type of contact, Like, It will work for the 1st time you pick a prefixed number and non prefixed number. The next time you try it, it won't work as i need. But works again perfect if we restart the app.

This is the code:

ScreenMain.java

import android.Manifest;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.net.Uri;
import android.provider.ContactsContract;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;


public class ScreenMain extends AppCompatActivity {


    private static final int PERMISSION_ALL = 1;

    ImageButton btnGetNumber;

    EditText etMobileNumber;

    private String sMobileNumber = "";

    private Uri uriContact;
    private String contactID;     // contacts unique ID


    private static ScreenMain inst;

    public static ScreenMain instance() {
        return inst;
    }


    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_screen_main);

        btnGetData = (Button) findViewById(R.id.btndGetStatus);

        etMobileNumber = (EditText) findViewById(R.id.etdMobileNumber);


        String[] PERMISSIONS = {    Manifest.permission.READ_CONTACTS,
                                    Manifest.permission.WRITE_CONTACTS,
                                    };

        ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL);


        etMobileNumber.setOnClickListener(new View.OnClickListener()
        {
            public void onClick(View view)
            {
                getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);

            }
        });

        btnGetNumber.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // using native contacts selection
                // Intent.ACTION_PICK = Pick an item from the data, returning what was selected.


                startActivityForResult(new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI), REQUEST_CODE_PICK_CONTACTS);
            }
        });

        btnGetData.setOnClickListener(new View.OnClickListener() {
            public void onClick(View view) {
                // sendSms("mONST");
                ClassSMS.sendSms(getApplicationContext(),"mONST",etMobileNumber.getText().toString());
            }
        });


        btnCall.setOnClickListener(new View.OnClickListener() {
            public void onClick(View view) {

              //  ClassMakeCall.makeCall(getApplicationContext(),etMobileNumber.getText().toString());

                String ssMobNumber = etMobileNumber.getText().toString();
                if (ssMobNumber.length() == 0) {
                    Toast.makeText(getApplicationContext(), " Please enter mobile number in the motorON unit", Toast.LENGTH_SHORT).show();
                    return;
                }
                if (ssMobNumber.length() != 10) {
                    Toast.makeText(getApplicationContext(), " Invalid mobile number", Toast.LENGTH_SHORT).show();
                    return;
                }

                try {
                    Intent callIntent = new Intent(Intent.ACTION_CALL);
                    callIntent.setData(Uri.parse("tel:+91" + ssMobNumber));
                    if (ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
                        // TODO: Consider calling
                        //    ActivityCompat#requestPermissions
                        // here to request the missing permissions, and then overriding
                        //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
                        //                                          int[] grantResults)
                        // to handle the case where the user grants the permission. See the documentation
                        // for ActivityCompat#requestPermissions for more details.

                        Toast.makeText(getApplicationContext()," SMS Fail, Please goto Settings -> APPS -> motorON -> Permissions and enable SMS permission ", Toast.LENGTH_SHORT).show();
                        return;
                    }
                   startActivity(callIntent);
                } catch (ActivityNotFoundException activityException) {
                    Toast.makeText(getApplicationContext()," unable to make call", Toast.LENGTH_SHORT).show();
                }


            }
        });

        ivSettings.setOnClickListener( new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                startActivity(new Intent(getApplicationContext(), ScreenSettings.class));
            }
        });


    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == REQUEST_CODE_PICK_CONTACTS && resultCode == RESULT_OK) {
            //   Log.d(TAG, "Response: " + data.toString());
            uriContact = data.getData();


            ClassGetPhoneNumber.retrieveContactNumber(getApplicationContext(),uriContact);
            if(ClassGetPhoneNumber.sStatus.equals("OK"))
            {
                etMobileNumber.setText(ClassGetPhoneNumber.sResponse);

            }

        }
    }


    @Override
    protected void onStart() {
        super.onStart();
        inst = this;
        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
    }

    @Override
    protected void onRestart(){
        super.onRestart();
        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
        //  Log.d(TAG, "atvt restart");
    }

    @Override
    protected void onResume(){
        super.onResume();
        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
        //   Log.d(TAG, "atvt resume");

    }

    @Override
    protected void onPause(){
        super.onPause();

        //   Log.d(TAG, "atvt pause");
    }

    @Override
    protected void onStop(){
        super.onStop();

        //  Log.d(TAG, "atvt stop");
    }

    @Override
    protected void onDestroy()
    {
        super.onDestroy();
        //   Log.d(TAG, "atvt destroy");
    }



    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           String permissions[], int[] grantResults)
    {
        switch (requestCode)
        {
            case PERMISSION_ALL:
                {
                    // If request is cancelled, the result arrays are empty.
                    if (grantResults.length > 0
                            && grantResults[0] == PackageManager.PERMISSION_GRANTED)
                    {
                    }
                    else
                    {
                        Toast.makeText(getApplicationContext()," App Needs SMS Permission to Work ", Toast.LENGTH_SHORT).show();
                    }
                    return;
                }
        }
    }




    }

ClassGetPhoneNumber.java

import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.provider.ContactsContract;
import android.util.Log;

class ClassGetPhoneNumber
{
    private static final String TAG = null ;
    public static String sStatus="ERROR";
    public static String sResponse;
    public static String sContactNumber;
    public static String sContactNumberFinal;
    public static int With91 = 0, With0 = 0, TenDigit = 0, InvalidNumber = 0;
    public static String contactID="";     // contacts unique ID
    public static String contactNumber = null;

    public static void retrieveContactNumber(Context context, Uri uriContact)
    {
        // getting contacts ID
        Cursor cursorID = context.getContentResolver().query(uriContact,
                new String[]{ContactsContract.Contacts._ID},
                null, null, null);

        if (cursorID.moveToFirst()) {

            contactID = cursorID.getString(cursorID.getColumnIndex(ContactsContract.Contacts._ID));
        }

        cursorID.close();

        // Using the contact ID now we will get contact phone number
        Cursor cursorPhone = context.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                new String[]{ContactsContract.CommonDataKinds.Phone.NUMBER},

                ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ? AND " +
                        ContactsContract.CommonDataKinds.Phone.TYPE + " = " +
                        ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE,

                new String[]{contactID},
                null);

        contactNumber = null;

        if (cursorPhone.moveToFirst()) {
            contactNumber = cursorPhone.getString(cursorPhone.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
        }

        cursorPhone.close();

        sResponse = null;
        sContactNumber = null;
        sContactNumberFinal = null;

        sContactNumber = contactNumber.replaceAll("\\s","");
        int iLength = sContactNumber.length();

        if(iLength==13)
            With91 = 1;
        if(iLength==11)
            With0 = 1;
        if(iLength==10)
            TenDigit = 1;

        if(With91 == 1)
        {
                sContactNumberFinal = sContactNumber.substring(3);
                Log.e(TAG,"In With91, sContactNumberFinal : "+sContactNumberFinal);
                sResponse = sContactNumberFinal;
                sStatus = "OK";
        }

        if (With0 == 1)
        {
                sContactNumberFinal = sContactNumber.substring(1);
                Log.e(TAG,"In With0, sContactNumberFinal : "+sContactNumberFinal);
                sResponse = sContactNumberFinal;
                sStatus = "OK";
        }

        if (TenDigit == 1)
        {
                sContactNumberFinal = sContactNumber;
                Log.e(TAG,"In TenDigit, sContactNumberFinal : "+sContactNumberFinal);
                sResponse = sContactNumberFinal;
                sStatus = "OK";
        }

    }
}
3

There are 3 answers

2
marmor On BEST ANSWER

I agree with @DaveyDaveDave static fields are not the way to go, but if you insist here's your same code, with lots of fixes and simplified code. Note that NORMALIZED_NUMBER is only supported from API 16 and above.

class ClassGetPhoneNumber {

    ...

    public static void retrieveContactNumber(Context context, Uri uriContact) {
        sResponse = null;
        sContactNumber = null;
        sContactNumberFinal = null;

        // get contactID from contactUri
        long contactID = ContentUris.parseId(contactUri);

        // Using the contact ID now we will get contact phone number
        // Don't add selection by Phone.TYPE as we might miss a lot of phones.
        // We ask for the normalized number, this will only work for API 16 and above
        Cursor cursorPhone = context.getContentResolver().query(CommonDataKinds.Phone.CONTENT_URI,
                new String[]{CommonDataKinds.Phone.NORMALIZED_NUMBER, CommonDataKinds.Phone.NUMBER},
                CommonDataKinds.Phone.CONTACT_ID + " = " + contactID,null,null);

        contactNumber = null;

        if (cursorPhone != null && cursorPhone.moveToFirst()) {
            contactNumber = cursorPhone.getString(0); // this number will always be of e164 format: "+<country><local number>"
            Log.d(TAG, "normalized number: " + contactNumber + ", original number: " + cursorPhone.getString(1) + ", contact-id: " + contactID);
        } else {
            // you need to quit here, otherwise you'll be using an old value of contactNumber in the rest of the code.
            if (cursorPhone != null) {
                cursorPhone.close();
            }
            return; 
        }

        cursorPhone.close();

        if (!TextUtils.isEmpty(contactNumber)) {
            sContactNumber = contactNumber;
            sContactNumberFinal = sContactNumber.substring(3);
            sResponse = sContactNumberFinal;
            sStatus = "OK";
        } else {
            // no phone was found
            sStatus = "NOT FOUND";
        }
    }
}
0
DaveyDaveDave On

It's hard to follow your code, because there's an awful lot going on, but I think the root cause will be that everything in your ClassGetPhoneNumber class is static, so the fields in that class are set on the first pass, and their values remain the next time you call the retrieveContactNumber method.

From looking at it, I suspect it's not as simple as it working the first time and not working subsequently, but rather that you get generally 'odd' behaviour, depending on the input.

The simplest solution would be to remove all the static keywords from the ClassGetPhoneNumber class, and to change the call from:

ClassGetPhoneNumber.retrieveContactNumber(getApplicationContext(),uriContact);

to:

new ClassGetPhoneNumber().retrieveContactNumber(getApplicationContext(),uriContact);

I think that will resolve the immediate problems you have.

3
Paul_Varghese On

I figured it out.

The issue was:
The value of the variables which I used to determine how the user has saved a particular number (With91, With0, TenDigit), was not initialized to zero at the start of the retrieveContactNumber() method.
Initializing them to zero at the start of the function cleared its previous values and made it work as intended.

Thanks everyone for your time and support.
-Paul Varghese