目录
1.需求描述
2.实现原理
第一个:手机来电状态
第二个:获取手机来电号码
第三个:接听和挂断电话
1.需求描述
监听用户手机来电,弹起App内自定义的来电展示,并且展示来电电话,用户可以接通和挂断。
2.实现原理
这儿我就总结下手机来电、获取手机号码和接听/挂断电话,弹起App的来电展示界面使用的windowmanager。
第一个:手机来电状态
权限
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.ANSWER_PHONE_CALLS" />//接/挂电话需要这个权限
private lateinit var telephonyManager: TelephonyManager
private lateinit var mPhoneListener: PhoneStateListener
//在你的onCreate里
......
telephonyManager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
//在注册监听的时候就会走一次回调,后面通话状态改变时也会走
//如下面的代码,在启动服务时如果手机没有通话相关动作,就会直接走一次TelephonyManager.CALL_STATE_IDLE
mPhoneListener = object : PhoneStateListener() {
override fun onCallStateChanged(state: Int, phoneNumber: String?) {
super.onCallStateChanged(state, phoneNumber)
when (state) {
//挂断
TelephonyManager.CALL_STATE_IDLE -> {
//toast("挂断${phoneNumber}")
Log.i("TAG", "onCallStateChanged: 挂断${phoneNumber}")
}
//接听
TelephonyManager.CALL_STATE_OFFHOOK -> {
Log.i("TAG", "onCallStateChanged: 接听${phoneNumber}")
}
//响铃
TelephonyManager.CALL_STATE_RINGING -> {
Log.i("TAG", "onCallStateChanged: 响铃${phoneNumber}")
LogUtils.e("来电${getLatestIncomingCallNumber(contentResolver)}")
}
}
}
}
telephonyManager.listen(mPhoneListener, PhoneStateListener.LISTEN_CALL_STATE)
......
这样就可以实时监听手机来电
第二个:获取手机来电号码
权限:
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.WRITE_CALL_LOG" />
@SuppressLint("Range")
private fun getLatestIncomingCallNumber(contentResolver: ContentResolver?): String? {
var phoneNumber: String? = null
var cursor: Cursor? = null
try {
if (contentResolver != null) {
cursor = contentResolver.query(
CallLog.Calls.CONTENT_URI, arrayOf(CallLog.Calls.NUMBER),
CallLog.Calls.TYPE + " = " + CallLog.Calls.INCOMING_TYPE,
null,
CallLog.Calls.DATE + " DESC"
)
if (cursor != null && cursor.moveToFirst()) {
phoneNumber = cursor.getString(cursor.getColumnIndex(CallLog.Calls.NUMBER))
}
}
} finally {
cursor?.close()
}
return phoneNumber
}
说实话,现在手机系统的来电展示不错了,所以这种App需要足够做的花哨好用才行,但是这又涉及用户的敏感权限和应用市场的卡脖子。emmm,不知道他的前景是什么?
第三个:接听和挂断电话
之前看了许多博客,结果发现,很多都是1几年的文章,很多方法都已经被废弃了,或者不适配高版本的android系统,于是去查了查开发者和stack overflow,emmmm,目前这个方法可行
首先是接电话,使用telecomManager,之前是telephonyManager?已经没有acceptRingingCall这个方法了。
private fun answerCall() {
val telecomManager =
this.getSystemService(Context.TELECOM_SERVICE) as TelecomManager
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ANSWER_PHONE_CALLS
) == PackageManager.PERMISSION_GRANTED
) {
telecomManager.acceptRingingCall()
LogUtils.e("telecomManager.接电话() finish")
}
}
其次是挂掉电话:
挂掉电话要根据android版本来做个适配:
fun userClickToEndCall(context: Context): Boolean {
var callSuccess = false
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
val telecomManager =
context.getSystemService(Context.TELECOM_SERVICE) as TelecomManager
if (ActivityCompat.checkSelfPermission(
context, Manifest.permission.ANSWER_PHONE_CALLS
) == PackageManager.PERMISSION_GRANTED
) {
telecomManager.endCall()
callSuccess = true
Log.d(TAG, "telecomManager.endCall() finish")
} else {
ToastUtils.showShort("No Permission!")
}
} else {
val tm = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
val c = Class.forName(tm.javaClass.name)
val m: Method = c.getDeclaredMethod("getITelephony")
m.isAccessible = true
val telephonyService: ITelephony = m.invoke(tm) as ITelephony
callSuccess = telephonyService.endCall()
Log.d(TAG, " telephonyService.endCall finish")
}
} catch (e: Exception) {
Log.d(TAG, "Exception error: " + e.message)
callSuccess = disconnectCall()
e.printStackTrace()
}
return callSuccess
}
private fun disconnectCall(): Boolean {
try {
Log.d(TAG, "input keyevent " + KeyEvent.KEYCODE_ENDCALL)
Runtime.getRuntime().exec(
"input keyevent " + KeyEvent.KEYCODE_ENDCALL.toString()
) //KEYCODE_HEADSETHOOK
} catch (exc: Exception) {
Log.d(TAG, "exc.printStackTrace")
exc.printStackTrace()
return false
}
return true
}
上面当Android版本大于9时,使用telecomManager.endCall()
小于Android9时,利用反射的原理来调用方法,因为Api接口不公开了,调用不了。文章来源:https://www.toymoban.com/news/detail-529462.html
1.获取TelephonyManager
2.获取TelephonyManager.class
3.反射调用TelephonyManager的 getITelephony方法获取ITelephony
4.挂断电话ITelephony.endCall文章来源地址https://www.toymoban.com/news/detail-529462.html
到了这里,关于Android 手机来电 获取来电信息,接听/挂断电话的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!