以编程方式获取Android手机的电话号码

发布于 2024-08-26 01:34:44 字数 40 浏览 7 评论 0 原文

如何以编程方式获取运行 Android 应用程序的设备的电话号码?

How can I programmatically get the phone number of the device that is running my android app?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(24

酒绊 2024-09-02 01:34:44

代码:

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

所需权限:

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

注意事项:

根据高度评价的评论,有一些注意事项需要注意。这可以返回 null"" 甚至 "???????",并且它可以返回一个过时的电话号码,即不再有效。如果您想要唯一标识设备的内容,则应该使用 getDeviceId()

Code:

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

Required Permission:

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

Caveats:

According to the highly upvoted comments, there are a few caveats to be aware of. This can return null or "" or even "???????", and it can return a stale phone number that is no longer valid. If you want something that uniquely identifies the device, you should use getDeviceId() instead.

橪书 2024-09-02 01:34:44

由于电话号码并未实际存储在所有 SIM 卡上或从网络广播到电话,因此无法保证解决此问题。在一些需要实际地址验证的国家尤其如此,号码分配仅在事后进行。电话号码分配发生在网络上 - 并且可以在不更改 SIM 卡或设备的情况下进行更改(例如,这就是支持移植的方式)。

我知道这很痛苦,但最有可能最好的解决方案就是要求用户输入他/她的电话号码一次并存储它。

There is no guaranteed solution to this problem because the phone number is not physically stored on all SIM-cards, or broadcasted from the network to the phone. This is especially true in some countries which requires physical address verification, with number assignment only happening afterwards. Phone number assignment happens on the network - and can be changed without changing the SIM card or device (e.g. this is how porting is supported).

I know it is pain, but most likely the best solution is just to ask the user to enter his/her phone number once and store it.

毁虫ゝ 2024-09-02 01:34: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);
}

检查 WhatsApp 帐户的 actype

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

当然,如果用户没有安装 WhatsApp,您可能无法获得它,但无论如何值得尝试。
请记住,您应该始终要求用户确认。

Update: This answer is no longer available as Whatsapp had stopped exposing the phone number as account name, kindly disregard this answer.

There is actually an alternative solution you might want to consider, if you can't get it through telephony service.

As of today, you can rely on another big application Whatsapp, using AccountManager. Millions of devices have this application installed and if you can't get the phone number via TelephonyManager, you may give this a shot.

Permission:

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

Code:

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

Check actype for WhatsApp account

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

Of course you may not get it if user did not install WhatsApp, but its worth to try anyway.
And remember you should always ask user for confirmation.

泛滥成性 2024-09-02 01:34:44

这就是您在未经许可和黑客攻击的情况下通过 Play Services API 请求电话号码的方式。 来源完整示例

在您的 build.gradle 中(需要 10.2.x 及更高版本):

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

在您的 Activity 中(代码已简化):

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

这将生成一个如下所示的对话框:

在此处输入图像描述

So that's how you request a phone number through the Play Services API without the permission and hacks. Source and Full example.

In your build.gradle (version 10.2.x and higher required):

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

In your activity (the code is simplified):

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

This will generate a dialog like this:

enter image description here

北音执念 2024-09-02 01:34:44

正如我的 早期答案中发布的那样,

使用以下代码:

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. 通过短信将代码发送到用户的手机号码。
  3. 要求用户输入代码以确认电话号码。
  4. 将号码保存在共享首选项中。

在应用程序首次启动期间将上述 4 个步骤作为一次性活动执行。稍后,每当需要电话号码时,请使用共享首选项中可用的值。

As posted in my earlier answer

Use below code :

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

In AndroidManifest.xml, give the following permission:

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

But remember, this code does not always work, since Cell phone number is dependent on the SIM Card and the Network operator / Cell phone carrier.

Also, try checking in Phone--> Settings --> About --> Phone Identity, If you are able to view the Number there, the probability of getting the phone number from above code is higher. If you are not able to view the phone number in the settings, then you won't be able to get via this code!

