本实例允许用户动态添加号码到黑名单,并实现黑名单来电自动挂断。程序通过创建PhoneStateListener监听器来监听TelephonyManager的通话状态来实现该功能。
由于自Android 10之后Android不再对外公开挂断电话的API,如果需要挂断电话必须使用AIDL与电话管理Service进行通信,并调用服务中的API实现结束电话。
为了调用远程的AIDL Service,开发者需要将Android源码中的如下两个文拷到指定位置:
com.android.internal.telephony包下的ITelephony.aidl
android.telephony包下的NeighboringCellInfo.aidl
这样就会在gen文件夹下生成相应的.Java文件。
另外调用API的方法如果有不解的地方可以参考:Class.forName()的作用与使用总结
另外本实例使用BaseAdapter作为ListView的适配器,BaseAdapter具有很强的定制型。
演示图片:
程序代码:
package com.jph.callguard;
import java.lang.reflect.Method;
import java.util.ArrayList;
import com.android.internal.telephony.ITelephony;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.ContactsContract;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ListView;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.database.Cursor;
/**
* Describe:</br>
* 黑名单自动挂断
* 本实例实现了获取联系人,并将选中的联系人添加到黑名单中
* 并通过ITelephony.aidl与NeighboringCellInfo.aidl
* 接口使用AIDL与电话管理Servic进行通信挂断黑名单中的电话
* @author jph
* Time:2014.07.24
* */
public class CallGuard extends Activity {
Button btnManage;
TelephonyManager tManager;
//创建一个集合用于保存黑名单中的号码
ArrayList<String>blockList=new ArrayList<String>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btnManage=(Button)findViewById(R.id.btnManage);
tManager=(TelephonyManager) getSystemService(TELEPHONY_SERVICE);
//创建电话状态监听器
PhoneStateListener pStateListener=new PhoneStateListener(){
@Override
public void onCallStateChanged(int state, String incomingNumber) {
// TODO Auto-generated method stub
switch (state) {
case TelephonyManager.CALL_STATE_IDLE://空闲状态不做处理
break;
case TelephonyManager.CALL_STATE_OFFHOOK://接起电话不做处理
break;
case TelephonyManager.CALL_STATE_RINGING://正在响铃
//如果来电号码在黑名单中则自动挂断
if (isBlock(incomingNumber)) {
try {
//获取android.os.ServiceManager类的对象的getService()方法
Method method=Class.forName("android.os.ServiceManager").
getMethod("getService",String.class);
// 获取远程TELEPHONY_SERVICE的IBinder对象的代理
IBinder binder =(IBinder)method.invoke(null, new Object[] {TELEPHONY_SERVICE});
// 将IBinder对象的代理转换为ITelephony对象
ITelephony telephony=ITelephony.Stub.asInterface(binder);
//挂断电话
telephony.endCall();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
break;
}
super.onCallStateChanged(state, incomingNumber);
}
};
//为TelephonyManager添加监听器
tManager.listen(pStateListener, PhoneStateListener.LISTEN_CALL_STATE);
btnManage.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
//查询通信录中的电话号码
final Cursor cursor=getContentResolver().query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null, null, null, null);
//创建一个BaseAdapter作为ListView的适配器
BaseAdapter adapter=new BaseAdapter() {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
//将游标的指针移动到指定位置
cursor.moveToPosition(position);
CheckBox box=new CheckBox(CallGuard.this);
//获取指定位置的电话号码
String number=cursor.getString(cursor.getColumnIndex(
ContactsContract.CommonDataKinds.Phone.NUMBER));
//去掉电话号码中间的中划线、空格
number.replace("-", "").replace(" ", "");
box.setText(number);
//如果该号码已经被加入黑名单、默认勾选该号码
if (isBlock(number)) {
box.setChecked(true);
}
return box;
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}
//返回列表的总条数
@Override
public int getCount() {
// TODO Auto-generated method stub
return cursor.getCount();
}
};
//加载line布局文件
View view=getLayoutInflater().inflate(R.layout.line, null);
//获取line布局文件中Id为list的组件
final ListView list=(ListView)view.findViewById(R.id.list);
list.setAdapter(adapter);
new AlertDialog.Builder(CallGuard.this).setView(view).setPositiveButton("确定",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
blockList.clear();
for (int i = 0; i < list.getCount(); i++) {
CheckBox box=(CheckBox)list.getChildAt(i);
//如果联系人被选中则将其添加到blockList集合
if (box.isChecked()) {
blockList.add(box.getText().toString());
}
}
}
}).show();
}
});
}
private boolean isBlock(String number) {
// TODO Auto-generated method stub
//判断号码是否在blockList集合中
for (String s:blockList) {
if (s.equals(number)) {
return true;
}
}
return false;
}
}
最后别忘添加相应的权限:
AndroidManifest.xml
<!-- 授予该应用控制通话的权限 -->
<uses-permission android:name="android.permission.CALL_PHONE" />
<!-- 授予该应用读取通话状态的权限 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!-- 授予读联系人ContentProvider的权限 -->
<uses-permission android:name="android.permission.READ_CONTACTS" />
<!-- 授予写联系人ContentProvider的权限 -->
<uses-permission android:name="android.permission.WRITE_CONTACTS" />