本文实例为大家分享了android实现通话自动录音服务的具体代码,供大家参考,具体内容如下

需求:

①:通话自动录音;
②:无界面,只是一个service;
③:录音自动压缩上传;
④:当用户清理后台的时候,要求service不可以被杀死;
⑤:稳定性:1、无网络的情况下;2、上传失败;3、服务报错。

解决方案:

①:通话自动录音

启动一个service,监听用户手机通话状态,当检测到用户处于通话状态下,立即开始录音,通话结束后,停止录音,并保存文件。
此功能的前提条件:
1、录音权限、读写存储空间的权限、读取通话状态的权限;
2、Service不可以被停止,否则无法录音。
3、开机启动(不可以让用户每次开机都主动去打开服务)

②:无界面,只是一个service

方案①
普通的service,监听开机广播,当用户开机的时候,启动service。但是,发现service并没有启动。想要启动一个service,必须要有一个activity,即使你不打开这个activity。
在真正做项目的时候,PM会提出各种你不能理解的需求,比如说本系统,PM要求本应用只是一个录音服务,不可以有任何界面,也不可以在手机桌面上出现应用图标。因此,方案①不可行。
方案②
Android手机在设置里面都一个辅助功能(个别手机也叫:无障碍),利用这个我们可以实现一些强大的功能,前提是用户开启我们的辅助功能,抢红包软件就是利用辅助功能实现的。

③:录音自动压缩上传

我们只需要在上传之前对文件进行压缩处理,然后再上传即可。

④:当用户清理后台的时候,要求service不可以被杀死

不会被杀死的服务,或许只有系统服务吧。当然类似于QQ、微信他们做的这种全家桶也可以做到。大公司是可以和厂商合作的,他们的应用可以不那么容易被杀死。当然也不提倡这样做,这样就是垃圾软件,破坏了Android开发的美好环境。
其实,如果可以把服务设置成系统服务,那么只要用户不主动在辅助功能页面关掉服务,后台是清理不掉改服务的。本人在小米手机上测试过,设置成系统级别的服务后,当清理后台的时候,即使服务被杀死,也会非常快的重新启动。(感兴趣的同学可以试一下)

⑤:稳定性:1、无网络的情况下;2、上传失败;3、服务报错

思路:

当无网络的情况下,把录音文件的地址保存下来(保存的方式有很多:Sqlite、Sharedpreferences等等),上传失败也一样,失败的原因可能有很多种:网络断开、接口报错等,当网络恢复的时候,可以重新上传,这样就不会丢失录音文件。
代码很简单,注释很详细:

项目的结构:


<uses-permission android:name="" />
<uses-permission android:name="" />
<uses-permission android:name="" />
<!-- 要存储文件或者创建文件夹的话还需要以下两个权限 -->
<uses-permission android:name="" />
<uses-permission android:name="" />
<uses-permission android:name="" />
<uses-permission android:name=""/>
<!--允许读取网络状态-->
<uses-permission android:name=""/>
<!--允许读取wifi网络状态-->
<uses-permission android:name=""/>


<serviceandroid:name="."android:permission=""><intent-filter><action android:name="" /></intent-filter><meta-dataandroid:name=""android:resource="@xml/accessible_service_config" />
</service>


