Программно получить номер телефона телефона Android

443

Как программно получить номер телефона устройства, на котором запущено мое приложение для Android?

jkap
источник
это невозможно, если только вы не введете это сами. Номер телефона не известен ни по мобильному телефону, ни по SIM-карте, только по сети ...
tomsoft
3
@ tomsoft Подумайте об этом ... Как такие приложения, как Facebook, автоматически проверяют ваш номер телефона?
Эдди Харт
1
@tomsoft Нет, в большинстве случаев он даже не запрашивает ваш номер телефона, или, если это так, поле заполняется.
Эдди Харт
1
@tomsoft Ну, я подписался на Facebook на днях, и он не спрашивал мой номер, когда он написал мне код. Попробуй это. ;)
Эдди Харт
1
@EddieHart Сделай это тоже, и меня спросили мой номер телефона. Таким образом, это подтверждает, что, вообще говоря, это недоступно, и некоторые операторы могут добавить эту информацию о настройке, но это не стандартная функция GMS
tomsoft,

Ответы:

484

Код:

TelephonyManager tMgr = (TelephonyManager)mAppContext.getSystemService(Context.TELEPHONY_SERVICE);
String mPhoneNumber = tMgr.getLine1Number();

Требуемое разрешение:

<uses-permission android:name="android.permission.READ_PHONE_STATE"/> 

Предостережения:

Согласно высоко голосуемым комментариям, есть несколько предостережений, о которых нужно знать. Это может вернуть nullили ""даже "???????", и это может вернуть устаревший номер телефона, который больше не действителен. Если вы хотите что-то, что однозначно идентифицирует устройство, вы должны использовать getDeviceId()вместо этого.

Алекс Воловой
источник
150
На самом деле, не так идеально. В прошлый раз, когда я пробовал этот метод, он сообщал номер телефона, который был у моего телефона, прежде чем мой старый номер мобильного телефона был перенесен на него. Это, вероятно, все еще делает, поскольку приложение Настройки все еще показывает тот несуществующий номер. Также есть сообщения о том, что некоторые SIM-карты вызывают возврат этого метода null. При этом, я не знаю лучшего ответа.
CommonsWare
4
Марк прав. Если намерение использовать что-то, что однозначно идентифицирует телефон, я бы использовал getDeviceId (), который вернет IMEA для GSM.
Алексей Воловой
15
(Я думаю, что вы имеете в виду IMEI ...?)
ChaimKut
23
Ну, я проверил его на Nexus One с Android OS 2.2, и он возвращает ноль
Омар Рехман
43
Разработчики могут подумать, что это идеальный ответ, учитывая количество голосов. Следует добавить примечание, чтобы предупредить разработчика, что этот метод не всегда дает номер телефона.
Habeeb Perwad
151

Гарантированного решения этой проблемы не существует, поскольку номер телефона физически не хранится на всех SIM-картах и ​​не транслируется из сети на телефон. Это особенно верно в некоторых странах, где требуется проверка физического адреса, причем назначение номера происходит только после этого. Назначение номера телефона происходит в сети и может быть изменено без замены SIM-карты или устройства (например, поддерживается портирование).

Я знаю, что это боль, но, скорее всего, лучшее решение - просто попросить пользователя ввести свой номер телефона и сохранить его.

Johan
источник
18
Чтобы проверить занятый номер, вы можете отправить смс (содержащий код) на номер и контролировать ответ, установив прослушиватель на «android.provider.Telephony.SMS_RECEIVED». таким образом, вы можете убедиться, что номер правильный и работает
Хоссейн Шахдуст
1
Творческое решение, но вы, возможно, захотите сообщить пользователю, что вы делаете это, на тот случай, если с него за это взимают плату.
Норман Х
3
Есть ли какой - либо поставщик , что плата за получение текстовых сообщений ?!
ThiefMaster
9
Да, конечно. Прежде чем я добавил текстовые сообщения в свой план, с меня взяли 0,30 доллара США за каждое полученное текстовое сообщение. Роджерс в Канаде.
Джон Кротч
44

