1、摘要 现在移动设备呈几何形增加,移动设备的演化增加了各种移动设备的应用程序开发,这些移动设备可以成为承载WEB服务的客户端,移动的硬件和软件平台形式允许更快和更丰富的应用程序的运行。本文所介绍的通话录音系统趋于国际化也被越来越多的人接受 ,自2000年以来,全国手机基本上普遍都具有通话录音功能,可将短暂通话记录下来,一般作为法庭重要政务和不可轻视的证据,也可适当看做娱乐。手机录音直接就可以保存在手机SD卡上,需要的时候可以直接调出来,很方便。因为目前手机市场已经出现了明显的Android一家独大趋势,所以本系统选择了Android平台进行开发。本论文首先给出了课题的研究背景,对Android平
2、台做了简单的介绍,通过介绍,可以让读者了解其平台的基本框架以及基本的平台开发技术,在此基础上分析了手机通话录音系统Android客户端程序的基本架构以及各个模块的解决方案,实现通话录音的打开、关闭、播放、删除、保存、选择格式等功能。关键字:移动设备、通话录音系统、AndroidAbstract Now the mobile device is geometric increase, evolution of mobile devices increase the application development of various mobile devices, these devices c
3、an be hosting the WEB service client, allowing faster and more extensive application of mobile hardware and software platform running .Call recording system described in this article to be internationalization is accepted by more and more people, since 2000, the national mobile phone basically unive
4、rsal has call recording function, can be recorded as a short talk, the General Court Affairs and important evidence, can also be appropriate as entertainment. Mobile phone recording directly can be kept in the mobile phone SD card, when necessary, can be directly transferred out, very convenient. Be
5、cause the mobile phone market has appeared obvious Android alone big trend, so the system selected Android development platform. This paper first presents the research background of the subject, the Android platform is introduced, through the introduction, so that readers can understand the basic fr
6、amework of the platform as well as the basic platform development technology, based on the analysis of the basic architecture of mobile phone call recording system Android client program and each module of the solution, realizing call recording open, close, delete, save, play, choose Format etc. Key
7、words: mobile equipment, call recording system, Android 目 录1.绪论11.1研究背景11.2研究概况与发展趋势12.需求分析12.1可行性分析12.1.1操作可行性12.1.2技术可行性12.1.3经济可行性22.2功能需求分析22.2.1基本功能需求22.2.2用户界面需求23.开发环境和开发技术23.1Android平台介绍23.2Android基本框架介绍33.3开发环境的选择44.Android手机客户端具体功能分析44.1主界面44.2录音文件的保存44.3开机自启动的设置94.4录音文件的管理94.5功能的开启和关闭104.
8、6录音文件格式的选择115.关键程序设计116总结12致谢12附图13参考文献141.绪论1.1研究背景 在日常生活或其它方方面面,都经常会遇到这样的问题,交流双方或者对接双方在通过电话沟通交流的时候,由于无法做到面面,所以所说的话,经常会发生歧义造成双方发生误解,尤其是在企业管理中,一般要记录下电话中的重要信息,传统的通话资料大部分都是在通话结束后,通话者再回忆一遍通话的内容,然后慢慢的记录下来,这种方式古老而落后,通话录音软件的出现,真正改变了这种模式。这样的资料保存方式,详细全面而准确,没有半点耽误,非常的方便。而且它也是作为法庭重要政务和不可轻视的证据,也会被人们适当看做娱乐。1.2研
9、究概况与发展趋势 通话录音软件最主要的作用是,把通话信息固化,形成数字化资料保存在手机内存里,是个人记录重要通话信息的便捷手段,也可以作为娱乐使用。随着通信和互联网技术的发展,当前通话录音软件的功能又有了新的发展。除了iphone不能实现通话录音软件的开发外,大部分手机系统都具有相应的通话录音软件,可实现双向通话录音,录音时间不再受时间限制。 如今,手机通话录音软件是智能手机发展起来后的新宠,是移动互联网技术的新型应用。尤其是录音文件被列入证据范畴以后,通话录音成为非常广泛的需求。近来,在云存储技术发展的促进之下,出现了一些与存证、公证相结合的新型通话录音软件,比如语音实录通话录音软件、存证宝
10、等 ,语音实录通话录音软件是其中最以技术见长的针对安卓手机开发的软件,在所有安卓通话录音软件中内录功能最强,已经可以支持四十款左右的安卓手机实现内录,双向通话录音属于高清标准。 随着这方面需求的不断增大,我们要不断注入新的功能,所以,软件通话录音系统必须保持进步与完善。2.需求分析2.1可行性分析2.1.1操作可行性 本系统操作简单,易于理解,只需通过简单指导,上手较快。尊重用户习惯,不改变常规电话接听模式,方便易用,可随时通话录音。 2.1.2技术可行性Android平台是一个开放式的平台,国内开发人员众多,网上相关资料丰富,同时在网上或书店都能买到各类有关Android平台技术开发的图书,
11、因此Android手机客户端的开发在技术方面已不是问题。2.1.3经济可行性该项目相比而言总体规模不大,开发周期比较短,且投入成本较少,并且目前Android手机越来越普遍,客户端成本非常低廉,易于管理和维护。因此在成本上不是问题。2.2功能需求分析2.2.1基本功能需求表2-2-1 功能描述实现的功能功能描述保存能够保存用户的通话,将录音文件保存到sd卡下.开机自启动用户可以选择是否开机自启动,避免每次开机都得手动开启此软件,给用户带来良好的体验。录音文件的管理本系统实现了一个类似文件游览器的界面,并且用户可以在此界面进行播放,删除等简单操作,方便用户进行管理这些音频文件。录音功能的打开关闭
12、用户可以进行自行选择电话录音功能的开启和关闭,当用户点击开启时,系统将会对电话状态进行监听,如果来电话,从而进行录音,达到电话录音的目的。录音文件格式的选择用户可以选择录音文件的音频格式,目前只支持3gp和amr两种主流音频文件的录制,给用户一个选择,以降低可能因音频文件格式而不能播放造成的BUG。2.2.2用户界面需求(见附图)3.开发环境和开发技术3.1 Android平台介绍 无论对于生产Android软件,还是硬件的企业来说,它都是免费的 3。对于软件厂商来说,加入Google的Android联盟之后就可以对Android系统进行更改,从而在Android框架下打造出自己的操作系统,我
13、国就有联想、华为、中兴、播思通讯等企业加入了Android联盟,并且打造出乐phone,Ophone等一系列就有自主知识产权的手机操作系统,目前国家工信部和移动在大力推广这些手机操作系统。相对于苹果公司、微软公司的“闭关锁国”政策,Android的策略是正好相反的,那就是Open,完全开放,无论是系统内使用的框架,OpenGL、OpenCore等都是开源组织在维护,还是Android系统本身的源代码都是完全开放的,任何人都可以使用Google公司的GIT账号去内部的服务器上去直接下载源码。这些举措得到了很多组织和个人的支持。对于硬件厂商来说,在自己的硬件产品上安装Android操作系统只需要遵
14、循Google的规范,是不需要额外像其支付任何费用的,相信在不久的将来Android系统将会被大量的手机、平板电脑,电视机顶盒,学习机等移动终端上面所使用,市场份额将会非常大,甚至有可能会做到中低端市场的“一统江湖”局面。对于Android开发者来说,学习这个系统的开发是非常容易上手的,它的开发主要由Java语言为主,并且Google提供了基于Eclipse 的开发环境(IDE),免费、跨平台(Windows、Mac OS X、Linux) 的开发工具(SDK),能够非常方便的进行配置,基于众多的Java程序员,想必Android程序员的基数也会非常的大,无疑这也会推动Android的进一步发
15、展。3.2Android基本框架介绍图3-2 Android基本框架从图中可以看出,Android系统架构为四层结构,从上层到下层依次是应用程序层、应用程序框架层、系统运行库层以及Linux内核层。应用程序层,我们在eclipse里面利用SDK开发出来的程序就运行在这一层中,的这些应用程序都是用Java语言编写的,并且这些应用程序的被安装和卸载,就连Android系统自带的应用程序,我们也可以将他们替换,只需将程序放到Android对应linux系统的system/app路径下,就可以轻松替换系统原生的应用,但这个操作需要ROOT权限,普通用户权限不能完成这个操作。应用程序框架层,这一层是普通
16、Android开发的基础,我们在应用程序框架层调用的函数大多来源于这一层,这一层主要包括ActivityManager、WindowManager、ContentProvider等类,这些都是与系统息息相关的类,系统控制Activity、界面的显示、消息的提醒等就是调用这一层的程序。系统运行库层从图中可以看出,这一层也可以叫做CC+层,因为这一层的代码都是由C和C+语言进行编写的,然后应用层和框架层可以通过JNI的方式来进行调用这一层的程序。这一层主要是SQLITE,OPENGL等偏底层的组件。 Linux内核层,最底层就是Android的改编原型Linux,它是基于Linux2.6内核,系统
17、与硬件的驱动等都依赖于Linux内核。就是以上四层构成了Android系统,这四层相互紧密联系,又相对独立,便于系统的维护以及新功能的增加。3.3开发环境的选择 开发与运行的环境的选择会影响到数据库设计,本系统开发与运行环境如下:此次研究使用eclipse作为开发工具,使用java开发环境JDK和android开发环境AndroidSDK,使用JAVA语言进行程序的开发。4. Android手机客户端具体功能分析4.1主界面此程序的主界面使用了android原生的PreferenceActivity,与android自带程序Setting的风格保持一直。从名字应该可以看出 其实 Activit
18、y 与 Perference 的混合物,因为只是存储用户的一些简单配置文件值,而SharedPreferences正好可以满足Preference的键值对存储。所以用户配置界面PreferenceActivity,就是使用SharedPreferneces以键值对的形式进行保存用户配置文件的,当然,既然是使用SharedPreferences保存数据,所有的一切关于SharedPreferences的性质我们都可以用得到,比如配置更改存储、数据变化监听等,PreferenceActivity的Preference在这里就是指的是SharedPreferences,而PreferenceActi
19、vity的Activity则是指其又可以像Activity一样展示出来。总言之,PreferenceActivity就是能够使用SharedPreferneces保存的数据的Activity。这种布局方式正好符合这种录音小程序对用户操作进行记录和保存。用法也非常简单,只需要在XML文件里面定义好你所需要的checkbox,button等组键,定义时可以加上Intent属性。它会自动监听用户的动作,用来执行跳转页面等操作。当然在主程序的onCreate时要执行this.addPreferencesFromResource(R.xml.mainpreference)此函数,用来将界面布局和程序结合
20、在一起。 此程序里面主要涉及到了录音列表,录音类型,开启电话录音功能开关,开机自动启动的的布局。4.2录音文件的保存 实现保存录音的功能,主要用到了Android的MediaRecorder,MediaRecorder具有复杂的生命周期,可以用来录制音频或视频。它具有以下几个状态: Initial:初始状态,在设定视频源或者音频源之后将转换为Initialized状态。 Initialized:已初始化状态,可以通过设置输出格式转换为DataSourceConfigured状态,或者通过重新启动转换成Initial状态。 DataSourceConfigured:数据源配置状态,这期间可以设定
21、编码方式、输出文件、屏幕旋转、预览显示等等。它仍然可以通过从新启动回到Initial状态,或者通过就绪到达Prepared状态。 Prepared:就绪状态,在就绪状态仍然可以通过重新启动方法回到Initialized状态。或者通过start方法进入录制状态。 Recording:录制状态,真正在录音的那个状态,前边做的一切都是铺垫,它可以通过停止或者重新启动回到Initial状态。 Released:释放状态(官方文档给出的词叫做Idle state空闲状态,而官方的图却不这么写),Initial状态可以通过调用释放方法来进入这个状态,这时将会释放所有和MediaRecorder对象绑定的资
22、源。 Error:错误状态,当错误发生的时候进入这个状态,它可以通过从新启动进入Initial状态。下图为MediaRecorder从初始化到结束的整个流程图:图4-2 MediaRecorder流程图但是如果直接使用的话发现跟我们的主要功能不是很匹配,为了方便使用,最好是将其进行封装,本程序中就将MediaRecorder封装成了PhoneRecorder类,下面列出主要的方法:public File getFile()File base = null;String root = Environment.getExternalStorageDirectory().getPath();/创建文
23、件夹base = new File(root + DEFAULT_STORE_SUBDIR);if (!base.isDirectory() & !base.mkdir()Log.e(TAG, getFile-Cant create base dir.);return null;/设置文件名格式SimpleDateFormat sdf = new SimpleDateFormat(phone-yyyyMMddHHmmss- + PhoneReceiver.mNumber);String fn = sdf.format(new Date();fn = base.getPath() + File.
24、separator + fn + DEFAULT_RECORD_SUFFIX;Log.d(TAG, getFile is filepath is + fn);/检验空间是否足够大StatFs stat = null;stat = new StatFs(base.getPath();long available_size = (long)stat.getAvailableBlocks() -4) * stat.getBlockSize();if (available_size MINIMUM_FREE_SIZE)Log.e(TAG, getFile-not enough free space.)
25、;return null;/建立文件File outFile = new File(fn);tryif (outFile.exists()outFile.delete();boolean bRect = outFile.createNewFile();if (!bRect)Log.e(TAG, getRecordFile, fn: + fn);catch (Exception e)e.printStackTrace();return null;Log.d(TAG, getFile sucess.);return outFile;此函数是用来创建一个空文件来供存储录音的音频。public boo
26、lean startRecord(int OutputFormate, String extension, Context context)Log.d(TAG, satrtReocrd.);if (mState != IDLE_STATE)Log.d(TAG, startRecord error mState != IDLE_STATE);return false;stopRecord();mFile = getFile();if (mFile = null)Log.d(TAG, startRecord error mFile = null);return false;/初始化mediaRec
27、order/TODO set这些值的顺序能否变化?mRecorder = new MediaRecorder();mRecorder.setAudioSource(MediaRecorder.AudioSource.VOICE_CALL);mRecorder.setOutputFormat(OutputFormate);mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);mRecorder.setOutputFile(mFile.getAbsolutePath();/mediaRecorder prepare, 一定要han
28、dle住 IOExceptiontry mRecorder.prepare();catch (IOException e) mRecorder.reset();mRecorder.release();mRecorder = null;e.printStackTrace();return false;/开始录音 trymRecorder.start(); catch (RuntimeException e)mRecorder.reset();mRecorder.release();mRecorder = null;e.printStackTrace();return false; /将状态设置为
29、录音状态setState(RECORDING_STATE);Log.d(TAG, satrtReocrd. success);return true;此函数是封装的开始录音函数,将MediaRecorder复杂的init,prepare等初始化过程封装在了一个函数中,方便业务逻辑调用。public void stopRecord()Log.d(TAG, stopRecord. );if(mRecorder = null)Log.d(TAG, Stop Recording error.mRecord = null);return;/暂停录音 trymRecorder.stop(); catch
30、(RuntimeException e) Log.d(TAG, Stop Recording error.RuntimeException);mRecorder.reset();e.printStackTrace(); mRecorder.release();mRecorder = null;setState(IDLE_STATE);/将数据插入数据库if (mFile.getPath() != null) ContentResolver cr = mContext.getContentResolver();ContentValues values = new ContentValues();
31、values.put(MediaStore.Audio.Media.DATA, mFile.getPath();String title = mFile.getName();if (title.contains(DEFAULT_RECORD_SUFFIX) Log.d(TAG, title.contains(DEFAULT_RECORD_SUFFIX) );title = title.replace(DEFAULT_RECORD_SUFFIX, );Log.d(TAG, title is + title);values.put(MediaStore.Audio.Media.TITLE, tit
32、le);values.put(MediaStore.Audio.Media.MIME_TYPE, audio/mp4);Uri uri = cr.insert(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,values);Log.d(TAG, uri is + uri);Intent intent_scanFile = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri);mContext.sendBroadcast(intent_scanFile);Log.d(TAG, sendBroadcas
33、t.);Log.d(TAG, stopRecord. success);此函数是将暂停录音,保存录音文件、插入数据库、发送广播来扫描录制的此文件封装到了一起。 在主线程中只需调用这三个函数即可完成录音文件的创建和保存,大大优化了效率,以及代码的复用性。4.3开机自启动的设置Android系统启动的时候,首先会进行一些诸如硬件自检之类的操作,这些操作完成以后(至少它应该知道当前的机器有没有电),会检查一下当前手机按键的状态(接下来就是所谓刷机模式切换了,不同的android手机有不同的按键组合用来进入刷机模式),如果此时按键状态处于刷机组合,那么系统会调用ROM里面的一个叫做recovery的程
34、序;如果此时按键没有标明是刷机模式,那么系统会创建内存盘,开始从ROM里面载入相应的文件系统,并把相关的文件拷贝到内存盘中,进而引导linux启动,然后是启动虚拟机dalvik,然后就是创建工作进程载入和运行framework,然后就会看到待机的画面。当然在这个过程中还发生了许多事情,启动了许多服务,我们就利用他启动Framework层和加载所有应用程序之后,发送BOOT_COMPLETED 广播消息,就好像告诉所有的应用程序手机启动起来了。BroadcastReceiver(广播接收器)是Android中的四大组件之一。此程序就是利用BroadcastReceiver来接受BOOT_COMP
35、LETED消息,然后就开始监听用户的电话状态。public void onReceive(Context context, Intent intent) Log.d(TAG, action + intent.getAction();mContext = context;Log.d(TAG ,flag is + flag);if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)SharedPreferences prefs = context.getSharedPreferences(com.android.work_prefere
36、nces, 0);boolean boot_turn_on = prefs.getBoolean(BootTurnOn, false);boolean turn_on = prefs.getBoolean(isTurnOn, false);/开机自启动关闭,录音功能开启 ,关闭录音if (!boot_turn_on & turn_on)flag = STATE_CLOSE;prefs.edit().putBoolean(isTurnOn, false).commit(); else if(boot_turn_on & turn_on)flag = STATE_OPEN; else if(boo
37、t_turn_on & !turn_on)flag = STATE_OPEN;prefs.edit().putBoolean(isTurnOn, true).commit();这样就实现了开机自启动的功能。4.4录音文件的管理 在此程序中实现了一个简单的文件管理器,利用ListActivity的布局方式,将已经录下的录音文件按照时间顺序进行排列。该界面里面的数据一个像数组或者是光标一样,通过绑定数据资源来陈列一系列选项的活动。当我们选择这些选项时,将会触发一个事件。ListActivity主持操作着一个列表视图对象,这个列表视图能绑定不同的数据资源,典型的就是一个持有查询结果的数组或者是光标。
38、ListActivity有一个默认的布局,这个布局由单一的、全屏列表构成。我们通过在onCreate()中使用setContentView()设置自己的视图布局来定制自己的屏幕布局。如果要完成这些,我们自己的视图必须包含一个id为“android:id/list”的ListView对象。如果我们的列表为空时,可以包含另外一个视图对象,这个空的列表必须有一个android:empty值的id,注意到当有一个空的视图显示时,这个列表视图将会在没有任何数据时被隐藏。简单的说就是首先将数据放到一个Adapter中,然后listActivity会自动的将数据按照线性进行排列,给用户一种简单,严谨的体验。
39、在此界面也实现了用户对录音文件的简单管理,如删除等操作。文件名的选择是根据跟你通话人的电话号码,在通讯录数据库中自动索引此人名字并且显示出来,如果索引不到,就会以电话号码作为此文件的显示名称,让用户一目了然,非常快速的找到自己想要的录音文件。4.5功能的开启和关闭此功能利用sharedPreference来进行保存开启和关闭的状态。 SharedPreferences是Android平台上一个轻量级的存储类,主要是保存一些常用的配置比如窗口状态,一般在Activity中 重载窗口状态onSaveInstanceState保存一般使用SharedPreferences完成,它提供了Android
40、平台常规的Long长 整形、Int整形、String字符串型的保存。在Android系统中,在主界面有一个checkbox用户来进行对电话录音功能的开启和关闭。当用户点击,程序会监听用户的点击事件,从而调用此函数:public boolean onPreferenceChange(Preference preference, Object newValue) Log.d(TAG, preference.key is + preference.getKey() + newValue is + newValue.toString();if (preference.getKey().equals(i
41、sTurnOn) if (newValue.toString().equals(true) /PhoneReceiver.setFlag(PhoneReceiver.STATE_OPEN); else if (newValue.toString().equals(false) /PhoneReceiver.setFlag(PhoneReceiver.STATE_CLOSE);Intent intent = new Intent(com.phonereceiver.state.close);this.sendBroadcast(intent);Log.d(TAG, sendBroadcast c
42、om.phonereceiver.state.close.);/设置将连接状态置为falseSharedPreferences prefs = this.getSharedPreferences(com.android.phone.record.master_preferences, 0);prefs.edit().putBoolean(STRING_CONNECT_STATE, false).commit();return true;修改SharedPreferences中的的标志位,来对开启和关闭录音进行操作。4.6录音文件格式的选择录音文件格式的保存实现方法与上面录音功能开启和关闭的方法
43、相同,Mediarecorder初始化时,可以进行MediaRecorder.OutputFormat的设置,我们程序里面使用了最常见的3gpp和AMR格式,来供用户进行选择。当然跟上面相同,通过修改SharedPreferences中的的key-value键值对来进行保存,当初始化时,会从SharedPreferences中得到此数据。5.关键程序设计 下面进行此程序的关键设计,就是如何监听电话的呼入和呼出状态。开发应用程序的时候,我们希望能够监听电话的呼入,以便执行暂停音乐播放器等操作,当电话结束之后,再次恢复播放。在Android平台可以通过TelephonyManager和PhoneS
44、tateListener来完成此任务。TelephonyManager作为一个Service接口提供给用户查询电话相关的内容,比如IMEI,LineNumber1。通过下面的代码即可获得TelephonyManager的实例。TelephonyManager mTelephonyMgr = (TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE);在Android平台中,PhoneStateListener是个很有用的监听器,用来监听电话的状态,比如呼叫状态和连接服务等。其方法如下所示:public void onC
45、allForwardingIndicatorChanged(boolean cfi)public void onCallStateChanged(int state, String incomingNumber)public void onCellLocationChanged(CellLocation location)public void onDataActivity(int direction)public void onDataConnectionStateChanged(int state)public void onMessageWaitingIndicatorChanged(boolean mwi)public