Android 来去电监听,电话挂断

<receiver android:name=“.PhoneStateReceiver”

android:enabled=“true”

android:process=“:PhoneListenService”>

public class PhoneStateReceiver extends BroadcastReceiver {

@Override

public void onReceive(Context context, Intent intent) {

if (intent.getAction().equals(Intent.ACTION_NEW_OUTGOING_CALL)) {

// 去电,可以用定时挂断

} else {

//来电

String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);

Log.d(PhoneListenService.TAG, "PhoneStateReceiver onReceive state: " + state);

if (state.equalsIgnoreCase(TelephonyManager.EXTRA_STATE_RINGING)) {

Log.d(PhoneListenService.TAG, “PhoneStateReceiver onReceive endCall”);

HangUpTelephonyUtil.endCall(context);

}

}

}

}

三. 实战,有什么需要特别注意地方


3.1 双卡双待的手机怎么获取

对于双卡手机,每张卡都对应一个 Service 和一个 PhoneStateListener,需要给每个服务注册自己的 PhoneStateListener,服务的名称还会有点变化,厂商可能会修改

public ArrayList getMultSimCardInfo() {

// 获取双卡的信息,这个也是经验尝试出来的,不知道其他厂商有什么坑

ArrayList phoneServerList = new ArrayList();

for(int i = 1; i < 3; i++) {

try {

String phoneServiceName;

if (MiuiUtils.isMiuiV6()) {

phoneServiceName = “phone.” + String.valueOf(i-1);

} else {

phoneServiceName = “phone” + String.valueOf(i);

}

// 尝试获取服务看是否能获取到

IBinder iBinder = ServiceManager.getService(phoneServiceName);

if(iBinder == null) continue;

ITelephony iTelephony = ITelephony.Stub.asInterface(iBinder);

if(iTelephony == null) continue;

phoneServerList.add(phoneServiceName);

} catch(Exception e) {

e.printStackTrace();

}

}

// 这个是默认的

phoneServerList.add(Context.TELEPHONY_SERVICE);

return phoneServerList;

}

3.2 挂断电话

挂断电话使用系统服务提供的接口去挂断,但是挂断电话是个并不能保证成功的方法,所以会有多种方式挂断同时使用,下面提供

package com.phone.listen;

import android.content.Context;

import android.os.RemoteException;

import android.telephony.TelephonyManager;

import com.android.internal.telephony.ITelephony;

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;

import java.util.concurrent.Executor;

import java.util.concurrent.Executors;

/**

  • 封装挂断电话接口

*/

public class HangUpTelephonyUtil {

public static boolean endCall(Context context) {

boolean callSuccess = false;

ITelephony telephonyService = getTelephonyService(context);

try {

if (telephonyService != null) {

callSuccess = telephonyService.endCall();

}

} catch (RemoteException e) {

e.printStackTrace();

} catch (Exception e){

e.printStackTrace();

}

if (callSuccess == false) {

Executor eS = Executors.newSingleThreadExecutor();

eS.execute(new Runnable() {

@Override

public void run() {

disconnectCall();

}

});

callSuccess = true;

}

return callSuccess;

}

private static ITelephony getTelephonyService(Context context) {

TelephonyManager telephonyManager = (TelephonyManager)

context.getSystemService(Context.TELEPHONY_SERVICE);

Class clazz;

try {

clazz = Class.forName(telephonyManager.getClass().getName());

Method method = clazz.getDeclaredMethod(“getITelephony”);

method.setAccessible(true);

return (ITelephony) method.invoke(telephonyManager);

} 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();

}

return null;

}

private static boolean disconnectCall() {

Runtime runtime = Runtime.getRuntime();

try {

runtime.exec(“service call phone 5 \n”);

} catch (Exception exc) {

exc.printStackTrace();

return false;

}

return true;

}

// 使用 endCall 挂断不了,再使用 killCall 反射调用再挂一次

public static boolean killCall(Context context) {

try {

// Get the boring old TelephonyManager

TelephonyManager telephonyManager = (TelephonyManager)

context.getSystemService(Context.TELEPHONY_SERVICE);

// Get the getITelephony() method

Class classTelephony = Class.forName(telephonyManager.getClass().getName());

Method methodGetITelephony = classTelephony.getDeclaredMethod(“getITelephony”);

// Ignore that the method is supposed to be private

methodGetITelephony.setAccessible(true);

// Invoke getITelephony() to get the ITelephony interface

Object telephonyInterface = methodGetITelephony.invoke(telephonyManager);

// Get the endCall method from ITelephony

Class telephonyInterfaceClass = Class.forName(telephonyInterface.getClass().getName());

Method methodEndCall = telephonyInterfaceClass.getDeclaredMethod(“endCall”);

// Invoke endCall()

methodEndCall.invoke(telephonyInterface);

} catch (Exception ex) { // Many things can go wrong with reflection calls

return false;

}

return true;

}

}

ITelephony 接口在 layoutlib.jar 包中,需要导入 android sdk 目录\platforms\android-8\data\layoutlib.jar

挂断电话需要权限

3.3 监听来去电状态放到后台服务(独立进程)

<service android:name=“.PhoneListenService”

android:label=“Android 来电监听”

android:process=“:PhoneListenService”/>

来去电监听 Service

package com.phone.listen;

import android.app.Service;

import android.content.Context;

import android.content.Intent;

import android.os.IBinder;

import android.telephony.PhoneStateListener;

import android.telephony.TelephonyManager;

import android.util.Log;

/**

  • 来去电监听服务

*/

public class PhoneListenService extends Service {

public static final String TAG = PhoneListenService.class.getSimpleName();

public static final String ACTION_REGISTER_LISTENER = “action_register_listener”;

@Override

public void onCreate() {

super.onCreate();

Log.d(TAG, “onCreate”);

}

@Override

public int onStartCommand(Intent intent, int flags, int startId) {

Log.d(TAG, "onStartCommand action: " + intent.getAction() +

" flags: " + flags + " startId: " + startId);

String action = intent.getAction();

if (action.equals(ACTION_REGISTER_LISTENER)) {

registerPhoneStateListener();

}

return super.onStartCommand(intent, flags, startId);

}

private void registerPhoneStateListener() {

CustomPhoneStateListener customPhoneStateListener = new CustomPhoneStateListener(this);

TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);

if (telephonyManager != null) {

telephonyManager.listen(customPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);

}

}

}

最后

**要想成为高级安卓工程师,必须掌握许多基础的知识。**在工作中,这些原理可以极大的帮助我们理解技术,在面试中,更是可以帮助我们应对大厂面试官的刁难。


加入社区》https://bbs.youkuaiyun.com/forums/4304bb5a486d4c3ab8389e65ecb71ac0

TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);

if (telephonyManager != null) {

telephonyManager.listen(customPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);

}

}

}

最后

**要想成为高级安卓工程师,必须掌握许多基础的知识。**在工作中,这些原理可以极大的帮助我们理解技术,在面试中,更是可以帮助我们应对大厂面试官的刁难。


[外链图片转存中…(img-rS3h40wY-1725661379152)]

[外链图片转存中…(img-Gv7EzqiM-1725661379152)]

加入社区》https://bbs.youkuaiyun.com/forums/4304bb5a486d4c3ab8389e65ecb71ac0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值