Suggested Workaround:

  1. Get the user's phone number as manual input from the user.
  2. Send a code to the user's mobile number via SMS.
  3. Ask user to enter the code to confirm the phone number.
  4. Save the number in sharedpreference.

Do the above 4 steps as one time activity during the app's first launch. Later on, whenever phone number is required, use the value available in shared preference.

夕嗳→ 2024-09-02 01:34:44

有一个新的 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);
} 

There is a new Android api that allows the user to select their phonenumber without the need for a permission. Take a look at:
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);
} 
漫雪独思 2024-09-02 01:34:44
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

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

Code taken from http://www.androidsnippets.com/get-my-phone-number

匿名。 2024-09-02 01:34:44

只是想在上面的答案中添加一些解释。这也将为其他人节省时间。

就我而言,此方法没有返回任何手机号码,而是返回了一个空字符串。这是由于我将我的号码转移到新SIM卡上的情况。因此,如果我进入“设置”>“关于电话”>“状态”>“我的电话号码”,它会显示“未知”。

Just want to add a bit here to above explanations in the above answers. Which will save time for others as well.

In my case this method didn't returned any mobile number, an empty string was returned. It was due to the case that I had ported my number on the new sim. So if I go into the Settings>About Phone>Status>My Phone Number it shows me "Unknown".

落日海湾 2024-09-02 01:34:44

有时,下面的代码会返回 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" />

希望这有帮助,
谢谢!

Sometimes, below code returns null or blank string.

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

With below permission

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

There is another way you will be able to get your phone number, I haven't tested this on multiple devices but above code is not working every time.

Try below code:

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();
}

You will need to add these two permissions.

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

Hope this helps,
Thanks!

-黛色若梦 2024-09-02 01:34:44

首先,获取用户手机号码是违反道德政策的,以前这是可能的,但现在根据我的研究,没有可靠的解决方案可用,通过使用一些代码,可以获取手机号码,但不能保证它会起作用仅在少数设备中。经过大量研究,我只发现了三种解决方案,但它们并不适用于所有设备。

我们没有得到的原因如下。

1.Android设备和新SIM卡不存储手机号码,如果设备和SIM卡中没有手机号码,那么如何获取号码,如果任何旧SIM卡有手机号码,那么使用电话管理器我们可以获取其他号码明智的它会返回“null”或“”或“??????”