/*** 电话自动录音辅助服务(去电、来电自动录音并上传)。* Created by wang.ao in 2017/2/24.*/public class RecorderService extends AccessibilityService {private static final String TAG = "RecorderService";private static final String TAG1 = "手机通话状态";/*** 音频录制*/private MediaRecorder recorder;private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");/*** 监听拨号广播,以便获取用户拨出的电话号码*/private OutCallReceiver outCallReceiver;private IntentFilter intentFilter;/*** 网络状态改变广播,当网络畅通的状态下,把用户未上传的录音文件都上传掉*/private NetworkConnectChangedReceiver networkConnectChangedReceiver;private IntentFilter intentFilter2;/*** 当前通话对象的电话号码*/private String currentCallNum = "";/*** 区分来电和去电*/private int previousStats = 0;/*** 当前正在录制的文件*/private String currentFile = "";/*** 保存未上传的录音文件*/private SharedPreferences unUploadFile;private String dirPath = "";private boolean isRecording = false;@Overrideprotected void onServiceConnected() {(TAG, "onServiceConnected");(getApplicationContext(), "自动录音服务已启动", ).show();}@Overridepublic void onAccessibilityEvent(AccessibilityEvent event) {// TODO Auto-generated method stub(TAG, "eventType " + ());}@Overridepublic void onInterrupt() {// TODO Auto-generated method stub(TAG, "onServiceConnected");}@Overridepublic boolean onUnbind(Intent intent) {return super.onUnbind(intent);}@Overridepublic void onCreate() {();TelephonyManager tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);// 监听电话状态(new MyListener(), );outCallReceiver = new OutCallReceiver();intentFilter = new IntentFilter();//设置拨号广播过滤("");registerReceiver(outCallReceiver, intentFilter);//注册拨号广播接收器networkConnectChangedReceiver = new NetworkConnectChangedReceiver();intentFilter2 = new IntentFilter();//设置网络状态改变广播过滤("");("");("");//注册网络状态改变广播接收器registerReceiver(networkConnectChangedReceiver, intentFilter2);unUploadFile = getSharedPreferences("un_upload_file", 0);().putString("description", "未上传的录音文件存放路径").commit();dirPath = ().getAbsolutePath() + "/";}@Overridepublic void onDestroy() {();(getApplicationContext(), "进程被关闭,无法继续录音,请打开录音服务", ).show();if (outCallReceiver != null) {unregisterReceiver(outCallReceiver);}if (networkConnectChangedReceiver != null) {unregisterReceiver(networkConnectChangedReceiver);}}class MyListener extends PhoneStateListener {@Overridepublic void onCallStateChanged(int state, String incomingNumber) {// TODO Auto-generated method stub(TAG1, "空闲状态" + incomingNumber);switch (state) {case TelephonyManager.CALL_STATE_IDLE:(TAG1, "空闲");if (recorder != null && isRecording) {();// 停止录音();recorder = null;("电话", "通话结束,停止录音");uploadFile(currentFile);}isRecording = false;break;case TelephonyManager.CALL_STATE_RINGING:(TAG1, "来电响铃" + incomingNumber);// 进行初始化break;case TelephonyManager.CALL_STATE_OFFHOOK:(TAG1, "摘机" + (!("") ? incomingNumber : currentCallNum));initRecord(!("") ? incomingNumber : currentCallNum);// 开始录音if (recorder != null) {();isRecording = true;}default:break;}(state, incomingNumber);}}/*** 当录音结束后,自动上传录音文件。* ①网络可用:直接上传;* ②网络不可用:保存文件路径,待网络可用的时候再进行上传;* ③上传失败的文件,也保存文件路径,或者重新上传。*/public void uploadFile(String file) {(dirPath + file, dirPath + file + ".zip");if ((getApplicationContext())) {//上传文件
//   ()} else {saveUnUploadFIles(dirPath + file + ".zip");}}/*** 保存未上传的录音文件** @param file 未上传的录音文件路径*/private void saveUnUploadFIles(String file) {String files = ("unUploadFile", "");if (("")) {files = file;} else {StringBuilder sb = new StringBuilder(files);files = (";").append(file).toString();}().putString("unUploadFile", files).commit();}/*** 上传因为网络或者其他原因,暂未上传或者上传失败的文件,重新上传*/public void uploadUnUploadedFiles() {//获取当前还未上传的文件,并把这些文件上传String files = ("unUploadFile", "");().putString("unUploadFile", "").commit();if (("")) {return;}String[] fileArry = (";");int len = fileArry.length;for (String file : fileArry) {upload(file);}}/*** 文件上传** @param file 要上传的文件*/public void upload(final String file) {File file1 = new File(file);if (file1 == null || !()) {//文件不存在return;}if (!(getApplicationContext())) {saveUnUploadFIles(file);return;}Map<String, String> map = new HashMap<String, String>();("type", "1");final String url = "";()//.addFile("mFile", (), file1)//.url(url)//.params(map).build()//.execute(new StringCallback() {@Overridepublic void onResponse(String response, int id) {(TAG, "成功 response=" + response);}@Overridepublic void onError(Call call, Exception e, int id) {(TAG, "失败 response=" + ());saveUnUploadFIles(file);}});}/*** 初始化录音机,并给录音文件重命名** @param incomingNumber 通话号码*/private void initRecord(String incomingNumber) {previousStats = TelephonyManager.CALL_STATE_RINGING;recorder = new MediaRecorder();();// Microphonerecorder.setOutputFormat();// 设置输出3gp格式File out = new File(dirPath);if (!()) {();}(dirPath+ getFileName((previousStats == TelephonyManager.CALL_STATE_RINGING ? incomingNumber : currentCallNum)));();// 设置音频编码格式try {();// 做好准备} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}/*** 获取录音文件的名称** @param incomingNumber 通话号码* @return 获取录音文件的名称*/private String getFileName(String incomingNumber) {Date date = new Date(());currentFile = incomingNumber + " " + (date) + ".mp3";return currentFile;}/*** 拨号广播接收器,并获取拨号号码*/public class OutCallReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {(TAG1, "当前手机拨打了电话:" + currentCallNum);if (().equals()) {currentCallNum = ();(TAG1, "当前手机拨打了电话:" + currentCallNum);} else {(TAG1, "有电话,快接听电话");}}}/*** 网络状态change广播接收器*/public class NetworkConnectChangedReceiver extends BroadcastReceiver {private static final String TAG = "network status";@Overridepublic void onReceive(Context context, Intent intent) {/*** 这个监听网络连接的设置,包括wifi和移动数据的打开和关闭。.* 最好用的还是这个监听。wifi如果打开,关闭,以及连接上可用的连接都会接到监听。见log* 这个广播的最大弊端是比上边两个广播的反应要慢,如果只是要监听wifi,我觉得还是用上边两个配合比较合适*/if ((())) {ConnectivityManager manager = (ConnectivityManager) context.getSystemService();(TAG, "CONNECTIVITY_ACTION");NetworkInfo activeNetwork = ();if (activeNetwork != null) { // connected to the internetif (()) {//当前网络可用if (() == ) {// connected to wifi(TAG, "当前WiFi连接可用 ");} else if (() == ) {// connected to the mobile provider's data plan(TAG, "当前移动网络连接可用 ");}uploadUnUploadedFiles();} else {(TAG, "当前没有网络连接,请确保你已经打开网络 ");}} else { // not connected to the internet(TAG, "当前没有网络连接,请确保你已经打开网络 ");}}}}}


/*** 获取网络连接状态工具类* Created by wang.ao in 2017/2/24.*/public class NetWorkUtils {/*** 判断是否有网络连接* @param context* @return*/public static boolean isNetworkConnected(Context context) {if (context != null) {ConnectivityManager mConnectivityManager = (ConnectivityManager) context.getSystemService();NetworkInfo mNetworkInfo = ();if (mNetworkInfo != null) {return ();}}return false;}/*** 判断WIFI网络是否可用* @param context* @return*/public static boolean isWifiConnected(Context context) {if (context != null) {ConnectivityManager mConnectivityManager = (ConnectivityManager) context.getSystemService();NetworkInfo mWiFiNetworkInfo = mConnectivityManager.getNetworkInfo();if (mWiFiNetworkInfo != null) {return mWiFiNetworkInfo.isAvailable();}}return false;}/*** 判断MOBILE网络是否可用* @param context* @return*/public static boolean isMobileConnected(Context context) {if (context != null) {ConnectivityManager mConnectivityManager = (ConnectivityManager) context.getSystemService();NetworkInfo mMobileNetworkInfo = mConnectivityManager.getNetworkInfo();if (mMobileNetworkInfo != null) {return mMobileNetworkInfo.isAvailable();}}return false;}/*** 获取当前网络连接的类型信息* @param context* @return*/public static int getConnectedType(Context context) {if (context != null) {ConnectivityManager mConnectivityManager = (ConnectivityManager) context.getSystemService();NetworkInfo mNetworkInfo = ();if (mNetworkInfo != null && ()) {return mNetworkInfo.getType();}}return -1;}/*** 获取当前的网络状态 :没有网络0:WIFI网络1:3G网络2:2G网络3** @param context* @return*/public static int getAPNType(Context context) {int netType = 0;ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService();NetworkInfo networkInfo = ();if (networkInfo == null) {return netType;}int nType = ();if (nType == ) {netType = 1;// wifi} else if (nType == ) {int nSubType = ();TelephonyManager mTelephony = (TelephonyManager) context.getSystemService();if (nSubType == TelephonyManager.NETWORK_TYPE_UMTS&& !()) {netType = 2;// 3G} else {netType = 3;// 2G}}return netType;}
}


public class ZipUtils {private static final int BUFF_SIZE = 1024;/*** @param zos   压缩流* @param parentDirName 父目录* @param file   待压缩文件* @param buffer  缓冲区*    * @return 只要目录中有一个文件压缩失败,就停止并返回*/private static boolean zipFile(ZipOutputStream zos, String parentDirName, File file, byte[] buffer) {String zipFilePath = parentDirName + ();if (()) {zipFilePath += ;for (File f : ()) {if (!zipFile(zos, zipFilePath, f, buffer)) {return false;}}return true;} else {try {BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));ZipEntry zipEntry = new ZipEntry(zipFilePath);(());(zipEntry);while ((buffer) != -1) {(buffer);}();return true;} catch (FileNotFoundException ex) {();} catch (IOException ex) {();}return false;}}/*** @param srcPath 待压缩的文件或目录* @param dstPath 压缩后的zip文件* @return 只要待压缩的文件有一个压缩失败就停止压缩并返回(等价于windows上直接进行压缩)*/public static boolean zipFile(String srcPath, String dstPath) {File srcFile = new File(srcPath);if (!()) {return false;}byte[] buffer = new byte[BUFF_SIZE];try {ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(dstPath));boolean result = zipFile(zos, "", srcFile, buffer);();return result;} catch (FileNotFoundException ex) {();} catch (IOException ex) {();}return false;}/*** @param srcPath 待解压的zip文件* @param dstPath zip解压后待存放的目录* @return 只要解压过程中发生错误,就立即停止并返回(等价于windows上直接进行解压)*/public static boolean unzipFile(String srcPath, String dstPath) {if ((srcPath) || (dstPath)) {return false;}File srcFile = new File(srcPath);if (!() || !().toLowerCase(()).endsWith("zip")) {return false;}File dstFile = new File(dstPath);if (!() || !()) {();}try {ZipInputStream zis = new ZipInputStream(new FileInputStream(srcFile));BufferedInputStream bis = new BufferedInputStream(zis);ZipEntry zipEntry = null;byte[] buffer = new byte[BUFF_SIZE];if (!()) {dstPath += ;}while ((zipEntry = ()) != null) {String fileName = dstPath + ();File file = new File(fileName);File parentDir = ();if (!()) {();}FileOutputStream fos = new FileOutputStream(file);while ((buffer) != -1) {(buffer);}();}();();return true;} catch (FileNotFoundException ex) {();} catch (IOException ex) {();}return false;}
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

开机 服务 自动 bat regedi_android实现通话自动录音服务_Android相关推荐

  1. 【Ubuntu】开启ssh服务/配置ftp内网穿透/自动连接校园网

    前言 想让工作电脑开启ssh服务,这样就可以在校外进行远程访问办公,电脑的系统为Ubuntu20.04 开启ssh服务 首先查看当前Ubuntu安装的SSH服务: dpkg -l | grep ssh ...

  2. 数据库自治服务DAS年度新版本:”数据库自动驾驶“进入规模化时代

    简介:在今天的发布会上,针对用户的核心痛点,DAS新发布了8大核心自治功能,包括7x24小时异常检测.自动SQL限流.自动SQL优化.自动空间优化.自动弹性伸缩.智能调参.智能压测.实时审计等,为企业 ...

  3. linux svn同步到本地目录,LINUX中SVN服务的搭建与实现SVN 自动同步到web目录,SVN自动启动...

    一,下载相关软件: [root@localhost test]# wget http://subversion.tigris.org/downloads/subversion-1.6.1.tar.gz ...

  4. c++ 实现录音并且指定到文件_通话自动录音,留下美好回忆,记录完整录音证据...

    手机通话,如果自动录音多好,许多人与我一样抱有这个想法. 记得华为Android版本5.0时代,手机没有自动录音功能,我一直到网上下载自动通话录音软件,有时甚至是下载ROOT版的带自动通话功能的EMU ...

  5. 微服务架构开发实战:如何实现微服务的自动扩展?

    微服务架构开发实战:如何实现微服务的自动扩展? 程序员高级码农II 2020-09-25 07:25:00 如何实现微服务的自动扩展 前面讲了一些关于自动扩展的理论知识,但如何实现自动扩展,并不是三言 ...

  6. 命令行下(bat)使用 Lhaplus 自动 压缩 解压文件 (含参数设定说明)

    命令行下(bat)使用 Lhaplus 自动 压缩 解压文件,参数设定 https://mp.csdn.net/console/editor/html/104400832 ■前言 准备测试数据,要压缩 ...

  7. 播放器可以完成:开机自动打开指定网页,自动运行浏览器打开指定的网页。

    播放器可以完成:开机自动打开指定网页,自动运行浏览器打开指定的网页. 设计要求: 1.通电自动开机,无需操作自动运行浏览器 2.自动打开指定的网站(网页). 3.客户可以远程修改网页,达到所有的电视机 ...

  8. 电脑开机自动登录,断网自动重连以及桌面联网小程序

    对于需要拨号连接联网的公司企业和学校,每次开机都需要点一下弹出的连接对话框,才能让电脑联网,有没有什么方法无需用户进行任何操作就能自动联网呢?在远程办公时,办公室偶尔会出现断网的情况,远程软件也无法使 ...

  9. Linux网络项目实验------网络架构(DNS域名解析、NFS共享服务、LAMP服务、搭建论坛、PXE自动装机)

    实验 环境描述: 客户端:无任何系统的裸金属机器 DNS:192.168.10.10/24 提供DNS域名解析 PXE:192.168.10.20/24 提供DHCP,TFTP,FTP功能,DHCP地 ...

  10. VOlte高清视频通话自动外放的机制

    VOlte高清视频通话自动外放的机制 设置外放的命令发送的log 主叫以高清视频起呼,speaker自动打开: 从高清语音切换到高清视频: 其他自动打开speaker的情况 设置外放的命令发送的log ...

最新文章

  1. java swing setborder_Swing编程边框(Border)的用法总结
  2. stop words list
  3. php将换行变为 p 标签,editplus 将文本换行替换为p标签
  4. numpy的常规使用(数组合并、拼接、添加)
  5. 233 Matrix HDU - 5015
  6. 开源重量级的流程引擎或UI引擎
  7. REVERSE-PRACTICE-BUUCTF-21
  8. Atlas读写分离Mysql集群的搭建
  9. 数据库Oracle 11g的安装步骤
  10. python实现xml文件解析失败_Python实现灵活的xml文件解析
  11. 微警务:网上公安服务一键开启
  12. 左手补贴右手社交 杀入直播红海的拼多多会有机会吗?
  13. swfupload 实例 php,SWFUpload在PHP中使用实例教程
  14. 举例说明数据库一、二、三及BCNF范式
  15. 三张图片无缝合成一张图片_怎样把两张照片连在一起合成一张照片
  16. ARM嵌入式的位绑定原理
  17. 84行C++代码教你实现洛谷占卜功能
  18. 其实EXCEL也是一个很好的管理程序开发工具
  19. postman测试图片上传接口一直失败的解决办法
  20. Uva 11584 线性DP

热门文章

  1. ERC-3525 通过倒计时|SFT 是什么?有什么用?
  2. HTML+CSS打造简单的横向时间轴
  3. 科普一下bl锁的知识,没解锁的必看!
  4. excel表格打印每页都有表头_excel单页表格打印带连续页码的多页
  5. excel表格打印每页都有表头_13个关于Excel表格的打印技巧
  6. 怎样更换计算机主板电池,如何更换电脑主板电池
  7. 物联网蓝牙芯片的选型
  8. 我们将迎来另一个 VR 寒冬吗?
  9. 【极富参考价值!】第1章 ClickHouse 简介《ClickHouse 企业级大数据分析引擎实战》...
  10. 《人工智能及其应用》练习题