本实例允许用户动态添加号码到黑名单,并实现黑名单来电自动挂断。程序通过创建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" />