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


当前回答

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

清单

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

其他回答

这个问题没有保证的解决方案,因为电话号码不是物理地存储在所有sim卡上,也不是从网络广播到电话上。在一些需要物理地址验证的国家尤其如此,只有在验证之后才会分配号码。电话号码分配是在网络上进行的,并且可以在不改变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卡和网络运营商/手机运营商。

另外,试着在电话->设置->关于->电话身份,如果你能在那里看到号码,从上面的代码获得电话号码的概率更高。如果您不能在设置中查看电话号码,那么您将无法通过此代码获得!

建议解决方案:

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

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

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

如果我从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())
    }

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