安卓 来电状态监听、去电监听

 电话状态(来电、接听、挂断、拨打电话)监听逻辑:

package com.sc.call;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;


/**
 * CallListener.java: 来电状态监听、去电监听。
 * 用法:创建CallListener实例,并重写电话相关的四个abstract抽象函数即可。
 * new CallListener(context){...};
 * 
 * 需要添加权限:
 * uses-permission android:name="android.permission.READ_PHONE_STATE" 
 * uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"
 * -----
 * 2019-1-9 上午10:16:06
 * scimence 
 */
public abstract class CallListener
{
	CallListener Instance;
	
	CallInListener callin;		// 来电监听
	OutCallListener callout;	// 拨出监听
	
	public CallListener(Context context)
	{
		Instance = this;
		callin = new CallInListener(context)
		{
			@Override
			public void Ringing(String phoneNumber)
			{
				Instance.Ringing(phoneNumber);
			}
			
			@Override
			public void OffHook(String phoneNumber)
			{
				Instance.OffHook(phoneNumber);
			}
			
			@Override
			public void HungUp(String phoneNumber)
			{
				Instance.HungUp(phoneNumber);
			}
		};
		
		callout = new OutCallListener(context)
		{
			@Override
			public void OutCall(String phoneNumber)
			{
				Instance.OutCall(phoneNumber);
			}
		};
	}
	
	/** 响铃时执行逻辑 */
	public abstract void Ringing(String phoneNumber);
	
	/** 接听时执行逻辑 */
	public abstract void OffHook(String phoneNumber);
	
	/** 挂断时执行逻辑 */
	public abstract void HungUp(String phoneNumber);
	
	/** 去电时执行逻辑 */
	public abstract void OutCall(String phoneNumber);
}

/**
 * 来电状态监听。
 * 
 * <uses-permission android:name="android.permission.READ_PHONE_STATE" />
 * */
abstract class CallInListener extends PhoneStateListener
{
	TelephonyManager phoneManager;
	public CallInListener(Context context)
	{
		phoneManager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
		Listen();
	}
	
	/** 监听来电状态 */
	public void Listen()
	{
		phoneManager.listen(this, PhoneStateListener.LISTEN_CALL_STATE);	// 在系统服务上,为当前Listener注册CALL_STATE状态监听
	}
	
	/** 不再监听 */
	public void ClearListen()
	{
		phoneManager.listen(this, PhoneStateListener.LISTEN_NONE);
	}
	
	/** 重写监听来电状态 */
	public void onCallStateChanged(int state, String phoneNumber)
	{
		if(state == TelephonyManager.CALL_STATE_IDLE)			// 空闲/挂断
		{
			HungUp(phoneNumber);
		}
		else if(state == TelephonyManager.CALL_STATE_RINGING)	// 响铃
		{
			Ringing(phoneNumber);
		}
		else if(state == TelephonyManager.CALL_STATE_OFFHOOK)	// 接听
		{
			OffHook(phoneNumber);
		}
	}
	
	/** 响铃时执行逻辑 */
	public abstract void Ringing(String phoneNumber);
	
	/** 接听时执行逻辑 */
	public abstract void OffHook(String phoneNumber);
	
	/** 挂断时执行逻辑 */
	public abstract void HungUp(String phoneNumber);
	
}


/**
 * 去电监听。
 * 
 * <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
 * */
abstract class OutCallListener extends BroadcastReceiver
{
	Context context;
	public OutCallListener(Context context)
	{
		this.context = context;
		Listen();
	}

	/** 监听来电状态 */
	public void Listen()
	{
		IntentFilter intentFilter = new IntentFilter(Intent.ACTION_NEW_OUTGOING_CALL);
		context.registerReceiver(this, intentFilter);
	}
	
	/** 不再监听 */
	public void ClearListen()
	{
		context.unregisterReceiver(this);
	}
	
	/** 重写监听去电事件 */
	public void onReceive(Context context, Intent intent)
	{
		String phoneNumber = getResultData();
		OutCall(phoneNumber);
	}
	
	/** 去电时执行逻辑 */
	public abstract void OutCall(String phoneNumber);
}