Обновление: этот ответ больше недоступен, так как Whatsapp прекратил указывать номер телефона в качестве имени учетной записи, не обращайте внимания на этот ответ.

На самом деле есть альтернативное решение, которое вы можете рассмотреть, если вы не можете получить его через службу телефонии.

На сегодняшний день вы можете положиться на другое большое приложение, которое использует WhatsApp AccountManager. Это приложение установлено на миллионах устройств, и если вы не можете получить номер телефона через него TelephonyManager, вы можете сделать это.

Разрешение:

<uses-permission android:name="android.permission.GET_ACCOUNTS" />

Код:

AccountManager am = AccountManager.get(this);
Account[] accounts = am.getAccounts();

for (Account ac : accounts) {
    String acname = ac.name;
    String actype = ac.type;
    // Take your time to look at all available accounts
    System.out.println("Accounts : " + acname + ", " + actype);
}

Проверьте actypeучетную запись WhatsApp

if(actype.equals("com.whatsapp")){
    String phoneNumber = ac.name;
}

Конечно, вы можете не получить его, если пользователь не установил WhatsApp, но в любом случае стоит попробовать. И помните, что вы всегда должны спрашивать у пользователя подтверждение.

Чор Вай Чун
источник
1
Я видел это сегодня, когда возился со счетами. Очень плохо, что число выставлено так. Конечно, вам нужно разрешение GET_ACCOUNTS, и в этот момент пользователю, вероятно, все равно, какие разрешения имеет приложение.
Jargetz
9
Это решение устарело, Whatsapp больше не сохраняет номер телефона на имени учетной записи, знаете ли вы, где WhatsApp сохраняет номер телефона после нового обновления?
Cohelad
@Cohelad, спасибо за обновление, я проверю позже и вычеркну этот ответ после подтверждения, а пока не знаю, где они сохраняют номер
Чор Вай Чун
3
Но Viber разоблачить номер! com.viber.voip.account
xnagyg
32

Как написано в моем предыдущем ответе

Используйте код ниже:

TelephonyManager tMgr = (TelephonyManager)mAppContext.getSystemService(Context.TELEPHONY_SERVICE);
String mPhoneNumber = tMgr.getLine1Number();

В AndroidManifest.xml дайте следующее разрешение:

 <uses-permission android:name="android.permission.READ_PHONE_STATE"/> 

Но помните, этот код не всегда работает, так как номер мобильного телефона зависит от SIM-карты и оператора сети / оператора сотовой связи.

Также попробуйте проверить в « Телефон» -> «Настройки» -> «О программе» -> «Идентификация телефона». Если вы можете просмотреть номер там, вероятность получения номера телефона по указанному выше коду выше. Если вы не можете просмотреть номер телефона в настройках, вы не сможете получить через этот код!

Предлагаемое решение:

  1. Получить номер телефона пользователя в качестве ручного ввода от пользователя.
  2. Отправьте код на мобильный номер пользователя с помощью SMS.
  3. Попросите пользователя ввести код для подтверждения номера телефона.
  4. Сохраните номер в общем предпочтении.

Выполните вышеуказанные 4 шага как одноразовое действие во время первого запуска приложения. Позже, когда требуется номер телефона, используйте значение, доступное в общих настройках.

Нишанти Грасия
источник
Этот ответ охватывает все факторы, он должен быть принят =)
Слава Фомин II
Как я могу получить номер мобильного телефона, если на телефоне есть две симки? с кодом выше. Для одиночного сима все работает нормально
Амрит Чакрадхари
26

Так вот, как вы запрашиваете номер телефона через API сервисов Play Services без разрешения и взломов. Источник и полный пример .

В вашем build.gradle (требуется версия 10.2.x и выше):

compile "com.google.android.gms:play-services-auth:$gms_version"

В вашей деятельности (код упрощен):

@Override
protected void onCreate(Bundle savedInstanceState) {
    // ...
    googleApiClient = new GoogleApiClient.Builder(this)
            .addApi(Auth.CREDENTIALS_API)
            .build();
    requestPhoneNumber(result -> {
        phoneET.setText(result);
    });
}