<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 中有效
这是双卡设备,它给了我两个手机号码,第一个是
正确,但第二个不属于我的第二个SIM卡,它属于
我没有使用一些旧的 SIM 卡。

 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 进行验证。

  • 如果您想识别用户的设备,为此您可以轻松获取设备 IMEI 号码。
  • First of all getting users mobile number is against the Ethical policy, earlier it was possible but now as per my research there no solid solution available for this, By using some code it is possible to get mobile number but no guarantee may be it will work only in few device. After lot of research i found only three solution but they are not working in all device.

    There is the following reason why we are not getting.

    1.Android device and new Sim Card not storing mobile number if mobile number is not available in device and in sim then how it is possible to get number, if any old sim card having mobile number then using Telephony manager we can get the number other wise it will return the “null” or “” or “??????”

    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
    
     TelephonyManager tel= (TelephonyManager)this.getSystemService(Context.
                TELEPHONY_SERVICE);
        String PhoneNumber =  tel.getLine1Number();
    

    Note:- I have tested this solution in following device Moto x, Samsung Tab 4, Samsung S4, Nexus 5 and Redmi 2 prime but it doesn’t work every
    time it return empty string so conclusion is it's useless

    1. This method is working only in Redmi 2 prime, but for this need to add
      read contact permission in manifest.

    Note:- This is also not the guaranteed and efficient solution, I have tested this solution in many device but it worked only in Redmi 2 prime
    which is dual sim device it gives me two mobile number first one is
    correct but the second one is not belong to my second sim it belong to
    my some old sim card which i am not using.

     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. In my research i have found earlier it was possible to get mobile number using WhatsApp account but now new Whatsapp version doesn’t storing user's mobile number.

    Conclusion:- Android doesn’t have any guaranteed solution to get
    user's mobile number programmatically.

    Suggestion:- 1. If you want to verify user’s mobile number then ask to
    user to provide his number, using otp you can can verify that.

    1. If you want to identify the user’s device, for this you can easily get device IMEI number.
    北城挽邺 2024-09-02 01:34:44

    TelephonyManager 不是正确的解决方案,因为在某些情况下,号码不会存储在 SIM 中。我建议您应该在应用程序首次打开时使用共享首选项来存储用户的电话号码,以便在需要时使用该号码。

    TelephonyManager is not the right solution, because in some cases the number is not stored in the SIM. I suggest that you should use the shared preference to store the user's phone number for the first time the application is open and the number will used whenever you need.

    夏尔 2024-09-02 01:34:44

    以下是我找到的解决方案的组合(示例项目此处< /a>,如果您还想检查自动填充):

    ma​​nifest

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

    Here's a combination of the solutions I've found (sample project here, if you want to also check auto-fill):

    manifest

        <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 ""
            }
        }
    }
    
    長街聽風 2024-09-02 01:34:44

    这是一个更简化的答案:

    public String getMyPhoneNumber()
    {
        return ((TelephonyManager) getSystemService(TELEPHONY_SERVICE))
                .getLine1Number();
    }
    

    This is a more simplified answer:

    public String getMyPhoneNumber()
    {
        return ((TelephonyManager) getSystemService(TELEPHONY_SERVICE))
                .getLine1Number();
    }
    
    内心旳酸楚 2024-09-02 01:34:44

    添加此依赖项:
    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)
            }
        }
    }
    

    Add this dependency:
    implementation 'com.google.android.gms:play-services-auth:18.0.0'

    To fetch phone number list use this:

    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
    )
    

    After tap on play services dialog:

    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)
            }
        }
    }
    
    回心转意 2024-09-02 01:34:44

    #SaveBangladesh

    // print phone numbers    
    getPhoneNumbers().forEach {
        val phoneNumber = it
        Log.d("DREG_PHONE", "phone number: $phoneNumber")
    }
    
    // Required Permissions: READ_PHONE_STATE, READ_PHONE_NUMBERS
    fun Context.getPhoneNumbers(): ArrayList<String> {
        val phoneNumbers = arrayListOf<String>()
        if (isFromAPI(23)) {
            val subscriptionManager = getSystemService(SubscriptionManager::class.java)
            val subsInfoList = subscriptionManager.activeSubscriptionInfoList
            for (subscriptionInfo in subsInfoList) {
                val phoneNumber =
                    if (isFromAPI(33))
                        subscriptionManager.getPhoneNumber(subscriptionInfo.subscriptionId)
                    else subscriptionInfo.number    
                if (phoneNumber.isNullOrBlank().not()) phoneNumbers.add(phoneNumber)
            }
        }
        return phoneNumbers
    }
        
    fun isFromAPI(apiLevel: Int) = Build.VERSION.SDK_INT >= apiLevel
    

    注意:为了避免 PlayConsole 中的政策违规:在 AppIntro 屏幕中,您需要有一个 PrivacyPolicy 屏幕。在隐私政策部分,您需要解释为什么您从用户那里获取电话号码。

    #SaveBangladesh

    // print phone numbers    
    getPhoneNumbers().forEach {
        val phoneNumber = it
        Log.d("DREG_PHONE", "phone number: $phoneNumber")
    }
    
    // Required Permissions: READ_PHONE_STATE, READ_PHONE_NUMBERS
    fun Context.getPhoneNumbers(): ArrayList<String> {
        val phoneNumbers = arrayListOf<String>()
        if (isFromAPI(23)) {
            val subscriptionManager = getSystemService(SubscriptionManager::class.java)
            val subsInfoList = subscriptionManager.activeSubscriptionInfoList
            for (subscriptionInfo in subsInfoList) {
                val phoneNumber =
                    if (isFromAPI(33))
                        subscriptionManager.getPhoneNumber(subscriptionInfo.subscriptionId)
                    else subscriptionInfo.number    
                if (phoneNumber.isNullOrBlank().not()) phoneNumbers.add(phoneNumber)
            }
        }
        return phoneNumbers
    }
        
    fun isFromAPI(apiLevel: Int) = Build.VERSION.SDK_INT >= apiLevel
    

    Note: To Avoid Policy Violation in PlayConsole: In AppIntro Screen, you need to have a PrivacyPolicy Screen. And in PrivacyPolicy section you need to explain why you get phone numbers from users.

    霊感 2024-09-02 01:34:44

    一点贡献。就我而言,代码引发了错误异常。我需要添加一个注释来运行代码并解决该问题。这里我让这段代码。

    public static String getLineNumberPhone(Context scenario) {
        TelephonyManager tMgr = (TelephonyManager) scenario.getSystemService(Context.TELEPHONY_SERVICE);
        @SuppressLint("MissingPermission") String mPhoneNumber = tMgr.getLine1Number();
        return mPhoneNumber;
    }
    

    A little contribution. In my case, the code launched an error exception. I have needed put an annotation that for the code be run and fix that problem. Here I let this code.

    public static String getLineNumberPhone(Context scenario) {
        TelephonyManager tMgr = (TelephonyManager) scenario.getSystemService(Context.TELEPHONY_SERVICE);
        @SuppressLint("MissingPermission") String mPhoneNumber = tMgr.getLine1Number();
        return mPhoneNumber;
    }
    
    杀手六號 2024-09-02 01:34:44

    我注意到几个答案发布了相同的内容。首先,发生了变化,onActivityResult 已被弃用,随后 HintRequest 也已被弃用。这是 2023 年未弃用的解决方案。

     private fun requestHint() {
    
        val signInClient = SignIn.getClient(this)
        val hintRequest = HintRequest.Builder()
            .setPhoneNumberIdentifierSupported(true)
            .build()
    
        val intentTask = signInClient.getSignInIntentBuilder()
            .setHintPickerConfig(hintRequest)
            .build()
    
        intentTask.addOnSuccessListener { intent ->
            val intentSenderRequest = IntentSenderRequest.Builder(intent.intentSender).build()
    
            val resultLauncher = registerForActivityResult(
                ActivityResultContracts.StartIntentSenderForResult()
            ) { result ->
                if (result.resultCode == Activity.RESULT_OK) {
                    val credential: Credential? = result.data?.getParcelableExtra(Credential.EXTRA_KEY)
                    // Phone number with country code
                    Log.i("mTag", "Selected phone No: ${credential?.id}")
                }
            }
            resultLauncher.launch(intentSenderRequest)
        }
    
        intentTask.addOnFailureListener { e ->
            // Handle the error
            Log.e("mTag", "Error retrieving hint picker intent: $e")
        }
    }
    

    注意:虽然许多人认为这可以让您检索用户的手机号码。通常情况并非如此。 Google Play 服务缓存了很少的电话号码,有时对话框会显示不属于用户的电话号码。

    文档

    I noticed several answers posting the same thing. First of all things changed, onActivityResult is deprecated followed by HintRequest which also got deprecated. Here is the non-deprecated solution from 2023.

     private fun requestHint() {
    
        val signInClient = SignIn.getClient(this)
        val hintRequest = HintRequest.Builder()
            .setPhoneNumberIdentifierSupported(true)
            .build()
    
        val intentTask = signInClient.getSignInIntentBuilder()
            .setHintPickerConfig(hintRequest)
            .build()
    
        intentTask.addOnSuccessListener { intent ->
            val intentSenderRequest = IntentSenderRequest.Builder(intent.intentSender).build()
    
            val resultLauncher = registerForActivityResult(
                ActivityResultContracts.StartIntentSenderForResult()
            ) { result ->
                if (result.resultCode == Activity.RESULT_OK) {
                    val credential: Credential? = result.data?.getParcelableExtra(Credential.EXTRA_KEY)
                    // Phone number with country code
                    Log.i("mTag", "Selected phone No: ${credential?.id}")
                }
            }
            resultLauncher.launch(intentSenderRequest)
        }
    
        intentTask.addOnFailureListener { e ->
            // Handle the error
            Log.e("mTag", "Error retrieving hint picker intent: $e")
        }
    }
    

    Note: While many of you think this allows you to retrieve user's mobile phone number. That is usually not the case. Google Play Services has cached few phone numbers and sometimes the dialog shows phone numbers in which none belongs to user.

    Documentation

    悸初 2024-09-02 01:34:44

    尽管可以拥有多个语音信箱帐户,但当使用您自己的号码拨打电话时,运营商会将您转至语音信箱。因此,TelephonyManager.getVoiceMailNumber()TelephonyManager.getCompleteVoiceMailNumber(),具体取决于您需要的风格。

    希望这有帮助。

    Although it's possible to have multiple voicemail accounts, when calling from your own number, carriers route you to voicemail. So, TelephonyManager.getVoiceMailNumber() or TelephonyManager.getCompleteVoiceMailNumber(), depending on the flavor you need.

    Hope this helps.

    以可爱出名 2024-09-02 01:34:44

    不建议使用 TelephonyManager,因为它要求应用在运行时需要 READ_PHONE_STATE 权限。

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

    应该使用 Google 的 Play 服务进行身份验证,并且它将能够允许用户选择要使用的电话号码,并处理多个 SIM 卡,而不是我们试图猜测哪一张是主 SIM 卡。

    implementation "com.google.android.gms:play-services-auth:$play_service_auth_version"
    
    fun main() {
        val googleApiClient = GoogleApiClient.Builder(context)
            .addApi(Auth.CREDENTIALS_API).build()
    
        val hintRequest = HintRequest.Builder()
            .setPhoneNumberIdentifierSupported(true)
            .build()
    
        val hintPickerIntent = Auth.CredentialsApi.getHintPickerIntent(
            googleApiClient, hintRequest
        )
    
        startIntentSenderForResult(
            hintPickerIntent.intentSender, REQUEST_PHONE_NUMBER, null, 0, 0, 0
        )
    }
    
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        when (requestCode) {
            REQUEST_PHONE_NUMBER -> {
                if (requestCode == Activity.RESULT_OK) {
                    val credential = data?.getParcelableExtra<Credential>(Credential.EXTRA_KEY)
                    val selectedPhoneNumber = credential?.id
                }
            }
        }
    }
    

    Wouldn't be recommending to use TelephonyManager as it requires the app to require READ_PHONE_STATE permission during runtime.

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

    Should be using Google's Play Service for Authentication, and it will able to allow User to select which phoneNumber to use, and handles multiple SIM cards, rather than us trying to guess which one is the primary SIM Card.

    implementation "com.google.android.gms:play-services-auth:$play_service_auth_version"
    
    fun main() {
        val googleApiClient = GoogleApiClient.Builder(context)
            .addApi(Auth.CREDENTIALS_API).build()
    
        val hintRequest = HintRequest.Builder()
            .setPhoneNumberIdentifierSupported(true)
            .build()
    
        val hintPickerIntent = Auth.CredentialsApi.getHintPickerIntent(
            googleApiClient, hintRequest
        )
    
        startIntentSenderForResult(
            hintPickerIntent.intentSender, REQUEST_PHONE_NUMBER, null, 0, 0, 0
        )
    }
    
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        when (requestCode) {
            REQUEST_PHONE_NUMBER -> {
                if (requestCode == Activity.RESULT_OK) {
                    val credential = data?.getParcelableExtra<Credential>(Credential.EXTRA_KEY)
                    val selectedPhoneNumber = credential?.id
                }
            }
        }
    }
    
    阳光①夏 2024-09-02 01:34:44

    对于 Android 版本 >= LOLLIPOP_MR1 :

    添加权限:

    并称之为:

     val subscriptionManager =
            getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE) as SubscriptionManager
        
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {
            
    val list = subscriptionManager.activeSubscriptionInfoList
            for (info in list) {
                Log.d(TAG, "number " + info.number)
                Log.d(TAG, "network name : " + info.carrierName)
                Log.d(TAG, "country iso " + info.countryIso)
            }
        }
    

    For android version >= LOLLIPOP_MR1 :

    Add permission :

    And call this :

     val subscriptionManager =
            getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE) as SubscriptionManager
        
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {
            
    val list = subscriptionManager.activeSubscriptionInfoList
            for (info in list) {
                Log.d(TAG, "number " + info.number)
                Log.d(TAG, "network name : " + info.carrierName)
                Log.d(TAG, "country iso " + info.countryIso)
            }
        }
    
    心凉怎暖 2024-09-02 01:34:44

    如果我从 voiceMailNumer 获取号码,那么它工作正常 -

    val telephonyManager = getSystemService(TELEPHONY_SERVICE) as TelephonyManager
        if (ActivityCompat.checkSelfPermission(this,
                        Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED
        ) {
            Log.d("number", telephonyManager.voiceMailNumber.toString())
        }
    

    If I'm getting number from voiceMailNumer then it is working good -

    val telephonyManager = getSystemService(TELEPHONY_SERVICE) as TelephonyManager
        if (ActivityCompat.checkSelfPermission(this,
                        Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED
        ) {
            Log.d("number", telephonyManager.voiceMailNumber.toString())
        }
    
    纵性 2024-09-02 01:34:44

    首先像这样初始化您的登录 Intent

    private val signInIntent = registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) { result ->
            try {
                val phoneNumber = Identity.getSignInClient(requireContext()).getPhoneNumberFromIntent(result.data)
                // Note phone number will be in country code + phone number format           
            } catch (e: Exception) {
            }
        }
    

    要打开 google play 意图并显示与 google 帐户关联的电话号码,请使用此

    val phoneNumberHintIntentRequest = GetPhoneNumberHintIntentRequest.builder()
                .build()
            Identity.getSignInClient(requireContext())
                .getPhoneNumberHintIntent(phoneNumberHintIntentRequest)
                .addOnSuccessListener { pendingIntent ->
                    signInIntent.launch(IntentSenderRequest.Builder(pendingIntent).build())
                }.addOnFailureListener {
                    it.printStackTrace()
                }
    

    注意

    1. 如果用户禁用电话号码共享,这将失败。如果是这样,用户必须从“设置”->“启用”。谷歌->自动填充->电话号码共享
    2. 如果您使用无法使用播放服务的模拟设备,此功能将不起作用

    Firstly Initalize your sign in Intent like this

    private val signInIntent = registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) { result ->
            try {
                val phoneNumber = Identity.getSignInClient(requireContext()).getPhoneNumberFromIntent(result.data)
                // Note phone number will be in country code + phone number format           
            } catch (e: Exception) {
            }
        }
    

    To open google play intent and show phone number associated with google account use this

    val phoneNumberHintIntentRequest = GetPhoneNumberHintIntentRequest.builder()
                .build()
            Identity.getSignInClient(requireContext())
                .getPhoneNumberHintIntent(phoneNumberHintIntentRequest)
                .addOnSuccessListener { pendingIntent ->
                    signInIntent.launch(IntentSenderRequest.Builder(pendingIntent).build())
                }.addOnFailureListener {
                    it.printStackTrace()
                }
    

    Note:

    1. This will fail if user is disabled phone number sharing. If is it so user have to enable that from Settings -> Google -> Auto-fill -> Phone Number sharing
    2. This will not working if you are using emulated device where play services is not available
    一桥轻雨一伞开 2024-09-02 01:34:44

    这适用于 SDK 33

    private void processSubscriptionManager() {
            SubscriptionManager subscriptionManager = (SubscriptionManager) getSystemService(TELEPHONY_SUBSCRIPTION_SERVICE);
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_NUMBERS) != PackageManager.PERMISSION_GRANTED ||
                    ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_PHONE_NUMBERS,
                        Manifest.permission.READ_PHONE_STATE}, 0);
                return;
            }
            List<SubscriptionInfo> subsInfoList = (List<SubscriptionInfo>) subscriptionManager.getActiveSubscriptionInfoList();
            StringBuilder number = new StringBuilder();
            for (SubscriptionInfo subscriptionInfo : subsInfoList) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                    number.append(subscriptionManager.getPhoneNumber(subscriptionInfo.getSubscriptionId())).append("\n");
                } else {
                    number.append(subscriptionInfo.getCarrierName()).append("\n");
                }
    
            }
    
            Log.d(TAG, number.toString());
            tvMobileNumber.setText("Mobile Number = " + number.toString());
        }
    

    AndroidManifest.xml

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

    This will work on SDK 33

    private void processSubscriptionManager() {
            SubscriptionManager subscriptionManager = (SubscriptionManager) getSystemService(TELEPHONY_SUBSCRIPTION_SERVICE);
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_NUMBERS) != PackageManager.PERMISSION_GRANTED ||
                    ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_PHONE_NUMBERS,
                        Manifest.permission.READ_PHONE_STATE}, 0);
                return;
            }
            List<SubscriptionInfo> subsInfoList = (List<SubscriptionInfo>) subscriptionManager.getActiveSubscriptionInfoList();
            StringBuilder number = new StringBuilder();
            for (SubscriptionInfo subscriptionInfo : subsInfoList) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                    number.append(subscriptionManager.getPhoneNumber(subscriptionInfo.getSubscriptionId())).append("\n");
                } else {
                    number.append(subscriptionInfo.getCarrierName()).append("\n");
                }
    
            }
    
            Log.d(TAG, number.toString());
            tvMobileNumber.setText("Mobile Number = " + number.toString());
        }
    

    AndroidManifest.xml

    <uses-permission android:name="android.permission.READ_PHONE_NUMBERS"/>
    
    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
    
    放手` 2024-09-02 01:34:44

    在开发一个安全应用程序时,该应用程序需要获取谁的电话号码,以便我的手机可能落入他们手中,我必须这样做;
    1. 接收启动完成,然后尝试从 telephonyManager 获取 Line1_Number,它返回字符串结果。
    2.将字符串结果与我自己的电话号码进行比较,如果不匹配或字符串返回null,
    3. 秘密发送一条包含字符串结果加上特殊符号的短信到我的办公室号码。
    4. 如果消息发送失败,则启动一个服务并每隔一小时继续尝试,直到发送的短信挂起意图返回成功。
    通过这些步骤,我可以获得使用我丢失的手机的人的号码。
    该人是否被指控并不重要。

    while working on a security app which needed to get the phone number of who so ever my phone might get into their hands, I had to do this;
    1. receive Boot completed and then try getting Line1_Number from telephonyManager which returns a string result.
    2. compare the String result with my own phone number and if they don't match or string returns null then,
    3. secretly send an SMS containing the string result plus a special sign to my office number.
    4. if message sending fails, start a service and keep trying after each hour until sent SMS pending intent returns successful.
    With this steps I could get the number of the person using my lost phone.
    it doesn't matter if the person is charged.

    ~没有更多了~
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文