简易调用:(引入CallProcess.jar,改写CallProcess.java)

CallProcess.jar下载


package com.sc.call;

//import java.util.ArrayList;

import android.content.Context;
import android.widget.Toast;

//
// 整体调用逻辑:
// (1)从BroadCast_Start广播接收到的系统事件(开机、锁屏等)启动服务CallService;
// (2)在CallService中添加来电、拨出事件监听,在监听到电话事件(来电、接听、挂断、拨打电话)后进行事件处理
// (3)在CallService中调用CallProcess中编写好的逻辑
//-----
// 2019-1-9 上午10:16:06
// scimence 


/** 接入逻辑(在AndroidManifest.xml中)
 * 
 * 1、添加权限:
 * uses-permission android:name="android.permission.READ_PHONE_STATE" 
 * uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"
 * 
 * 2、添加receiver和service
<application ...>
....
		<!-- 添加静态广播接收,监听开启、锁屏、解屏 事件(以启动电话监听CallService) -->
		<receiver
		    android:name="com.sc.broad.BroadCast_Start"
		    android:exported="true" >
		    <intent-filter>
		        <action android:name="android.intent.action.BOOT_COMPLETED" />
		        <action android:name="android.intent.action.SCREEN_OFF" />
		        <action android:name="android.intent.action.SCREEN_ON" />
		    </intent-filter>
		</receiver>
		
		<!-- 定义CallService,用于执行电话事件处理逻辑 -->
        <service
            android:name="com.sc.service.CallService"
            android:enabled="true"
            android:exported="true" >
        </service>
</application>
*
*
* 3、电话事件处理逻辑:改写该类中的处理逻辑(实现来电、接听、挂断、拨出 事件逻辑)
* 
* 备注:若改变当前类名、路径,请在CallService.CallLogic()中修改调用
* */
public class CallProcess
{
	/** 添加来电处理逻辑 */
	public static void Ringing(Context context, String phoneNumber)
	{	
		// TODO 添加来电相关处理逻辑
		Toast.makeText(context, "来电相关处理逻辑!", Toast.LENGTH_SHORT).show();
	}
	
	/** 添加接听处理逻辑 */
	public static void OffHook(Context context, String phoneNumber)
	{	
		// TODO 添加接听相关处理逻辑
		Toast.makeText(context, "接听相关处理逻辑!", Toast.LENGTH_SHORT).show();
	}
	
	/** 添加挂断处理逻辑 */
	public static void HungUp(Context context, String phoneNumber)
	{	
		// TODO 添加挂断相关处理逻辑
		Toast.makeText(context, "挂断相关处理逻辑!", Toast.LENGTH_SHORT).show();
	}
	
	/** 添加拨出处理逻辑 */
	public static void OutCall(Context context, String phoneNumber)
	{	
		// TODO 添加拨出相关处理逻辑
		Toast.makeText(context, "拨出相关处理逻辑!", Toast.LENGTH_SHORT).show();
	}
}

}简易调用结束


相关源码附录:

package com.sc.broad;

//import java.util.HashMap;
 
import com.sc.service.CallService;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
 
/* 需在AndroidManifest.xml添加广播静态配置,<intent-filter/>中添加需要监听的广播类型
<application ...>
...
<receiver
    android:name="com.sc.broad.BroadCast_Start"
    android:exported="true" >
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
        <action android:name="android.intent.action.SCREEN_OFF" />
        <action android:name="android.intent.action.SCREEN_ON" />
        
        <!-- 自定义广播类型 -->
        <action android:name="com.sc.broad.actionDemo" />
    </intent-filter>
</receiver>
</application>
*/
 
/** AndroidManifest.xml的静态注册广播(安装app时会自动注册,app未运行时也可正常接收广播 )
 * 
 * 用法:无需调用,通过开启、锁屏 广播启动电话监听Service */
public class BroadCast_Start extends BroadcastReceiver
{
	@Override
	public void onReceive(Context context, Intent intent)
	{
		String action = intent.getAction();
		Broad(action, context, intent);
	}
	