public void requestPhoneNumber(SimpleCallback<String> callback) {
    phoneNumberCallback = callback;
    HintRequest hintRequest = new HintRequest.Builder()
            .setPhoneNumberIdentifierSupported(true)
            .build();

    PendingIntent intent = Auth.CredentialsApi.getHintPickerIntent(googleApiClient, hintRequest);
    try {
        startIntentSenderForResult(intent.getIntentSender(), PHONE_NUMBER_RC, null, 0, 0, 0);
    } catch (IntentSender.SendIntentException e) {
        Logs.e(TAG, "Could not start hint picker Intent", e);
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == PHONE_NUMBER_RC) {
        if (resultCode == RESULT_OK) {
            Credential cred = data.getParcelableExtra(Credential.EXTRA_KEY);
            if (phoneNumberCallback != null){
                phoneNumberCallback.onSuccess(cred.getId());
            }
        }
        phoneNumberCallback = null;
    }
}

Это создаст диалог, подобный этому:

введите описание изображения здесь

Dmide
источник
2
Запрос подсказки показывает номер телефона из учетной записи электронной почты, связанной с телефоном, он будет отображаться в раскрывающемся списке, даже если в устройстве нет SIM-карты.
Ари
как диалоговое окно показывает несколько номеров, когда есть только одна SIM-карта? Для меня это показывает 5 номеров. : / :)
РКА
Как мы можем выбрать первый номер телефона автоматически в Android?
Ноорул
13
private String getMyPhoneNumber(){
    TelephonyManager mTelephonyMgr;
    mTelephonyMgr = (TelephonyManager)
        getSystemService(Context.TELEPHONY_SERVICE); 
    return mTelephonyMgr.getLine1Number();
}

private String getMy10DigitPhoneNumber(){
    String s = getMyPhoneNumber();
    return s != null && s.length() > 2 ? s.substring(2) : null;
}

Код взят с http://www.androidsnippets.com/get-my-phone-number

Эмиль Хайрик
источник
@JaredBurrows из-за "s.substring (2)".
Cookie Monster
1
это не работает для меня. Я получаю значение NULL (восходящая SIM-карта, Швейцария)
e-nature
Ваша ссылка не работает.
Уманг Бюрмон
11

Существует новый Android API, который позволяет пользователю выбирать свой номер телефона без необходимости разрешения. Взгляните на: https://android-developers.googleblog.com/2017/10/effective-phone-number-verification.html

// Construct a request for phone numbers and show the picker
private void requestHint() {
    HintRequest hintRequest = new HintRequest.Builder()
       .setPhoneNumberIdentifierSupported(true)
       .build();

    PendingIntent intent = Auth.CredentialsApi.getHintPickerIntent(
        apiClient, hintRequest);
    startIntentSenderForResult(intent.getIntentSender(),
        RESOLVE_HINT, null, 0, 0, 0);
} 
Wirling
источник
Это требует Firebase
Влад
@ Влад Нет, это не так. Для этого требуется только Google Play Services, который поставляется с большинством устройств. Цитата из поста в блоге: «Перед тем, как начать, вам нужно собрать и протестировать это устройство с номером телефона, которое может получать SMS-сообщения и поддерживает сервисы Google Play 10.2.x и выше».
Wirling
9

Просто хочу добавить немного здесь к объяснениям выше в ответах выше. Что сэкономит время и другим.

В моем случае этот метод не вернул номер мобильного телефона, была возвращена пустая строка. Это было связано с тем, что я перенес свой номер на новую симку. Поэтому, если я захожу в «Настройки»> «О телефоне»> «Состояние»> «Мой номер телефона», отображается сообщение «Неизвестно».

user_CC
источник
Мой тоже, что это за состояние? Роуминг? Или, может быть, на симкарте просто не хранится номер.
Александр Маркондес
8

Иногда ниже кода возвращается nullили пустая строка.

TelephonyManager tMgr = (TelephonyManager)mAppContext.getSystemService(Context.TELEPHONY_SERVICE);
String mPhoneNumber = tMgr.getLine1Number();

С разрешения ниже

<uses-permission android:name="android.permission.READ_PHONE_STATE"/>

