一、目标
1、显示来电号码的归属地;
2、可在“设置中心”设置“是否启用来电号码归属地显示”
二、代码实现
(以服务的形式监听来电状态)
1、在项目服务包中新增一个服务类(取名ShowComingPhoneAdd,继承系统Service)用于监听来电状态,并在清单文件中注册;
2、建立TelephonyManager对象的成员变量(取名tm),用于获取手机状态;
3、在新建的服务类中复写服务的onCreate()和onDestroy方法(),用于实现当服务创建(onCreate)时监听来电状态,当服务销毁(onDestroy)时取消来电监听;
通过TelephonyManager对象(tm)的listen(PhoneStateListener listener, int events)方法监听电话状态,参数PhoneStateListener listener为电话状态监听器,需要自定义一个类继承该监听器类,详见第7步,参数int events表示监听事件,TelephonyManager.CALL_STATE_RINGING表示监听来电事件;
5、在服务销毁时(onDestroy()方法中)通过TelephonyManager对象(tm)的listen()方法和自定义监听器对象设为null来销毁监听;
6、在服务类(ShowComingPhoneAdd)中自定义电话监听器类(取名MyPhoneListener,继承PhoneStateListener),复写其onCallStateChanged(int state, String incomingNumber) 方法,表示电话状态改变时回调该方法,参数int state表示电话状态,String incomingNumber表示来电号码,在电话状态改变(onCallStateChanged())方法中:
(1)通过switch...case...语句判断电话状态state;
(2)当其值为TelephonyManager.CALL_STATE_RINGING表示电话铃声响起,则将来电号码(incomingNumber)传至号码归属地工具类(NumberAddQueryUtils)中的查询号码归属地(queryNumber())方法中,从而获得String类型的号码归属地
(3)通过Toast对象显示出来,也可以采用其他方法将归属地显示出来;
7、在清单文件中增加读取电话状态权限(READ_PHONE_STATE)
自定义电话状态监听器类代码:
1 private class MyPhoneListener extends PhoneStateListener {
2
3 //电话状态改变回调的方法
4 @Override
5 public void onCallStateChanged(int state, String incomingNumber) {
6 //state:电话状态,incomingNumber:来电号码
7 super.onCallStateChanged(state, incomingNumber);
8 switch (state) {
9 case TelephonyManager.CALL_STATE_RINGING://来电
10 String inComingPhoneAdd = NumberAddQueryUtils.queryNumber(incomingNumber);
11 Toast.makeText(getApplicationContext(), inComingPhoneAdd, Toast.LENGTH_LONG).show();
12 break;
13 default:
14 break;
15 }
16 }
17 }
View Code
onCreate方法代码:
1 //当服务创建时建立来电监听
2 @Override
3 public void onCreate() {
4 super.onCreate();
5 tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
6 //监听来电
7 listener = new MyPhoneListener();
8 tm.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
9 }
View Code
onDestroy方法代码:
1 //当服务销毁时取消来电监听
2 @Override
3 public void onDestroy() {
4 super.onDestroy();
5 tm.listen(listener,PhoneStateListener.LISTEN_NONE);
6 listener = null;
7 }
View Code
8、在“设置中心”(SettingActivity)页面的布局文件(activity_setting)中,增加一条自定义的控件(com.example.mobilesafe.ui.SettingItemView,可复制上面的控件),用于设置是否显示来电号码归属地,根据要求设置标题、内容、默认状态、id(setting_show_incoming_add)等信息;
9、在“设置中心”(SettingActivity)页面中定义自定义控件(SettingItemView,取名setting_show_incoming_add)和Intent对象(取名showAddIntent)两个成员变量;
10、Intent对象(showAddIntent)用于通过自定义控件的勾选情况启动或取消来电号码归属地显示服务(ShowComingPhoneAdd),通过new Intent(Context packageContext, Class<?> cls)实例化并通过当前上下文(参数Context packageContext,此例为this)与目标类(参数Class<?> cls,此例为来电号码归属地显示服务类(ShowComingPhoneAdd.class))关联;
11、定义自定义控件(SettingItemView)通过findViewById()找个布局文件中的自定义控件并强制,再通过setOnClickListener(OnClickListener l)为其设置点击事件,参数OnClickListener l通过new 实例化,并实现其中未实现的点击事件处理方法(onClick(View v));在点击事件处理方法onClick()中:
(1)判断自定义的“显示来电号码归属地”控件(setting_show_incoming_add)是否处于选中状态,如果是选中状态,则通过自定义控件(setting_show_incoming_add)的setChecked(boolean checked)设置其值为false,并通过stopService(Intent name)方法停止显示来电号码归属地服务,参数Intent为第10步定义的Intent对象;
(2)如果是非选中状态,则设置为true,并通过startService(Intent service)方法启动服务。
“设置中心”(SettingActivity)中来电显示代码:
1 //设置是否开启来电号码归属地显示功能
2 setting_show_incoming_add = (SettingItemView) findViewById(R.id.setting_show_incoming_add);
3 showAddIntent = new Intent(this,ShowComingPhoneAdd.class);
4 setting_show_incoming_add.setOnClickListener(new OnClickListener(){
5
6 @Override
7 public void onClick(View v) {
8 if(setting_show_incoming_add.isChecked()){
9 //设为非选中状态,取消显示来电归属地服务
10 setting_show_incoming_add.setChecked(false);
11 stopService(showAddIntent);
12 Toast.makeText(getApplicationContext(), "已停止显示来电号码归属地服务", 0).show();
13 }else {
14 //设为选中状态,启动显示来电归属地服务
15 setting_show_incoming_add.setChecked(true);
16 startService(showAddIntent);
17 Toast.makeText(getApplicationContext(), "已启动显示来电号码归属地服务", 0).show();
18 }
19 }
20
21 });
View Code