	/** 广播回调,action为广播类型 */
	public void Broad(String action, Context context, Intent intent)
	{
//		if(action.equals("android.intent.action.BOOT_COMPLETED"))
//		{
//			CallService.GetInstance().start(context, CallService.class);
			CallService.GetInstance().start(context, CallService.class, 500);
//		}
	}
	
	
	// ------------
	
//	/** 发送自定义广播,action广播名称 如:"com.sc.broad.actionDemo"; extData广播附带的数据; extName广播数据对应的名称 */
//	public void SendBroadCast(Context context, String action, String extName, String extData)
//	{
//		BroadCastTool.SendBroadCast(context, action, extName, extData);
//	}
//	
//	/** 发送自定义广播,action广播名称 如:"com.sc.broad.actionDemo"; ext为广播附带的数据 */
//	public void SendBroadCast(Context context, String action, HashMap<String, String> ext)
//	{
//		BroadCastTool.SendBroadCast(context, action, ext);
//	}
}

package com.sc.service;

import com.sc.call.CallListener;
import com.sc.call.CallProcess;

import android.widget.Toast;

/* 在AndroidManifest.xml
 * 
 * 添加权限:
 * uses-permission android:name="android.permission.READ_PHONE_STATE" 
 * uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"
 * 
 * 添加 <service/>
<application ...>
....
        <service
            android:name="com.sc.service.CallService"
            android:enabled="true"
            android:exported="true" >
        </service>
</application>
*/

/**
 * 定义:继承BaseService,重写自定义服务逻辑serviceLogic()
 * 
 * 1、获取服务:CallService.GetInstance()
 * 
 * 2、启动服务:CallService.GetInstance().start(context, CallService.class);
 * 3、停止服务:CallService.GetInstance().stop();
 * */
public class CallService extends BaseService
{
	/** 在service中待执行的逻辑(在service未停止时,会一直执行)*/
	public void serviceLogic()
	{
		CheckListener();	// 检测电话监听状态
		CallLogic();		// 执行对应电话状态逻辑
	}
	
	public static boolean isRinging = false;
	public static boolean isOutCall = false;
	public static boolean isOffHook = false;
	public static boolean isHungUp = false;
	public static String Number = "";

	CallListener callListen;
	
	// 检测并自动创建来电、去电监听
	private void CheckListener()
	{
		if(callListen == null)
		{
			callListen = new CallListener(this)
			{
				@Override
				public void Ringing(String phoneNumber)
				{
					isRinging = true;
					Number = phoneNumber;
				}
				
				@Override
				public void OutCall(String phoneNumber)
				{
					isOutCall = true;
					Number = phoneNumber;
				}
				
				@Override
				public void OffHook(String phoneNumber)
				{
					isOffHook = true;
					Number = phoneNumber;
				}
				
				@Override
				public void HungUp(String phoneNumber)
				{
					isHungUp = true;
					Number = phoneNumber;
				}
			};
		}
	}
	
	/** 电话状态处理逻辑 */
	private void CallLogic()
	{
		if(isRinging)
		{
			isRinging = false;
			CallProcess.Ringing(this, Number);
		}
		else if(isOffHook)
		{
			isOffHook = false;
			CallProcess.OffHook(this, Number);
		}
		else if(isHungUp)
		{
			isHungUp = false;
			CallProcess.HungUp(this, Number);
		}
		else if(isOutCall)
		{
			isOutCall = false;
			CallProcess.OutCall(this, Number);
		}
	}
	
//	/** 电话状态处理逻辑 */
//	private void CallLogic()
//	{
//	
//		// 执行定义在CallProcess中的逻辑
//		for(CallProcess proccesser : CallProcess.ProcessList())
//		{
//			if(isRinging)
//			{
//				isRinging = false;
//				proccesser.Ringing(this, Number);
//			}
//			else if(isOffHook)
//			{
//				isOffHook = false;
//				proccesser.OffHook(this, Number);
//			}
//			else if(isHungUp)
//			{
//				isHungUp = false;
//				proccesser.HungUp(this, Number);
//			}
//			else if(isOutCall)
//			{
//				isOutCall = false;
//				proccesser.OutCall(this, Number);
//			}
//		}
//		
//	}

	
//	public void Ringing(String phoneNumber)
//	{
//		// TODO 添加来电处理逻辑
//	}
//	
//	public void OffHook(String phoneNumber)
//	{
//		// TODO 添加接听处理逻辑
//	}
//	
//	public void HungUp(String phoneNumber)
//	{
//		// TODO 添加挂断处理逻辑
//	}
//	
//	public void OutCall(String phoneNumber)
//	{
//		// TODO 添加拨出处理逻辑
//	}
}

