需要用Aidl,来与系统进程进行交互
(关于aidl的介绍:
http://chenfeng0104.iteye.com/blog/1255302
http://www.cnblogs.com/mydomainlistentome/p/4687173.html)
首先在src下建立这样的包:
com.android.internal.telephony
然后在这个包下建立这样的aidl文件:
ITelephony.aidl
package com.android.internal.telephony ; interface ITelephony { boolean endCall() ; // 挂断电话 void answerRingingCall() ; // 拨打电话 }
利用反射,在后台打印出隐藏的可以挂断电话的private类型的方法
private ITelephony getITelephony() { ITelephony iTelephony=null; Class<TelephonyManager> cls=TelephonyManager.class; Method [] method= cls.getDeclaredMethods(); for(int i=0;i<method.length;i++){ System.out.println("方法:"+method[i]); }
找到这个方法:
I/System.out(1406): 方法:private com.android.internal.telephony.ITelephony android.telephony.TelephonyManager.getITelephony() 07-31 21:59:27.522: I/System.out(1406): 方法:public static int android.telephony.TelephonyManager.getLteOnCdmaModeStatic() 07-31 21:59:27.522: I/System.out(1406): 方法:public static int android.telephony.TelephonyManager.getNetworkClass(int) 07-31 21:59:27.522: I/System.out(1406): 方法:public static java.lang.String android.telephony.TelephonyManager.getNetworkTypeName(int) 07-31 21:59:27.522: I/System.out(1406): 方法:public static int android.telephony.TelephonyManager.getPhoneType(int) 07-31 21:59:27.522: I/System.out(1406): 方法:private int android.telephony.TelephonyManager.getPhoneTypeFromNetworkType()
然后将这个方法解封,调用
private ITelephony getITelephony() { ITelephony iTelephony = null; Class<TelephonyManager> cls = TelephonyManager.class; Method method = null; // Method [] method= cls.getDeclaredMethods(); // for(int i=0;i<method.length;i++){ // System.out.println("方法:"+method[i]); // } try { method = cls.getDeclaredMethod("getITelephony"); // 取消封装 method.setAccessible(true); } catch (NoSuchMethodException e) { e.printStackTrace(); } try { // 使用invoke来执行这个私有方法 iTelephony = (ITelephony) method.invoke(telephone); return iTelephony; } catch (Exception e) { e.printStackTrace(); } return iTelephony; }
解决以上的问题就可以实现电话拦截了,下面是全部代码:
service实现挂断:
package com.example.phonelistendemo; import java.lang.reflect.Method; import com.android.internal.telephony.ITelephony; import android.app.Service; import android.content.Intent; import android.media.AudioManager; import android.os.Binder; import android.os.IBinder; import android.os.RemoteException; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; public class ServicePhone extends Service { private TelephonyManager telephone = null; private AudioManager audio = null; private IBinder mbinder = new BinderImpl(); private String num = null; public void onCreate() { super.onCreate(); } @Override public void onDestroy() { mbinder = null; num = null; super.onDestroy(); } public class BinderImpl extends Binder implements IService { @Override public String getInterfaceDescriptor() { return "过滤电话:“" + ServicePhone.this.num + "”设置成功!"; } } public IBinder onBind(Intent arg0) { audio = (AudioManager) getSystemService(AUDIO_SERVICE); num = arg0.getStringExtra("Nums"); telephone = (TelephonyManager) getSystemService(TELEPHONY_SERVICE); backGroundExecution(); return mbinder; } // 启动子线程 public void backGroundExecution() { Thread thread = new Thread(null, backGroundProgress, "phoneListener"); thread.start(); } // 实例化子线程 private Runnable backGroundProgress = new Runnable() { public void run() { telephone.listen(new PhoneStateListenerImpl(), PhoneStateListener.LISTEN_CALL_STATE); } }; private class PhoneStateListenerImpl extends PhoneStateListener { public void onCallStateChanged(int state, String incomingNumber) { switch (state) { case TelephonyManager.CALL_STATE_RINGING: if (incomingNumber.equals(num)) { ITelephony iTelephony=getITelephony(); if(iTelephony!=null){ try { //挂断电话 iTelephony.endCall(); } catch (RemoteException e) { e.printStackTrace(); } } } break; case TelephonyManager.CALL_STATE_OFFHOOK: break; case TelephonyManager.CALL_STATE_IDLE:
//挂断提示音开启
//audio.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
break;
} } } private ITelephony getITelephony() { ITelephony iTelephony = null; Class<TelephonyManager> cls = TelephonyManager.class; Method method = null; // Method [] method= cls.getDeclaredMethods(); // for(int i=0;i<method.length;i++){ // System.out.println("方法:"+method[i]); // } try { method = cls.getDeclaredMethod("getITelephony"); // 取消封装 method.setAccessible(true); } catch (NoSuchMethodException e) { e.printStackTrace(); } try { // 使用invoke来执行这个私有方法 iTelephony = (ITelephony) method.invoke(telephone); return iTelephony; } catch (Exception e) { e.printStackTrace(); } return iTelephony; } }
broadcastReceive 接收电话状态
package com.example.phonelistendemo; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; public class ReceivePhone extends BroadcastReceiver { public void onReceive(Context content, Intent intent) { // 拨打电话 if (Intent.ACTION_NEW_OUTGOING_CALL.equals(intent.getAction())) { Intent in=new Intent(content,ServicePhone.class); content.startService(in); } else{ Intent in=new Intent(content, ServicePhone.class); content.startService(in); } } }
定义IService接口 标记绑定状态
package com.example.phonelistendemo; public interface IService { }
MainActivity
package com.example.phonelistendemo; import android.app.Activity; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; import com.example.phonelisten_Limite.R; import com.example.phonelisten_Limite.R.id; import com.example.phonelistendemo.ServicePhone.BinderImpl; public class MainActivity extends Activity { private Button bind, unBind; private EditText num; private ServiceConnection connect; private IService service; private String getNum; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); connect=new ServiceConnection() { public void onServiceDisconnected(ComponentName arg0) { } public void onServiceConnected(ComponentName arg0, IBinder arg1) { MainActivity.this.service=(BinderImpl)arg1; try { Toast.makeText(MainActivity.this, arg1.getInterfaceDescriptor(), Toast.LENGTH_LONG).show(); } catch (RemoteException e) { e.printStackTrace(); } } }; init(); } private void init() { bind = (Button) findViewById(R.id.bind); unBind = (Button) findViewById(id.unBind); num = (EditText) findViewById(id.num); bind.setOnClickListener(new BindListenImpl()); unBind.setOnClickListener(new UnBindListenImpl()); } public class BindListenImpl implements OnClickListener { public void onClick(View arg0) { getNum=num.getText().toString(); Intent intent=new Intent(MainActivity.this,ServicePhone.class); intent.putExtra("Nums", getNum); bindService(intent, connect, BIND_AUTO_CREATE); } } public class UnBindListenImpl implements OnClickListener { public void onClick(View arg0) { if(MainActivity.this.service != null) { unbindService(connect) ; stopService(new Intent(MainActivity.this,ServicePhone.class)) ; getNum=null; Toast.makeText(MainActivity.this, "黑名单已取消", Toast.LENGTH_LONG) .show(); MainActivity.this.service = null ; } } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } }
权限配置
<uses-permission android:name="android.permission.CALL_PHONE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
广播配置:
<receiver android:name="com.example.phonelistendemo.ReceivePhone">
<intent-filter android:priority="999" >
<action android:name="android.intent.action.PHONE_STATE" />
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter>
</receiver>
布局自行解决
(ps:我是菜鸟,勿喷,谢谢)