android服务(service)初步——通话录音
启动服务之后,监听手机TelephonyManager状态,根据不同情况做出选择,源码以及截图如下:
生成的录音文件:
Log日志:
这个不知道为什么,点击多次停止服务的时候,总是会出现下面的BUG:
图片看不清楚,我把日志复制了出来如下:
09-21 19:56:31.850: ERROR/audio_input(34): unsupported parameter: x-pvmf/media-input-node/cap-config-interface;valtype=key_specific_value
09-21 19:56:31.850: ERROR/audio_input(34): VerifyAndSetParameter failed
知道原因的,麻烦告诉我,灰常感激。。。俺百度了好久不知道为啥。
源码:
MainActivity:
package com.song; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; public class PhoneListenerActivity extends Activity { protected static final String ACTION = "recordingFlag"; protected static final String TAG = "TAG"; Button btnStart; Button btnStop; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); btnStart = (Button) findViewById(R.id.btnstart); btnStop = (Button) findViewById(R.id.btnstop); btnStart.setOnClickListener(new Button.OnClickListener() { @Override public void onClick(View v) { Log.v(TAG, "startService"); startService(new Intent(ACTION)); } }); btnStop.setOnClickListener(new Button.OnClickListener() { @Override public void onClick(View v) { Log.v(TAG, "stopService"); stopService(new Intent(ACTION)); } }); } }
服务类:
package com.song; import java.io.IOException; import android.app.Service; import android.content.Context; import android.content.Intent; import android.media.MediaRecorder; import android.os.Environment; import android.os.IBinder; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; import android.util.Log; public class PhoneListenerService extends Service { private MediaRecorder recorder; private boolean recording = false; @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { TelephonyManager manager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); manager.listen(listener, PhoneStateListener.LISTEN_CALL_STATE); super.onCreate(); } private PhoneStateListener listener = new PhoneStateListener() { @Override public void onCallStateChanged(int state, String incomingNumber) { super.onCallStateChanged(state, incomingNumber); switch (state) { case TelephonyManager.CALL_STATE_IDLE:// 空闲或者挂断 // 挂断就停止录音 stopRecord(); break; case TelephonyManager.CALL_STATE_RINGING:// 响铃 // 响铃什么都不做 break; case TelephonyManager.CALL_STATE_OFFHOOK:// 接起电话 // 接起电话开始录音 recordCalling(); break; default: break; } } }; private void stopRecord() { if (recording) { Log.v("TAG", "stopRecord"); recorder.stop(); recorder.release();// 释放资源 } } private void recordCalling() { try { Log.v("TAG", "recordCalling"); recorder = new MediaRecorder(); recorder.setAudioSource(MediaRecorder.AudioSource.MIC); recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); recorder.setOutputFile(Environment.getExternalStorageDirectory() .getAbsolutePath()+"/" + System.currentTimeMillis() + ".3gp"); recorder.prepare(); recorder.start(); recording = true; }catch (Exception e) { e.printStackTrace(); } } }
配置文件:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.song" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="8" /> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".PhoneListenerActivity" 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=".PhoneListenerService"> <intent-filter> <action android:name="recordingFlag"/> </intent-filter> </service> </application> <uses-permission android:name="android.permission.READ_PHONE_STATE"/> <uses-permission android:name="android.permission.RECORD_AUDIO"/> <!-- 向sdcard中写数据的权限 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> </manifest>