Есть еще один способ, которым вы сможете получить свой номер телефона, я не проверял это на нескольких устройствах, но приведенный выше код не работает каждый раз.

Попробуйте код ниже:

String main_data[] = {"data1", "is_primary", "data3", "data2", "data1", "is_primary", "photo_uri", "mimetype"};
Object object = getContentResolver().query(Uri.withAppendedPath(android.provider.ContactsContract.Profile.CONTENT_URI, "data"),
        main_data, "mimetype=?",
        new String[]{"vnd.android.cursor.item/phone_v2"},
        "is_primary DESC");
if (object != null) {
    do {
        if (!((Cursor) (object)).moveToNext())
            break;
        // This is the phoneNumber
        String s1 = ((Cursor) (object)).getString(4);
    } while (true);
    ((Cursor) (object)).close();
}

Вам нужно будет добавить эти два разрешения.

<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.READ_PROFILE" />

Надеюсь, это поможет, спасибо!

activesince93
источник
Могу я спросить: во втором фрагменте номер ячейки?
iOSAndroidWindowsMobileAppsDev
1
Значение String s1будет номер телефона.
activesince93
Этот код не работает для меня. (Ваш последний фрагмент кода). Возвращает пустую строку.
Кристи Уэлш
Пожалуйста, объясните свой ответ. Где хранится номер и как он содержит номер? Зависит от чего?
not2qubit
3
@ not2qubit Я думаю, что он получает доступ к самоконтакту в приложении «Контакты»
Samplasion
4

Это более упрощенный ответ:

public String getMyPhoneNumber()
{
    return ((TelephonyManager) getSystemService(TELEPHONY_SERVICE))
            .getLine1Number();
}
EP Льюис
источник
3

Во-первых, получение мобильного номера пользователя противоречит этической политике, раньше это было возможно, но теперь, согласно моим исследованиям, для этого нет надежного решения. Используя некоторый код, можно получить номер мобильного телефона, но нет никаких гарантий, что он будет работать. только в нескольких устройствах. После долгих исследований я нашел только три решения, но они работают не на всех устройствах.

Есть следующая причина, почему мы не получаем.

1. Android-устройство и новая SIM-карта не хранят номер мобильного телефона, если мобильный номер недоступен в устройстве и в симе, то как можно получить номер, если любая старая SIM-карта, имеющая номер мобильного телефона, то с помощью диспетчера телефонии мы можем получить номер другого мудро, он вернет «ноль» или «» или «??????»

<uses-permission android:name="android.permission.READ_PHONE_STATE"/>

 TelephonyManager tel= (TelephonyManager)this.getSystemService(Context.
            TELEPHONY_SERVICE);
    String PhoneNumber =  tel.getLine1Number();

Примечание: - Я протестировал это решение на следующих устройствах Moto x, Samsung Tab 4, Samsung S4, Nexus 5 и Redmi 2 prime, но он не работает каждый раз, когда возвращает пустую строку, поэтому вывод бесполезен

  1. Этот метод работает только в Redmi 2 prime, но для этого необходимо добавить разрешение на чтение контакта в манифесте.

Примечание: - Это также не гарантированное и эффективное решение, я тестировал это решение на многих устройствах, но оно работало только в Redmi 2 prime, который является устройством с двумя симами, он дает мне два мобильных номера, первый номер правильный, а второй нет. принадлежат моей второй симе, принадлежат моей какой-то старой сим-карте, которую я не использую.

 String main_data[] = {"data1", "is_primary", "data3", "data2", "data1",
            "is_primary", "photo_uri", "mimetype"};
    Object object = getContentResolver().
            query(Uri.withAppendedPath(android.provider.ContactsContract.Profile.CONTENT_URI, "data"),
            main_data, "mimetype=?",
            new String[]{"vnd.android.cursor.item/phone_v2"},
            "is_primary DESC");
    String s1="";
    if (object != null) {
        do {
            if (!((Cursor) (object)).moveToNext())
                break;
            // This is the phoneNumber
             s1 =s1+"---"+ ((Cursor) (object)).getString(4);
        } while (true);
        ((Cursor) (object)).close();
    }
  1. В моем исследовании, которое я обнаружил ранее, можно было получить номер мобильного телефона, используя учетную запись WhatsApp, но теперь новая версия Whatsapp не хранит номер мобильного телефона пользователя.

