APK: 拨号、广播监听电话的状态-TelephonyManager(电话管理器)
一、实现手机电话状态的监听,主要依靠两个类:TelephoneManger和PhoneStateListener
1.1、TelephonseManger提供了取得手机基本服务的信息的一种方式。因此应用程序可以使用TelephonyManager来探测手机基本服务的情况。
应用程序可以注册listener来监听电话状态的改变。我们不能对TelephonyManager进行实例化,只能通过获取服务的形式:
Context.getSystemService(Context.TELEPHONY_SERVICE);
注意:对手机的某些信息进行读取是需要一定许可(permission)的。
1.2、主要静态成员常量:(它们对应PhoneStateListener.LISTEN_CALL_STATE所监听到的内容)
通过PhoneStateListener的回调方法onCallStateChanged(int state, String incomingNumber) 实现来电的监听
int CALL_STATE_IDLE 空闲状态,没有任何活动。
int CALL_STATE_OFFHOOK 摘机状态,至少有个电话活动。该活动或是拨打(dialing)或是通话,或是 on hold。并且没有电话是ringing or waiting
int CALL_STATE_RINGING 来电状态,电话铃声响起的那段时间或正在通话又来新电,新来电话不得不等待的那段时间。
二、监听来电去电能干什么?
2.1、能够对监听到的电话做个标识,告诉用户这个电话是诈骗、推销、广告什么的
2.2、能够针对那些特殊的电话进行自动挂断,避免打扰到用户
三、贴代码时间
3.1、AndroidMainfest.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | <?xml version= "1.0" encoding= "utf-8" ?> <manifest xmlns:android= "http://schemas.android.com/apk/res/android" package = "com.gatsby.xhringupphone" > <!--CONTACTS 联系人--> <!--允许程序从非系统拨号器里输入电话号码--> <uses-permission android:name= "android.permission.CALL_PHONE" /> <!--允许读取手机状态的权限--> <uses-permission android:name= "android.permission.READ_PHONE_STATE" /> <!-- 允许程序读取用户联系人数据 --> <uses-permission android:name= "android.permission.READ_CONTACTS" /> <application android:allowBackup= "true" android:icon= "@mipmap/ic_launcher" android:label= "@string/app_name" android:roundIcon= "@mipmap/ic_launcher_round" android:supportsRtl= "true" android:theme= "@style/AppTheme" > <activity android:name= ".MainActivity" > <intent-filter> <action android:name= "android.intent.action.MAIN" /> <category android:name= "android.intent.category.LAUNCHER" /> </intent-filter> </activity> <receiver android:name= ".PhoneReceiver" > <!--android中的级别- 1000 ~ 1000 --> <intent-filter android:priority= "1000" > <action android:name= "android.intent.action.PHONE_STATE" /> <action android:name= "android.intent.action.NEW_OUTGOING_CALL" /> </intent-filter> </receiver> </application> </manifest> |
3.2、activity_main.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <?xml version= "1.0" encoding= "utf-8" ?> <LinearLayout xmlns:android= "http://schemas.android.com/apk/res/android" android:layout_width= "match_parent" android:layout_height= "match_parent" android:gravity= "center" android:orientation= "vertical" > <Button android:id= "@+id/btn1" android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:text= "btn1->跳转拨号应用" android:textSize= "32sp" /> <Button android:id= "@+id/btn2" android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:text= "btn2->直接拨号" android:textSize= "32sp" /> </LinearLayout> |
3.3、MainActivity.java 拨号
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | package com.gatsby.xhringupphone; import android.Manifest; import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Bundle; import android.view.View; import android.widget.Button; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import java.io.DataInputStream; import java.io.DataOutputStream; public class MainActivity extends AppCompatActivity implements View.OnClickListener { Button btn1, btn2, btn3, btn4; @Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); } public void initView() { btn1 = (Button) findViewById(R.id.btn1); btn2 = (Button) findViewById(R.id.btn2); btn1.setOnClickListener( this ); btn2.setOnClickListener( this ); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn1: //跳转到拨号应用 Uri uri = Uri.parse( "tel:10086" ); Intent intent1 = new Intent(Intent.ACTION_DIAL, uri); startActivity(intent1); break ; case R.id.btn2: call( "10086" ); break ; } } public void call(String number) { Intent intent = new Intent(Intent.ACTION_CALL); intent.setData(Uri.parse( "tel:" + number)); if (ActivityCompat.checkSelfPermission( this , Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) { // TODO: Consider calling // ActivityCompat#requestPermissions // here to request the missing permissions, and then overriding // public void onRequestPermissionsResult(int requestCode, String[] permissions, // int[] grantResults) // to handle the case where the user grants the permission. See the documentation // for ActivityCompat#requestPermissions for more details. return ; } startActivity(intent); } @Override protected void onDestroy() { super .onDestroy(); //RootCommand("pm clear com.android.dialer "); } private void RootCommand(String cmd) { Process process = null ; DataOutputStream os = null ; DataInputStream is = null ; try { process = Runtime.getRuntime().exec( "su" ); os = new DataOutputStream(process.getOutputStream()); os.writeBytes(cmd + "\n" ); os.writeBytes( "exit\n" ); os.flush(); int aa = process.waitFor(); is = new DataInputStream(process.getInputStream()); byte [] buffer = new byte [is.available()]; is.read(buffer); } catch (Exception e) { e.printStackTrace(); } finally { try { if (os != null ) { os.close(); } if (is != null ) { is.close(); } process.destroy(); } catch (Exception e) { } } } } |
3.4、PhoneReceiver.java 电话监听广播
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | package com.gatsby.xhringupphone; import android.app.Service; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; import android.util.Log; public class PhoneReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(Intent.ACTION_NEW_OUTGOING_CALL)) { String phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER); Log.d( "gatsby" , "call OUT:" + phoneNumber); } else { TelephonyManager tm = (TelephonyManager) context.getSystemService(Service.TELEPHONY_SERVICE); tm.listen(listener, PhoneStateListener.LISTEN_CALL_STATE); } } PhoneStateListener listener = new PhoneStateListener() { @Override public void onCallStateChanged( int state, String incomingNumber) { super .onCallStateChanged(state, incomingNumber); switch (state) { case TelephonyManager.CALL_STATE_IDLE: //挂断 空闲 无任何状态时 Log.d( "gatsby" , "aaaa" ); break ; case TelephonyManager.CALL_STATE_OFFHOOK: //接听 通话 接起电话时 Log.d( "gatsby" , "bbbb" ); break ; case TelephonyManager.CALL_STATE_RINGING: //响铃:来电号码 //输出来电号码 电话进来时 Log.d( "gatsby" , "cccc" ); break ; } } }; } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】