478

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

4

20 回答 20

501

代码:

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

所需权限:

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

注意事项:

根据高度评价的评论,有一些警告需要注意。这可以返回nullor""甚至"???????",并且它可以返回不再有效的陈旧电话号码。如果你想要唯一标识设备的东西,你应该getDeviceId()改用。

于 2010-03-19T20:13:18.623 回答
154

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

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

于 2011-07-22T23:50:39.473 回答
45

更新:此答案不再可用,因为 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);
}

检查actypeWhatsApp帐户

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

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

于 2013-06-15T07:05:08.050 回答
36

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

在您的 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;
    }
}

这将生成一个像这样的对话框:

在此处输入图像描述

于 2018-01-11T15:06:36.680 回答
34

正如我之前的回答中所发布的

使用以下代码:

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

在 AndroidManifest.xml 中,赋予以下权限:

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

但请记住,此代码并不总是有效,因为手机号码取决于 SIM 卡和网络运营商/手机运营商。

另外,请尝试检查Phone--> Settings --> About --> Phone Identity,如果您能够在此处查看号码,则从上述代码中获取电话号码的概率更高。如果您无法在设置中查看电话号码,那么您将无法通过此代码获取!

建议的解决方法:

  1. 获取用户的电话号码作为用户的手动输入。
  2. 通过 SMS 向用户的手机号码发送代码。
  3. 要求用户输入代码以确认电话号码。
  4. 将号码保存在 sharedpreference 中。

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

于 2014-08-05T04:11:25.157 回答
17

有一个新的 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);
} 
于 2017-10-19T12:46:36.640 回答
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

于 2011-03-05T17:35:04.307 回答
9

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

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

于 2012-05-20T22:48:41.193 回答
9

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

希望这会有所帮助,谢谢!

于 2016-02-11T18:55:12.283 回答
5

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

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

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

<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,但为此需要在 manifest 中添加读取联系人权限。

注意:- 这也不是有保证和有效的解决方案,我已经在许多设备上测试过这个解决方案,但它只适用于双 sim 设备的 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你可以验证。

  1. 如果您想识别用户的设备,为此您可以轻松获取设备 IMEI 号码。
于 2017-01-19T10:30:51.420 回答
4

这是一个更简化的答案:

public String getMyPhoneNumber()
{
    return ((TelephonyManager) getSystemService(TELEPHONY_SERVICE))
            .getLine1Number();
}
于 2011-09-19T18:31:15.447 回答
4

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

于 2014-01-07T08:40:54.577 回答
3

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

显现

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

构建.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 ""
        }
    }
}
于 2020-02-26T09:50:38.427 回答
3

添加此依赖项: 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)
        }
    }
}
于 2020-05-28T11:35:51.557 回答
1

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

public static String getLineNumberPhone(Context scenario) {
    TelephonyManager tMgr = (TelephonyManager) scenario.getSystemService(Context.TELEPHONY_SERVICE);
    @SuppressLint("MissingPermission") String mPhoneNumber = tMgr.getLine1Number();
    return mPhoneNumber;
}
于 2018-07-06T16:26:51.197 回答
1

对于 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)
        }
    }
于 2021-05-19T13:11:09.533 回答
1

我注意到有几个答案发布了相同的内容。首先,根据 2021 年所做的更改onActivityResult已被弃用。这是未弃用的解决方案。

private fun requestHint() {

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

    val intent = Credentials.getClient(this).getHintPickerIntent(hintRequest)
    val intentSender = 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(intentSender)
}

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

重要的进口com.google.android.gms.auth.api.credentials.Credential

参考文档提供了详细信息,但代码有些过时。

于 2021-09-20T16:54:09.177 回答
0

虽然可以有多个语音信箱帐户,但当您使用自己的号码拨打电话时,运营商会将您转至语音信箱。所以,TelephonyManager.getVoiceMailNumber()或者TelephonyManager.getCompleteVoiceMailNumber(),取决于你需要的味道。

希望这可以帮助。

于 2011-06-06T06:11:23.180 回答
0

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

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

应该使用 Google 的 Play Service 进行身份验证,它将能够允许用户选择要使用的电话号码,并处理多个 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
            }
        }
    }
}
于 2020-10-08T07:08:21.120 回答
-7

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

于 2016-12-21T20:14:14.363 回答