Вывод : - Android не имеет какого-либо гарантированного решения для получения номера мобильного телефона программно.

Предложение : - 1. Если вы хотите подтвердить номер мобильного телефона пользователя, попросите пользователя указать его номер, используя otp, вы можете это проверить.

  1. Если вы хотите идентифицировать устройство пользователя, для этого вы можете легко получить номер IMEI устройства.
Рамкришна Кушваха
источник
2

TelephonyManagerне является правильным решением, потому что в некоторых случаях номер не сохраняется на SIM-карте. Я предлагаю вам использовать общие предпочтения, чтобы сохранить номер телефона пользователя при первом открытии приложения, и этот номер будет использоваться всякий раз, когда вам нужно.

Навид Ахмад
источник
1
Но этот метод подвержен ошибкам. Пользователь может ввести неправильный номер.
Зохра Хан
3
да, так что для этого я использовал текстовое сообщение, когда пользователь вводит номер, поэтому из SmsManager само сообщение приложения, и с помощью этого мы можем использовать smsReciever для получения оригинального номера
Naveed Ahmad
1
У меня есть еще один вопрос .. с этим методом будет взиматься плата за SMS, предоставляемая пользователем (если это не бесплатный номер). Есть ли другой способ, которым я могу получить номер телефона пользователя?
Зохра Хан
Да, конечно, с этого SMS будет взиматься плата, если номер не является бесплатным.
Навид Ахмад
Нет, я думаю, что нет такого метода без TelephonyManager до сих пор. и я указываю на проблему TelephoneManager в своем ответе.
Навид Ахмад
2

Вот комбинация решений, которые я нашел (пример проекта здесь , если вы также хотите проверить автозаполнение):

манифест

    <uses-permission android:name="android.permission.READ_PHONE_STATE" />

build.gradle

    implementation "com.google.android.gms:play-services-auth:17.0.0"

MainActivity.kt

class MainActivity : AppCompatActivity() {
    private lateinit var googleApiClient: GoogleApiClient

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        tryGetCurrentUserPhoneNumber(this)
        googleApiClient = GoogleApiClient.Builder(this).addApi(Auth.CREDENTIALS_API).build()
        if (phoneNumber.isEmpty()) {
            val hintRequest = HintRequest.Builder().setPhoneNumberIdentifierSupported(true).build()
            val intent = Auth.CredentialsApi.getHintPickerIntent(googleApiClient, hintRequest)
            try {
                startIntentSenderForResult(intent.intentSender, REQUEST_PHONE_NUMBER, null, 0, 0, 0);
            } catch (e: IntentSender.SendIntentException) {
                Toast.makeText(this, "failed to show phone picker", Toast.LENGTH_SHORT).show()
            }
        } else
            onGotPhoneNumberToSendTo()

    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == REQUEST_PHONE_NUMBER) {
            if (resultCode == Activity.RESULT_OK) {
                val cred: Credential? = data?.getParcelableExtra(Credential.EXTRA_KEY)
                phoneNumber = cred?.id ?: ""
                if (phoneNumber.isEmpty())
                    Toast.makeText(this, "failed to get phone number", Toast.LENGTH_SHORT).show()
                else
                    onGotPhoneNumberToSendTo()
            }
        }
    }

    private fun onGotPhoneNumberToSendTo() {
        Toast.makeText(this, "got number:$phoneNumber", Toast.LENGTH_SHORT).show()
    }


    companion object {
        private const val REQUEST_PHONE_NUMBER = 1
        private var phoneNumber = ""

        @SuppressLint("MissingPermission", "HardwareIds")
        private fun tryGetCurrentUserPhoneNumber(context: Context): String {
            if (phoneNumber.isNotEmpty())
                return phoneNumber
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                val subscriptionManager = context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE) as SubscriptionManager
                try {
                    subscriptionManager.activeSubscriptionInfoList?.forEach {
                        val number: String? = it.number
                        if (!number.isNullOrBlank()) {
                            phoneNumber = number
                            return number
                        }
                    }
                } catch (ignored: Exception) {
                }
            }
            try {
                val telephonyManager = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
                val number = telephonyManager.line1Number ?: ""
                if (!number.isBlank()) {
                    phoneNumber = number
                    return number
                }
            } catch (e: Exception) {
            }
            return ""
        }
    }
}
разработчик Android
источник
Пожалуйста, смотрите комментарии к этому ответу stackoverflow.com/a/48210130/5457916 , прежде чем реализовать этот метод
humble_wolf
Ссылка, которую вы предоставили, является лишь частью того, что я сделал здесь. Здесь я впервые попытался заполнить его сам. И есть запасной вариант для этого.
Android-разработчик
Я знаю, сэр, ваш ответ отличный и не неправильный в каком-либо смысле, я просто хотел, чтобы читатели знали об условиях, которые идут с этим способом, например, это может заполнить число, связанное с вашей учетной записью Google и т. Д., Упомянутые в комментариях там.
humble_wolf
Я все еще предпочитаю то, что я написал. Извините
разработчик для Android
1