package com.sc.service;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.widget.Toast;


/* 在AndroidManifest.xml添加 <service/>
 <application ...>
 ....
        <service
            android:name="com.sc.service.MsgService"
            android:enabled="true"
            android:exported="true" >
        </service>
 </application>
 */

/** Service类,简化Service调用: 
 * 子类可继承BaseService,重写函数serviceLogic()实现自定义服务逻辑
 * 
 *  1、获取服务单例对象 BaseService.GetInstance() 
 *  2、启动服务 .start(Context context, Class<?> service_cls)(一次启动,持续运行) 
 *  3、停止服务 .stop() */
public class BaseService extends Service
{
	protected BaseService()
	{}
	
	@Override
	public IBinder onBind(Intent intent)
	{
		return null;
	}
	
	@Override
	public int onStartCommand(Intent intent, int flags, int startId)
	{
		if (!isrunning)
		{
			// if (BaseService.intent == null) BaseService.intent = intent;
			// if (context == null) context = this.getBaseContext();
			
			isrunning = true;
			// Log.i(this.getClass().getSimpleName(), "onStartCommand");
			
			// 执行服务处理逻辑
			doServicesLogic(IntervalMillis);
		}
		
		return super.onStartCommand(intent, flags, startId);
	}
	
	/** service执行间隔时间(毫秒) */
	public static long IntervalMillis = 2000;
	
	
	Runnable runable;
	
	/** 循环执行服务处理逻辑 */
	private void doServicesLogic(final long delayMillis)
	{
		if(runable == null)
		{
			runable = new Runnable()
			{
				@Override
				public void run()
				{
					if (isrunning)
					{
						// Toast.makeText(context, "doServicesLogic is running !", Toast.LENGTH_SHORT).show();
						serviceLogic();						// 执行服务处理逻辑
						
						doServicesLogic(delayMillis);		// 处理逻辑执行完成1秒后再次执行
					}
				}
			};
		}
		new Handler().postDelayed(runable, delayMillis);
	}
	
	/** 在service中待执行的逻辑(在service未停止时,会一直执行,每轮逻辑执行间隔IntervalMillis毫秒) */
	public void serviceLogic()
	{};
	
	static BaseService Instance;
	
	/** 获取当前服务的单例对象 */
	public static BaseService GetInstance()
	{
		if (Instance == null) Instance = new BaseService();
		return Instance;
	}
	
	// ------------
	
	private static boolean isrunning = false;
	
	// private static Intent intent;
	// private static Context context;
	
	/** 启动服务, service_cls当前服务对应的类, Millis指定服务逻辑serviceLogic()执行间隔毫秒数 */
	public void start(Context context, Class<?> service_cls, long Millis)
	{
		IntervalMillis = Millis;
		if (!isrunning)
		{
			// BaseService.context = context;
			Intent intent = new Intent(context, service_cls);
			context.startService(intent);
			
			Toast.makeText(context, this.getClass().getSimpleName() + " 服务已启动 !", Toast.LENGTH_SHORT).show();
		}
	}
	
	/** 启动服务, service_cls当前服务对应的类 */
	public void start(Context context, Class<?> service_cls)
	{
		start(context, service_cls, 2000);
	}
	
	/** 停止服务(暂时停止服务,服务逻辑会在应用退出后自行重启,并一直运行) */
	public void stop()
	{
		if (isrunning)
		{
			stopSelf();
			// context.stopService(intent);
			isrunning = false;
			
			// Toast.makeText(context, this.getClass().getSimpleName() + " 服务已停止 !", Toast.LENGTH_SHORT).show();
		}
	}
	
}

猜你喜欢

转载自blog.csdn.net/scimence/article/details/86244443