完整的工程(源碼):http://download.csdn.net/detail/zhujinghao09/5313666
完整的工程(源碼):http://download.csdn.net/detail/zhujinghao09/5313666
因為這個版本只是功能實現的測試版,所以介面做的很醜,請大家見諒,主要看功能哦!!
主要功能:
串連伺服器,並開啟一個監聽來信的線程,如果有來信,開啟接收檔案線程;
按鈕控制發送語音線程;
使用第三方類實現原生未壓縮的錄音格式 .wav;
使用android 系統內建的mediaPlayer 實現聲音播放功能;
第一步: 串連伺服器
btnConnect.setOnClickListener(newButton.OnClickListener()
{
@Override
publicvoid onClick(View arg0) {
//TODO Auto-generated method stub
//IP=etIp.getContext().toString();
IP= etIp.getText().toString();
try{
Port= Integer.parseInt(etPort.getText().toString());
}catch(Exceptione)
{
Log.i(Tag,"IP"+IP+"port"+Port);
Toast.makeText(MainActivity.this,"請輸入正確的連接埠號碼!!",Toast.LENGTH_LONG).show();
return;
}
try{
client= new Socket(IP, Port); //串連伺服器
}catch (UnknownHostException e) {
//TODO Auto-generated catch block
e.printStackTrace();
Toast.makeText(MainActivity.this,"UnknownHostException", Toast.LENGTH_LONG).show();
return;
}catch (IOException e) {
//TODO Auto-generated catch block
e.printStackTrace();
Toast.makeText(MainActivity.this,"IOException!",Toast.LENGTH_LONG).show();
return;
}
PrintWriterout;
try{
out= new PrintWriter(client.getOutputStream(), true);
out.println("Android"); //向伺服器發送用戶端名稱
}catch (IOException e) {
//TODO Auto-generated catch block
e.printStackTrace();
}
tvState.setText("串連伺服器成功!!!");
SocketListensListen = new SocketListen(client,mHandler); //開啟監聽接收線程
sListen.SetControlBar(tvRecvCount);
sListen.start();
}
});
第二步:監聽接收線程
package er.fly;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.net.Socket;import er.fly.nettandclient.MyHandler;import android.util.Log;import android.widget.TextView;public class SocketListen extends Thread{ private Socket client; //private String savepath="/sdcard/MyVoice/"; MyHandler mHandler; MyHandler SLHandler; TextView tvR; public SocketListen(Socket s,MyHandler h) { this.client=s; mHandler = h; } public void SetControlBar(TextView tv) { tvR = tv; } public void run() { int len; if (client == null) return; while(true) //迴圈監聽來信 { BufferedReader in;// = new BufferedReader(new InputStreamReader(System.in));// 接收來自 server 的響應資料try {in = new BufferedReader(new InputStreamReader(client.getInputStream()));try{String strlen= in.readLine(); //讀取網路流,檔案長度//System.out.println("File Size :"+strlen);Log.i("SocketListen", strlen);len = Integer.parseInt(strlen);//開啟接收檔案線程 DownloadFile downFile = new DownloadFile(client,len); downFile.SetHanglers(mHandler, SLHandler);downFile.SetControlBar(tvR);downFile.start();//this.suspend();while(true) //判斷檔案是否接收完成//等待 {if(!downFile.isAlive())break;}}catch(IOException e){Log.i("SocketListen", "no recv");}} catch (IOException e) {// TODO Auto-generated catch block//e.printStackTrace();} } }}
接收檔案線程類:
package er.fly;import java.io.BufferedOutputStream;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.Socket;import java.util.Date;import er.fly.nettandclient.MyHandler;import android.os.Looper;import android.os.Message;import android.util.Log;import android.widget.TextView;//import er.fly.nettandclient;public class DownloadFile extends Thread{private Socket client; File file=null; String sendinfo=null; int fileLen; String tag = "DownloadFile"; MyHandler mHandler; //用於子線程和主線程通訊,更新聲音列表 MyHandler SLHandler; TextView tvRecvCount; String recvVoiceSavePath; public DownloadFile(Socket s,int l){ this.client = s; fileLen=l;} public void SetHanglers(MyHandler m,MyHandler sl) { mHandler = m; SLHandler = sl; } public void SetControlBar(TextView tv) { tvRecvCount = tv; } // 建立目錄(不存在則建立) public File CreateDir(String dir) { File file = new File(dir); if (!file.exists()) { file.mkdirs(); } return file; } public void run() { Looper curLooper = Looper.myLooper(); Looper mainLooper = Looper.getMainLooper(); String msg=null; boolean flag = false; if(client == null) { return ; } try { InputStream inputStream = client.getInputStream();byte[] buffer = new byte[1024]; int readCount = 0; int count=0; CreateDir("sdcard/MyRecvVoice/"); int h = new Date().getHours();int m = new Date().getMinutes();int s = new Date().getSeconds();String strTime = String.valueOf(h)+"-"+String.valueOf(m)+"-"+String.valueOf(s); BufferedOutputStream fo = new BufferedOutputStream(new FileOutputStream(new File("sdcard/MyRecvVoice/"+strTime+".wav"))); //迴圈接收檔案 while (true) { readCount = inputStream.read(buffer); count = count+readCount; fo.write(buffer, 0,readCount); //System.out.println("recv len " + String.valueOf(count)+"readCount "+String.valueOf(readCount)); Log.i(tag, "recv len"+ String.valueOf(count)+"readCount "+String.valueOf(readCount)); if(count>=fileLen) //判斷接收結束 break; } flag = true; recvVoiceSavePath="sdcard/MyRecvVoice/"+strTime+".wav"; Log.i(tag,"接收成功!!"); fo.flush(); fo.close(); //inputStream.close();// 一定不能關閉輸入輸出資料流,因為關閉它們的同時也會關閉socket //這個很重要 //outputStream.close(); } catch(IOException e) { e.printStackTrace(); } mHandler = new MyHandler(mainLooper); mHandler.SetHandlerArgs(tvRecvCount); if(flag) msg="DownloadFile:"+recvVoiceSavePath+"#"+"接收成功!!"; else msg="DownloadFile:"+"$"+"接收失敗!!"; mHandler .removeMessages(0); Message m = mHandler .obtainMessage(1, 1, 1, msg);//向主線程發信,通知接收結束 mHandler .sendMessage(m); }}
傳送檔案線程類:
package er.fly;import java.io.BufferedReader;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.PrintWriter;import java.net.Socket;import java.net.SocketException;import android.util.Log;public class UpFile extends Thread{private Socket client; File file=null; String Tag ="UpFile"; public UpFile(Socket client) { this.client = client; } public void SetFile(File file){ this.file = file; } public void run(){ if(client == null) { return ; } if(client.isOutputShutdown()) { try {client.setKeepAlive(true);} catch (SocketException e) {// TODO Auto-generated catch blocke.printStackTrace();Log.i(Tag, "client setKeepAlive worry");} } FileInputStream reader = null; FileInputStream readLen = null; byte[] buf = null; try{ InputStream inPut = client.getInputStream(); OutputStream outPut = client.getOutputStream(); readLen = new FileInputStream(file); ByteArrayOutputStream ow = new ByteArrayOutputStream(); int count =0; int buffersize= 256; int fileLen=0; buf = new byte[buffersize]; while ((count = readLen.read(buf)) > 0) //讀取檔案位元組長度 { fileLen = fileLen + count; } String strLen =String.valueOf(fileLen); strLen = strLen+"\n"; Log.i(Tag, strLen); byte[] buffLen = strLen.getBytes(); byte[] buffL = new byte[50]; for(int i=0;i<50;i++) //把檔案位元組長度添加到一個長度為50位元組數組中 //因為服務也是一次接收50個位元組 { if(i<buffLen.length) { buffL[i]=buffLen[i]; } else { buffL[i]= 0; } } outPut.write(buffL); //傳送檔案長度位元組數組 outPut.flush(); // 把網路流發送出去,否則伺服器接收不到 count =0; //讀取檔案位元組,並迴圈發送 reader = new FileInputStream(file); while ((count = reader.read(buf)) > 0) { ow.write(buf, 0, count); Log.i(Tag, "reading file"); } Log.i(Tag, "開始發送!!"); outPut.write(ow.toByteArray()); outPut.flush(); Log.i(Tag, "檔案發送完成!!!"); // client.shutdownOutput(); //一定不能加這句話,否則socket關閉發送流,以後就不能在此發送,這也是問什麼用檔案位元組長度來判斷接收結束原因 } catch(Exception e) { System.out.println("socket執行異常:" + e.toString()); }finally { try { // 結束對象 buf = null; // out.close(); //out一定不能關閉,因為同事也會關閉socket // out.close(); // in.close(); reader.close(); // client.close(); } catch (Exception e) { } } }}
完整的工程(源碼):http://download.csdn.net/detail/zhujinghao09/5313666