Небольшой вклад. В моем случае код запускает исключение ошибки. Мне нужно было поместить аннотацию для запуска кода и решить эту проблему. Здесь я позволю этот код.

public static String getLineNumberPhone(Context scenario) {
    TelephonyManager tMgr = (TelephonyManager) scenario.getSystemService(Context.TELEPHONY_SERVICE);
    @SuppressLint("MissingPermission") String mPhoneNumber = tMgr.getLine1Number();
    return mPhoneNumber;
}
Ариэль Алехандро Вагнер
источник
0

Несмотря на то, что возможно иметь несколько учетных записей голосовой почты, при звонке со своего собственного номера операторы направляют вас на голосовую почту. Так TelephonyManager.getVoiceMailNumber()или TelephonyManager.getCompleteVoiceMailNumber(), в зависимости от вкуса, который вам нужен.

Надеюсь это поможет.

Джим
источник
5
функция getCompleteVoiceMailNumber отсутствует, плюс функция getVoiceMailNumber () возвращает число, отличное от реального номера телефона.
Android-разработчик
Это трюк, который работает только с парой операторов мобильной связи в мире. Но технически может быть обходной путь.
Technik
0

Добавьте эту зависимость: implementation 'com.google.android.gms:play-services-auth:18.0.0'

Чтобы получить список телефонных номеров, используйте это:

val hintRequest = HintRequest.Builder()
    .setPhoneNumberIdentifierSupported(true)
    .build()

val intent = Credentials.getClient(context).getHintPickerIntent(hintRequest)

startIntentSenderForResult(
    intent.intentSender,
    PHONE_NUMBER_FETCH_REQUEST_CODE,
    null,
    0,
    0,
    0,
    null
)

После нажатия на диалог воспроизведения услуг:

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent? { 
    super.onActivityResult(requestCode, resultCode, data)

    if (requestCode == PHONE_NUMBER_FETCH_REQUEST_CODE) {
        data?.getParcelableExtra<Credential>(Credential.EXTRA_KEY)?.id?.let { 
            useFetchedPhoneNumber(it)
        }
    }
}
Реаз Ахмад
источник
-6

во время работы над приложением безопасности, которое должно было получить номер телефона того, кому мой телефон мог попасть в их руки, я должен был это сделать; 1. Получите Boot complete и затем попробуйте получить Line1_Number из telephonyManager, который возвращает строковый результат. 2. сравните результат «Строка» с моим собственным номером телефона, и если они не совпадают или строка вернет значение «ноль», 3. тайно отправьте SMS-сообщение с результатом строки и специальным знаком на номер моего офиса. 4. если отправка сообщения не удалась, запустите службу и продолжайте попытки после каждого часа, пока не будет успешно отправлено ожидающее отправленное SMS-сообщение. С помощью этих шагов я мог получить номер человека, использующего мой потерянный телефон. не имеет значения, если человек обвинен.

луч
источник
почему понижает?
humble_wolf