Неправильный выбор номера контакта в средстве выбора контактов – Android

Я использую средство выбора контактов, чтобы получить номер в editText. Сохраненные контактные номера могут быть трех типов в зависимости от того, как пользователь сохранил конкретный номер.

  1. +911234567899 (с префиксом +91) [код страны Индии].
  2. 01234567899 (с префиксом 0) [общий код STD, используемый для звонков на мобильные номера].
  3. 1234567899 (без префикса).

Мне нужно удалить префиксы (если они есть) и получить фактическое 10-значное число без пробелов в моем editText (некоторые устройства помещают пробелы между числами для лучшей читаемости).

Теперь проблема, с которой я столкнулся, заключается в том, что это работает идеально только в первый раз, когда вы выбираете каждый тип контакта. Например, это будет работать в первый раз, когда вы выбираете номер с префиксом и номер без префикса. В следующий раз, когда вы попробуете это, это не сработает так, как мне нужно. Но снова работает отлично, если мы перезапустим приложение.

Это код:

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";
        }

    }
}

person Paul_Varghese    schedule 02.08.2017    source источник
comment
Два общих замечания: вы используете регулярное выражение для удаления всех пробелов (contactNumber.replaceAll("\\s","")) — почему бы не сделать то же самое для удаления ведущего 0 (что-то вроде: contactNumber.replaceAll("^0", "")) и +91? Это значительно упростит код в вашем методе retrieveContactNumber. Вторая мысль: похоже, вы рады ограничить это только индийскими телефонными номерами (+91), но не забывайте, что в других странах другие коды и другие форматы.   -  person DaveyDaveDave    schedule 02.08.2017


Ответы (3)


Я согласен с тем, что статические поля @DaveyDaveDave не подходят, но если вы настаиваете, вот ваш тот же код с множеством исправлений и упрощенным кодом. Обратите внимание, что NORMALIZED_NUMBER поддерживается только в API 16 и выше.

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";
        }
    }
}
person marmor    schedule 02.08.2017
comment
Спасибо @marmor за предложение и решение моей проблемы. Это сработало нормально, и я добавил фрагмент, чтобы удалить +91 и 0, не используя длинное выражение if_statement для моей цели. - person Paul_Varghese; 03.08.2017
comment
отлично, если вам нужна поддержка API 15 и ниже или иногда получение нулевого значения от NORMALIZED_NUMBER, воспользуйтесь утилитой Google libphonenumber для обработки и форматирования телефонных номеров: github.com/googlei18n/libphonenumber - person marmor; 03.08.2017

Трудно следить за вашим кодом, потому что происходит очень много всего, но я думаю, что основной причиной будет то, что все в вашем классе ClassGetPhoneNumber является статическим, поэтому поля в этом классе устанавливаются при первом проходе, а их значения остаются в следующий раз, когда вы вызовете метод retrieveContactNumber.

Глядя на это, я подозреваю, что это не так просто, как то, что он работает в первый раз и не работает впоследствии, а скорее то, что вы получаете обычно «странное» поведение в зависимости от ввода.

Самым простым решением было бы удалить все ключевые слова static из класса ClassGetPhoneNumber и изменить вызов с:

ClassGetPhoneNumber.retrieveContactNumber(getApplicationContext(),uriContact);

to:

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

Я думаю, что это решит насущные проблемы, которые у вас есть.

person DaveyDaveDave    schedule 02.08.2017

Я понял.

Проблема заключалась в следующем:
Значение переменных, которые я использовал для определения того, как пользователь сохранил определенное число (With91, With0, TenDigit), не было инициализировано нулем в момент начало метода retrieveContactNumber().
Их инициализация нулем в начале функции очистила ее предыдущие значения и заставила ее работать должным образом.

Спасибо всем за ваше время и поддержку.
-Пол Варгезе

person Paul_Varghese    schedule 02.08.2017
comment
эй, Пол, кажется, у тебя есть другие проблемы в коде: (1) ты не можешь предположить, что телефон будет типа МОБИЛЬНЫЙ, он может быть установлен на другие ярлыки (ГЛАВНЫЙ, ПОЛЬЗОВАТЕЛЬСКИЙ, ЧАСТНЫЙ, РАБОЧИЙ), ты должен удалить это из подборки. (2) вы можете получить contactId без запроса через: long contactId = ContentUris.parseId(contactUri); (3) вместо регулярного выражения и анализа номера телефона используйте CommonDataKinds.Phone.NORMALIZED_NUMBER, чтобы всегда получать один и тот же тип - person marmor; 02.08.2017
comment
Не могли бы вы объяснить это, используя мой код? Это было бы полезно. - person Paul_Varghese; 02.08.2017
comment
да, я добавил исправленную версию в качестве нового ответа, обратите внимание на все мои встроенные комментарии - person marmor; 02.08.2017