由于公司要做一个手机间传输图片的功能,网上的资料又太过杂乱,没有达到我想要的效果,于是自己前前后后折腾了好久,终于把这个功能做出来,现在分享出来。话不多说,上代码。
服务端代码
/* 服务器端接收数据 服务器应该要多线程,一个服务器可能会有多个客户端进行连接; */ public void receiveData() { Thread thread = new Thread() { @Override public void run() { super.run(); /*指明服务器端的端口号*/ try { serverSocket = new ServerSocket(8000); } catch (IOException e) { e.printStackTrace(); } //获取IP地址 GetIpAddress.getLocalIpAddress(serverSocket); Message message_2 = handler.obtainMessage(); message_2.what = 2; message_2.obj = GetIpAddress.getIP() + " " + GetIpAddress.getPort(); handler.sendMessage(message_2); while (true) { try { mSocket = serverSocket.accept(); socketStatus = true; } catch (IOException e) { e.printStackTrace(); } //开启接收数据的线程 new ServerThread(mSocket).start(); } } }; thread.start(); }
接收线程数据的代码
class ServerThread extends Thread { private Socket socket; private InputStream inputStream; public ServerThread(Socket socket) { this.socket = socket; } @Override public void run() { while (true) { if (socketStatus) { try { inputStream = socket.getInputStream(); } catch (IOException e) { e.printStackTrace(); } int len; byte[] bytes = new byte[1024]; boolean isString = false; try { //这里必须是无限循环的,因为服务端要随时等待客户端发送数据 //当客户端断开后其结果等于-1,循环结束 while ((len = inputStream.read(bytes)) != -1) { for (int i = 0; i < len; i++) { if (bytes[i] != '\0') { stringBuffer.append((char) bytes[i]); } else { isString = true; break; } } if (isString) { Message message_1 = handler.obtainMessage(); message_1.what = 1; message_1.obj = stringBuffer; handler.sendMessage(message_1); isString = false; stringBuffer = new StringBuffer(); } } //当这个异常发生时,说明客户端那边的连接已经断开 } catch (IOException e) { e.printStackTrace(); try { inputStream.close(); socket.close(); } catch (IOException e1) { e1.printStackTrace(); } } } } } }
接下来是客户端代码
首先是连接的代码
public void connect(View view) { ip = editText_1.getText().toString(); if (ip == null) { Toast.makeText(MainActivity.this, "please input Server IP", Toast.LENGTH_SHORT).show(); } Thread thread = new Thread() { @Override public void run() { super.run(); if (!socketStatus) { try { String msg = null; socket = new Socket(ip, 8000); if (socket == null) { msg = "连接失败"; } else { socketStatus = true; msg = "连接成功"; outputStream = socket.getOutputStream(); //receive(); } Message message_3 = handler.obtainMessage(); message_3.what = 3; message_3.obj = msg; handler.sendMessage(message_3); } catch (IOException e) { e.printStackTrace(); Log.e("MainActivity", "run: --->>" + e); } } } }; thread.start(); }
然后是发送图片的方法,这里我用R文件下的图片代替
public void send(View view){ Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.wugeng); data = convertIconToString(bitmap); if (data == null) { Toast.makeText(MainActivity.this, "please input Sending Data", Toast.LENGTH_SHORT).show(); } else { //在后面加上 '\0' ,是为了在服务端方便我们去解析; data = data + '\0'; } Thread thread = new Thread() { @Override public void run() { super.run(); if (socketStatus) { try { outputStream.write(data.getBytes()); } catch (IOException e) { e.printStackTrace(); Log.e("MainActivity", "run: --->>" + e); } } } }; thread.start(); }
最后,最重要的一步!!!
请加上权限
<uses-permission android:name="android.permission.INTERNET" /> <!-- 网络权限 -->大功告成,图片传输要经过base64加密解密传输的,代码里的message是通过handler发送消息到主线程去更新UI,相信大家应该都知道吧。记住,socket一般都是放在子线程去操作的。
附上保存图片到本地和从本地获取图片的代码
首先是保存到本地
public void saveBitmapForSdCard(String bitName, Bitmap mBitmap) { //创建file对象 File f = new File("/sdcard/" + bitName + ".png"); try { //创建 f.createNewFile(); } catch (IOException e) { } FileOutputStream fOut = null; try { fOut = new FileOutputStream(f); } catch (FileNotFoundException e) { e.printStackTrace(); } //原封不动的保存在内存卡上 mBitmap.compress(Bitmap.CompressFormat.PNG, 100, fOut); try { fOut.flush(); } catch (IOException e) { e.printStackTrace(); } try { fOut.close(); } catch (IOException e) { e.printStackTrace(); } }然后是从固定路径获取图片的方法,这里就写固定值了
private Bitmap getDiskBitmap(String pathString) { Bitmap bitmap = null; try { File file = new File(pathString); if(file.exists()) { bitmap = BitmapFactory.decodeFile(pathString); } } catch (Exception e) { // TODO: handle exception } return bitmap; }