通过程序获取Android手机的电话号码

我如何通过编程方式获得正在运行我的android应用程序的设备的电话号码?

505955 次浏览

代码:

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

需要许可:

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

警告:

根据得到高度好评的评论,有一些注意事项需要注意。这可以返回null""甚至"???????",它可以返回一个过时的电话号码,不再有效。如果你想要唯一标识设备的东西,你应该使用getDeviceId()

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的代码

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

希望这能有所帮助。

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

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

这是一个更简单的答案:

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

只是想在以上回答中对以上解释做一点补充。这也会为其他人节省时间。

在我的情况下,这个方法没有返回任何手机号码,返回一个空字符串。这是由于我把我的号码移植到新的sim卡上的情况。所以如果我进入设置>关于电话>状态>我的电话号码,它显示我“未知”。

更新:这个答案不再可用,因为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,你可能不会得到它,但无论如何都值得一试。 并且记住你应该总是询问用户的确认

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

正如在我的早些时候的答案

使用以下代码:

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 . Phone——> Settings——> About——>Phone Identity,如果你能够查看那里的号码,从上面的代码获得电话号码的概率更高。如果您不能在设置中查看电话号码,那么您将无法通过此代码获得!

建议解决方案:

  1. 获取用户的电话号码作为用户的手动输入。
  2. 通过短信将代码发送到用户的手机号码。
  3. 请用户输入确认电话号码的代码。
  4. 保存在sharedpreference中。

在应用首次发布时一次性执行上述4个步骤。稍后,当需要电话号码时,使用共享首选项中可用的值。

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

希望这有帮助, 谢谢!< / p >

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

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

有以下原因,为什么我们没有得到。

1.Android设备和新的Sim卡没有存储手机号码,如果手机号码在设备和Sim卡中都不可用,那么如何获得号码,如果任何旧的Sim卡有手机号码,那么使用Telephony manager我们可以获得号码,否则它将返回“null”或“”或“??????”

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


TelephonyManager tel= (TelephonyManager)this.getSystemService(Context.
TELEPHONY_SERVICE);
String PhoneNumber =  tel.getLine1Number();
注意:-我已经在以下设备Moto x,三星Tab 4,三星S4, Nexus 5和红米2 prime上测试了这个解决方案,但它并不是每一个都有效 Time返回空字符串,所以结论是没有用

  1. 此方法仅适用于红米2 ',但为此需要添加
  2. .读取manifest中的联系人权限
注意:-这也不是保证和有效的解决方案,我已经在许多设备上测试了这个解决方案,但它只在红米2撇中工作 哪个是双卡设备它给了我两个手机号码第一个是 正确,但第二个不属于我的第二个模拟,它属于 我的一些旧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没有任何保证的解决方案

.用户的手机号码 < p > 建议: - 1。如果你想验证用户的手机号码,请问 用户提供他的号码,使用otp可以验证
  1. 如果你想识别用户的设备,你可以很容易地获得设备IMEI号。
有一个新的Android api,允许用户选择他们的电话号码,而不需要权限。来看看: https://android-developers.googleblog.com/2017/10/effective-phone-number-verification.html < / p >
// 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);
}

所以这就是你如何通过Play服务API请求一个电话号码,而没有许可和黑客。完整的示例

在你的构建中。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;
}
}

这会生成一个这样的对话框:

enter image description here

一点小小的贡献。在我的例子中,代码启动了一个错误异常。我需要把一个注释,为代码运行和修复这个问题。这里我让这段代码。

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

以下是我找到的解决方案的组合(示例项目这里<强> < / >强,如果你也想检查自动填充):

清单

    <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 ""
}
}
}
添加此依赖项: implementation 'com.google.android.gms:play-services-auth:18.0.0' < / p >

获取电话号码列表使用这个:

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

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

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

应该使用谷歌的播放服务进行身份验证,它将能够允许用户选择使用哪个phoneNumber,并处理多张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
}
}
}
}

对于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年起,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)
}

虽然很多人认为这允许你检索用户的手机号码。通常情况并非如此。谷歌播放服务缓存了几个电话号码,有时对话框显示电话号码,其中不属于用户。

一个重要的导入com.google.android.gms.auth.api.credentials.Credential

参考文档提供了详细信息,但代码有些不赞成。

如果我从voiceMailNumer中获得number,那么它工作得很好-

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

首先在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) {
}
}

要打开谷歌播放意图,并显示与谷歌帐户相关联的电话号码,请使用此

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

请注意:

  1. 如果用户禁用电话号码共享,此操作将失败。如果是这样,用户必须在设置中启用->谷歌→自动→电话号码共享
  2. 如果您正在使用播放服务不可用的模拟设备,这将不起作用