用dw制作视频网站,百度域名对应的ip地址,成都房地产政策,建设沙滩车官方网站可以先参考下这篇博客#xff0c;讲得比较详细 http://www.jizhuomi.com/android/example/354.html
然后我看到这篇博客很叼#xff0c;其它的文章质量也非常不错#xff0c;http://blog.csdn.net/gyhgx/article/details/51669892
项目中需要实现基于Android 6.0 的双向通…可以先参考下这篇博客讲得比较详细 http://www.jizhuomi.com/android/example/354.html
然后我看到这篇博客很叼其它的文章质量也非常不错http://blog.csdn.net/gyhgx/article/details/51669892
项目中需要实现基于Android 6.0 的双向通话自动录音功能在查阅相关android电话状态监听文章以及git上的开源录音项目后整理出此文 实现手机电话状态的监听主要依靠两个类 TelephoneManger和PhoneStateListener TelephonseManger提供了取得手机基本服务的信息的一种方式。因此应用程序可以使用TelephonyManager来探测手机基本服务的情况。应用程序可以注册listener来监听电话状态的改变。 我们不能对TelephonyManager进行实例化只能通过获取服务的形式
code classhljs mathematica has-numbering styledisplay: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: Source Code Pro, monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;span classhljs-keyword stylecolor: rgb(0, 0, 136); box-sizing: border-box;Context/span.getSystemService(span classhljs-keyword stylecolor: rgb(0, 0, 136); box-sizing: border-box;Context/span.TELEPHONY_SERVICE);/codeul classpre-numbering stylebox-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);li stylebox-sizing: border-box; padding: 0px 5px;1/li/ul 注意对手机的某些信息进行读取是需要一定许可permission的。 主要静态成员常量它们对应PhoneStateListener.LISTEN_CALL_STATE所监听到的内容
int CALL_STATE_IDLE //空闲状态没有任何活动。int CALL_STATE_OFFHOOK //摘机状态至少有个电话活动。该活动或是拨打dialing或是通话或是 on hold。并且没有电话是ringing or waitingint CALL_STATE_RINGING //来电状态电话铃声响起的那段时间或正在通话又来新电新来电话不得不等待的那段时间。项目中使用服务来监听通话状态所以需要弄清楚手机通话状态在广播中的对应值
code classhljs javascript has-numbering styledisplay: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: Source Code Pro, monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;EXTRA_STATE_IDLE span classhljs-comment stylecolor: rgb(136, 0, 0); box-sizing: border-box;//它在手机通话状态改变的广播中用于表示CALL_STATE_IDLE状态即空闲状态。/spanEXTRA_STATE_OFFHOOK span classhljs-comment stylecolor: rgb(136, 0, 0); box-sizing: border-box;//它在手机通话状态改变的广播中用于表示CALL_STATE_OFFHOOK状态即摘机状态。/spanEXTRA_STATE_RINGING span classhljs-comment stylecolor: rgb(136, 0, 0); box-sizing: border-box;//它在手机通话状态改变的广播中用于表示CALL_STATE_RINGING状态即来电状态/spanACTION_PHONE_STATE_CHANGED span classhljs-comment stylecolor: rgb(136, 0, 0); box-sizing: border-box;//在广播中用ACTION_PHONE_STATE_CHANGED这个Action来标示通话状态改变的广播intent。/span
span classhljs-comment stylecolor: rgb(136, 0, 0); box-sizing: border-box;//注需要许可READ_PHONE_STATE。/spanspan classhljs-built_in stylecolor: rgb(102, 0, 102); box-sizing: border-box;String/span EXTRA_INCOMING_NUMBER span classhljs-comment stylecolor: rgb(136, 0, 0); box-sizing: border-box;//在手机通话状态改变的广播用于从extra取来电号码。/spanspan classhljs-built_in stylecolor: rgb(102, 0, 102); box-sizing: border-box;String/span EXTRA_STATE span classhljs-comment stylecolor: rgb(136, 0, 0); box-sizing: border-box;//在通话状态改变的广播用于从extra取来通话状态。/span/code 如何实现电话监听呢 Android在电话状态改变是会发送action为android.intent.action.PHONE_STATE的广播而拨打电话时会发送action为
code classhljs java has-numbering styledisplay: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: Source Code Pro, monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;span classhljs-keyword stylecolor: rgb(0, 0, 136); box-sizing: border-box;public/span span classhljs-keyword stylecolor: rgb(0, 0, 136); box-sizing: border-box;static/span span classhljs-keyword stylecolor: rgb(0, 0, 136); box-sizing: border-box;final/span String ACTION_NEW_OUTGOING_CALL span classhljs-string stylecolor: rgb(0, 136, 0); box-sizing: border-box;android.intent.action.NEW_OUTGOING_CALL/span;/codeul classpre-numbering stylebox-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);li stylebox-sizing: border-box; padding: 0px 5px;1/lili stylebox-sizing: border-box; padding: 0px 5px;2/li/ul 的广播。通过自定义广播接收器接受上述两个广播便可。 下面给出Java代码(其中的Toast均为方便测试而添加)
package com.example.hgx.phoneinfo60.Recording;import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.TelephonyManager;
import android.widget.Toast;/*** Created by hgx on 2016/6/13.*/
public class PhoneCallReceiver extends BroadcastReceiver {private int lastCallState TelephonyManager.CALL_STATE_IDLE;private boolean isIncoming false;private static String contactNum;Intent audioRecorderService;public PhoneCallReceiver() {}Overridepublic void onReceive(Context context, Intent intent) {//如果是去电if (intent.getAction().equals(Intent.ACTION_NEW_OUTGOING_CALL)){contactNum intent.getExtras().getString(Intent.EXTRA_PHONE_NUMBER);}else //android.intent.action.PHONE_STATE.查了下android文档貌似没有专门用于接收来电的action,所以非去电即来电.{String state intent.getExtras().getString(TelephonyManager.EXTRA_STATE);String phoneNumber intent.getExtras().getString(TelephonyManager.EXTRA_INCOMING_NUMBER);int stateChange 0;if (state.equals(TelephonyManager.EXTRA_STATE_IDLE)){//空闲状态stateChange TelephonyManager.CALL_STATE_IDLE;if (isIncoming){onIncomingCallEnded(context,phoneNumber);}else {onOutgoingCallEnded(context,phoneNumber);}}else if (state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)){//摘机状态stateChange TelephonyManager.CALL_STATE_OFFHOOK;if (lastCallState ! TelephonyManager.CALL_STATE_RINGING){//如果最近的状态不是来电响铃的话意味着本次通话是去电isIncoming false;onOutgoingCallStarted(context,phoneNumber);}else {//否则本次通话是来电isIncoming true;onIncomingCallAnswered(context, phoneNumber);}}else if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)){//来电响铃状态stateChange TelephonyManager.CALL_STATE_RINGING;lastCallState stateChange;onIncomingCallReceived(context,contactNum);}}}protected void onIncomingCallStarted(Context context,String number){Toast.makeText(context,Incoming call is started,Toast.LENGTH_LONG).show();context.startService(new Intent(context,AudioRecorderService.class));}protected void onOutgoingCallStarted(Context context,String number){Toast.makeText(context, Outgoing call is started, Toast.LENGTH_LONG).show();context.startService(new Intent(context, AudioRecorderService.class));}protected void onIncomingCallEnded(Context context,String number){Toast.makeText(context, Incoming call is ended, Toast.LENGTH_LONG).show();context.startService(new Intent(context, AudioRecorderService.class));}protected void onOutgoingCallEnded(Context context,String number){Toast.makeText(context, Outgoing call is ended, Toast.LENGTH_LONG).show();context.startService(new Intent(context, AudioRecorderService.class));}protected void onIncomingCallReceived(Context context,String number){Toast.makeText(context, Incoming call is received, Toast.LENGTH_LONG).show();}protected void onIncomingCallAnswered(Context context, String number) {Toast.makeText(context, Incoming call is answered, Toast.LENGTH_LONG).show();}
}
下面是AudioRecorderService的java实现 package com.example.hgx.phoneinfo60.Recording;
import android.app.Service;
import android.content.Intent;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.os.AsyncTask;
import android.os.Environment;
import android.os.IBinder;
import android.provider.MediaStore;
import android.util.Log;
import android.widget.Toast;import com.example.hgx.phoneinfo60.MyApplication;import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
/*** Created by hgx on 2016/6/13.*/public class AudioRecorderService extends Service {private static int RECORD_RATE 0;private static int RECORD_BPP 32;private static int RECORD_CHANNEL AudioFormat.CHANNEL_IN_MONO;private static int RECORD_ENCODER AudioFormat.ENCODING_PCM_16BIT;private AudioRecord audioRecorder null;private Thread recordT null;private Boolean isRecording false;private int bufferEle 1024, bytesPerEle 2;// want to play 2048 (2K) since 2 bytes we use only 1024 2 bytes in 16bit formatprivate static int[] recordRate {44100 , 22050 , 11025 , 8000};int bufferSize 0;File uploadFile;Overridepublic IBinder onBind(Intent intent) {// TODO: Return the communication channel to the service.//maintain the relationship between the caller activity and the callee service, currently useless herereturn null;}Overridepublic void onDestroy() {if (isRecording){stopRecord();}else{Toast.makeText(MyApplication.getContext(), Recording is already stopped,Toast.LENGTH_SHORT).show();}super.onDestroy();}Overridepublic int onStartCommand(Intent intent, int flags, int startId) {if (!isRecording){startRecord();}else {Toast.makeText(MyApplication.getContext(), Recording is already started,Toast.LENGTH_SHORT).show();}return 1;}private void startRecord(){audioRecorder initializeRecord();if (audioRecorder ! null){Toast.makeText(MyApplication.getContext(), Recording is started,Toast.LENGTH_SHORT).show();audioRecorder.startRecording();}elsereturn;isRecording true;recordT new Thread(new Runnable() {Overridepublic void run() {writeToFile();}},Recording Thread);recordT.start();}private void writeToFile(){byte bDate[] new byte[bufferEle];FileOutputStream fos null;File recordFile createTempFile();try {fos new FileOutputStream(recordFile);} catch (FileNotFoundException e) {e.printStackTrace();}while (isRecording){audioRecorder.read(bDate,0,bufferEle);}try {fos.write(bDate);} catch (IOException e) {e.printStackTrace();}try {fos.close();} catch (IOException e) {e.printStackTrace();}}//Following function converts short data to byte dataprivate byte[] writeShortToByte(short[] sData) {int size sData.length;byte[] byteArrayData new byte[size * 2];for (int i 0; i size; i) {byteArrayData[i * 2] (byte) (sData[i] 0x00FF);byteArrayData[(i * 2) 1] (byte) (sData[i] 8);sData[i] 0;}return byteArrayData;}//Creates temporary .raw file for recordingprivate File createTempFile() {File tempFile new File(Environment.getExternalStorageDirectory(), aditi.raw);return tempFile;}//Create file to convert to .wav formatprivate File createWavFile() {File wavFile new File(Environment.getExternalStorageDirectory(), aditi_ System.currentTimeMillis() .wav);return wavFile;}/** Convert raw to wav file* param java.io.File temporay raw file* param java.io.File destination wav file* return void** */private void convertRawToWavFile(File tempFile, File wavFile) {FileInputStream fin null;FileOutputStream fos null;long audioLength 0;long dataLength audioLength 36;long sampleRate RECORD_RATE;int channel 1;long byteRate RECORD_BPP * RECORD_RATE * channel / 8;String fileName null;byte[] data new byte[bufferSize];try {fin new FileInputStream(tempFile);fos new FileOutputStream(wavFile);audioLength fin.getChannel().size();dataLength audioLength 36;createWaveFileHeader(fos, audioLength, dataLength, sampleRate, channel, byteRate);while (fin.read(data) ! -1) {fos.write(data);}uploadFile wavFile.getAbsoluteFile();} catch (FileNotFoundException e) {//Log.e(MainActivity:convertRawToWavFile,e.getMessage());} catch (IOException e) {//Log.e(MainActivity:convertRawToWavFile,e.getMessage());} catch (Exception e) {//Log.e(MainActivity:convertRawToWavFile,e.getMessage());}}/** To create wav file need to create header for the same** param java.io.FileOutputStream* param long* param long* param long* param int* param long* return void*/private void createWaveFileHeader(FileOutputStream fos, long audioLength, long dataLength, long sampleRate, int channel, long byteRate) {byte[] header new byte[44];header[0] R; // RIFF/WAVE headerheader[1] I;header[2] F;header[3] F;header[4] (byte) (dataLength 0xff);header[5] (byte) ((dataLength 8) 0xff);header[6] (byte) ((dataLength 16) 0xff);header[7] (byte) ((dataLength 24) 0xff);header[8] W;header[9] A;header[10] V;header[11] E;header[12] f; // fmt chunkheader[13] m;header[14] t;header[15] ;header[16] 16; // 4 bytes: size of fmt chunkheader[17] 0;header[18] 0;header[19] 0;header[20] 1; // format 1header[21] 0;header[22] (byte) channel;header[23] 0;header[24] (byte) (sampleRate 0xff);header[25] (byte) ((sampleRate 8) 0xff);header[26] (byte) ((sampleRate 16) 0xff);header[27] (byte) ((sampleRate 24) 0xff);header[28] (byte) (byteRate 0xff);header[29] (byte) ((byteRate 8) 0xff);header[30] (byte) ((byteRate 16) 0xff);header[31] (byte) ((byteRate 24) 0xff);header[32] (byte) (2 * 16 / 8); // block alignheader[33] 0;header[34] 16; // bits per sampleheader[35] 0;header[36] d;header[37] a;header[38] t;header[39] a;header[40] (byte) (audioLength 0xff);header[41] (byte) ((audioLength 8) 0xff);header[42] (byte) ((audioLength 16) 0xff);header[43] (byte) ((audioLength 24) 0xff);try {fos.write(header, 0, 44);} catch (IOException e) {// TODO Auto-generated catch block//Log.e(MainActivity:createWavFileHeader(),e.getMessage());}}/** delete created temperory file* param* return void*/private void deletTempFile() {File file createTempFile();file.delete();}/** Initialize audio record** param* return android.media.AudioRecord*/private AudioRecord initializeRecord() {short[] audioFormat new short[]{AudioFormat.ENCODING_PCM_16BIT, AudioFormat.ENCODING_PCM_8BIT};short[] channelConfiguration new short[]{AudioFormat.CHANNEL_IN_MONO, AudioFormat.CHANNEL_IN_STEREO};for (int rate : recordRate) {for (short aFormat : audioFormat) {for (short cConf : channelConfiguration) {//Log.d(MainActivity:initializeRecord(),RaterateAudioFormataFormatChannel ConfigurationcConf);try {int buffSize AudioRecord.getMinBufferSize(rate, cConf, aFormat);bufferSize buffSize;if (buffSize ! AudioRecord.ERROR_BAD_VALUE) {AudioRecord aRecorder new AudioRecord(MediaRecorder.AudioSource.DEFAULT, rate, cConf, aFormat, buffSize);if (aRecorder.getState() AudioRecord.STATE_INITIALIZED) {RECORD_RATE rate;//Log.d(MainActivity:InitializeRecord - AudioFormat,String.valueOf(aFormat));//Log.d(MainActivity:InitializeRecord - Channel,String.valueOf(cConf));//Log.d(MainActivity:InitialoizeRecord - rceordRate, String.valueOf(rate));return aRecorder;}}} catch (Exception e) {//Log.e(MainActivity:initializeRecord(),e.getMessage());}}}}return null;}/** Method to stop and release audio record** param* return void*/private void stopRecord() {if (null ! audioRecorder) {isRecording false;audioRecorder.stop();audioRecorder.release();audioRecorder null;recordT null;Toast.makeText(getApplicationContext(), Recording is stopped, Toast.LENGTH_LONG).show();}convertRawToWavFile(createTempFile(), createWavFile());if (uploadFile.exists()) {//Log.d(AudioRecorderService:stopRecord(), UploadFile exists);}new UploadFile().execute(uploadFile);deletTempFile();}/** Asynchronous task to upload audio file in background***/private class UploadFile extends AsyncTaskFile, Void, Void {protected Void doInBackground(File... files) {if (files[0] null)return null;try {File fileToUpload files[0];String boundary *****;String lineEnd \r\n;String twoHyphens --;int maxBufferSize 1 * 1024 * 1024;String fileName fileToUpload.getAbsolutePath();FileInputStream fis new FileInputStream(new File(fileName));URL serverUrl new URL(http://192.168.78.128/UploadToServer.php);HttpURLConnection connection (HttpURLConnection) serverUrl.openConnection();connection.setDoInput(true);connection.setDoOutput(true);connection.setUseCaches(false);connection.setRequestMethod(POST);connection.setRequestProperty(Connection, Keep-Alive);connection.setRequestProperty(ENCTYPE, multipart/form-data);connection.setRequestProperty(Content-Type, multipart/form-data;boundary boundary);connection.setRequestProperty(uploaded_file, fileName);DataOutputStream dos new DataOutputStream(connection.getOutputStream());dos.writeBytes(twoHyphens boundary lineEnd);dos.writeBytes(Content-Disposition: form-data; name\uploadedfile\;filename\ fileName \ lineEnd);dos.writeBytes(lineEnd);// create a buffer of maximum sizeint bytesAvailable fis.available();int bufferSize Math.min(bytesAvailable, maxBufferSize);byte[] buffer new byte[bufferSize];// read file and write it into form...int bytesRead fis.read(buffer, 0, bufferSize);while (bytesRead 0) {dos.write(buffer, 0, bufferSize);bytesAvailable fis.available();bufferSize Math.min(bytesAvailable, maxBufferSize);bytesRead fis.read(buffer, 0, bufferSize);}dos.writeBytes(lineEnd);dos.writeBytes(twoHyphens boundary twoHyphens lineEnd);// Responses from the server (code and message)int serverResponseCode connection.getResponseCode();String serverResponseMessage connection.getResponseMessage();// /Log.d(AudioRecorderService:AsyncTask,String.valueOf(serverResponseCode));// /Log.d(AudioRecorderService:AsyncTask,serverResponseMessage);if (serverResponseCode 200) {Toast.makeText(getApplicationContext(), File is uploaded successfully, Toast.LENGTH_SHORT).show();}//close the streams //fis.close();dos.flush();dos.close();} catch (Exception e) {Log.e(AudioRecorder:Asynctask, e.getMessage());}return null;}}
}