通过反射的方式挂断电话

思路:


要想挂断电话,必然会用到电话服务:getSystemService(TELEPHONY_SERVICE);

但查看源码时,发现

	@Override
    public Object getSystemService(String name) {
        return mBase.getSystemService(name);
  }


继续查找:

	 Context mBase;
    public ContextWrapper(Context base) {
        mBase = base;
    }

接着查看Context的源码

public abstract class Context {........}

崩溃了,经常使用的Context,竟然是个抽象类,那么它的具体实现呢?


这时采用断点的方式进行查找:

随便弄个测试代码,获取到要查找的对象,在下面打个断点

通过反射的方式挂断电话_第1张图片


Debug之后


通过反射的方式挂断电话_第2张图片


哦了,接着就是去找到ContextImpl类了,这个时候用到了一个搜索神器:search everything,很强大,只要你的电脑里有什么,就可以搜到什么。

本人已经在CSDN上传了该工具,这里是链接,想下的朋友可以去瞅瞅http://download.csdn.net/detail/xushuaic/5346268



通过反射的方式挂断电话_第3张图片



右键open path,就可以找到了。

打开ContextImpl,接着又开始犯愁了,该从哪找起呢,两千多行代码,疯了,

既然咱们是要找Service的,只是跟踪的时候跟到了ContextImpl,那么它一定有getSystemService()的方法,Ctrl+F查找,一下就定位到来,往下看几行,一大串类似于下面的代码


 private AccountManager getAccountManager() {
        synchronized (mSync) {
            if (mAccountManager == null) {
                IBinder b = ServiceManager.getService(ACCOUNT_SERVICE);
                IAccountManager service = IAccountManager.Stub.asInterface(b);
                mAccountManager = new AccountManager(this, service);
            }
            return mAccountManager;
        }
  }
  


从这就可以推断出,咱要想获取服务,就得使用ServiceManager,那么哦了,回到我们自己的代码中调用: ServiceManager.getService(TELEPHONY_SERVICE);

发现报错,原因是,该类是放在android.os.ServiceManager包中的,对于一些重要的服务,Android工程师是不希望我们自己直接拿到的,不让咱拿咱偏要拿,只好使用暴力了,这时候二话不说,上反射,使用反射得到了getService方法之后,根据上面的代码,照葫芦画瓢,很容易能写出下面的代码:


Class ServiceManager = getClass().getClassLoader().loadClass(
						"android.os.ServiceManager");

Method getServiceMethod = ServiceManager.getMethod(
						"getService", new String[] {String.class});

IBinder ibinder = (IBinder) getServiceMethod.invoke(null,
						new String[] { TELEPHONY_SERVICE });

//TELEPHONY 比对 ACCOUNT_SERVICE,也可以去找到ITelephony 
ITelephony itelephony = ITelephony.Stub.asInterface(ibinder);
				itelephony.endCall();



如果对AIDL不太了解的朋友,可以看看笔者的另一篇博客http://blog.csdn.net/xushuaic/article/details/8559022


通过ITelephony.Stub.asInterface 就能看出一定是AIDL的通信,那么必须使用到AIDL协议,而且该协议文件的名称就是ITelephony,那么easySearch Everything,又哦了,新建一个包,将ITelephony.aidl放进去,本以为这样就哦了,谁知道又报错,找到红叉叉,鼠标移上去





没问题,Search一把

通过反射的方式挂断电话_第4张图片


找到,Ctrl+CCtrl+V一把,导入包,终于没有红叉叉了,大功告成

注意包的创建,如果你把两个两个文件放错包了,不好意思,eclipse可不客气



正解


又错喽


下面是结束电话的服务,只要在另一个Activity中开启该服务,那么就可以自动地挂断指定的电话了,这里有的朋友一定会发现,这不就是黑名单拦截么,哦了,黑名单拦截就是这样的原理,只要提供一个黑名单的数据库,当来电的时候,到数据库里去查找然后进行判断就可以


记得权限:

<!-- 监听电话状态 -->
   <uses-permission android:name="android.permission.READ_PHONE_STATE" />

注册服务 

<service android:name="com.example.service.EndCallService" ></service>

结束电话的服务

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import com.android.internal.telephony.ITelephony;

import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.provider.CallLog;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;

public class EndCallService extends Service {
	private static final String TAG = "EndCallService";
	private TelephonyManager telephonyManager;
	private MyPhoneListener listener;
	private Intent callSmsSafeService;

	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}

	@Override
	public void onCreate() {
		Log.i(TAG,"启动服务");
		// 开启电话拦截服务
		telephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
		listener = new MyPhoneListener();
		telephonyManager.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
		super.onCreate();
	}

	@Override
	public void onDestroy() {
		// 取消电话监听服务
		telephonyManager.listen(listener, PhoneStateListener.LISTEN_NONE);
		listener = null;
		super.onDestroy();
	}

	// 自定义电话状态监听
	class MyPhoneListener extends PhoneStateListener {

		@Override
			public void onCallStateChanged(int state, String incomingNumber) {
				super.onCallStateChanged(state, incomingNumber);

				switch (state) {
				case TelephonyManager.CALL_STATE_RINGING:
					Log.i(TAG, "电话到来" + incomingNumber);
				
					if ("10086".equals(incomingNumber)) {// 拦截电话
						Log.i(TAG, "挂断电话" + incomingNumber);
						endCall();
					break;
				}
			}
		}

		// 挂断电话功能的API隐藏了,无法直接获取服务,通过反射
		private void endCall() {

			// ServiceManager.getService(TELEPHONY_SERVICE);
			getSystemService(TELEPHONY_SERVICE);
			try {

Class ServiceManager = getClass().getClassLoader().loadClass(
						"android.os.ServiceManager");
				Method getServiceMethod = ServiceManager.getMethod(
						"getService", String.class);

IBinder ibinder = (IBinder) getServiceMethod.invoke(null,
						new String[] { TELEPHONY_SERVICE });

ITelephony iTelephony = ITelephony.Stub.asInterface(ibinder);
				iTelephony.endCall();

Log.i(TAG, "end call-------------");
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			} catch (NoSuchMethodException e) {
				e.printStackTrace();
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				e.printStackTrace();
			} catch (RemoteException e) {
				e.printStackTrace();
			}
		}
	}
}



你可能感兴趣的:(通过反射的方式挂断电话)