版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010302327/article/details/80661582
公司要求搞个手机控制电视盒子的功能,涉及到文件传输和控制指令,网上有很多例子,简单的总结一下,使用一个socket线程来进行文件传输和指令传输
server端WifiFileServers.java
public class WifiFileServers { private ServerSocket serverSocket = null; private String serversIp; private Handler mHandler; private HandlerThread handlerThread; private Socket socket = null; private OnServersListener serversListener; public WifiFileServers(final int port){ handlerThread = new HandlerThread("WifiFileServers"); handlerThread.start(); mHandler = new Handler(handlerThread.getLooper()); mHandler.post(new Runnable() { @Override public void run() { //开启socket try { serverSocket = new ServerSocket(port); } catch (IOException e) { e.printStackTrace(); } serversIp = GetIpAddress.getLocalIpAddress(); } }); } public void startServers(final OnServersListener listener){ serversListener = listener; mHandler.post(new Runnable() { @Override public void run() { int port = serverSocket.getLocalPort(); serversListener.onServersIp(serversIp,port); //等待连接,我这里做的是单连接,多连接可以建个连接类,把socket放到连接类中 while (!serverSocket.isClosed()){ try { socket = serverSocket.accept(); } catch (IOException e) { e.printStackTrace(); } //连接成功开始接收数据,如果多连接需要多开线程 if(socket != null){ start(); } } } }); } public void start() { int port = serverSocket.getLocalPort(); String ip = socket.getInetAddress().getHostAddress(); serversListener.onConnect(port,ip); long length = 0; int len; FileOutputStream fos = null; File file = null; //用于接收文件数据 byte[] bytes = new byte[8192]; //用于接收字符串 ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { File path = new File(Environment.getExternalStorageDirectory()+"/HMSDK/video"); if(!path.exists()){ path.mkdir(); } int type = -1; String fileName = null; long size = 0; //等待数据 while ((len = socket.getInputStream().read(bytes)) != -1) { //数据长度为1的时候,可能为client端发来的数据类型标签 if(len == 1){ //0表示准备发送字符串 if(bytes[0] == '0' && type == -1){ type = 1; //准备好接收字符串 socket.getOutputStream().write('0'); }else if(bytes[0] == '\0' && type == 1){//表示字符串接收完成 //转成字符串 String data = new String(baos.toByteArray(),"utf8"); baos.flush(); baos.close(); baos.reset(); //开始解析 String t = data.substring(0,1); if("0".equals(t)){ fileName = data.substring(1,data.length()); }else if("1".equals(t)){ length = Long.valueOf(data.substring(1,data.length())); }else if("3".equals(t)){//正常字符串 serversListener.onReceive(port,ip,data.substring(1,data.length())); } type = -1; //通知client字符串接收完成 socket.getOutputStream().write('1'); }else if(bytes[0] == '5' && type == -1){//准备接收文件 type = 0; size = 0; //创建文件 if(fileName != null){ file = new File(Environment.getExternalStorageDirectory()+"/HMSDK/video", fileName); if (file.exists()) { file.delete(); } fos = new FileOutputStream(file); } //通知client端准备接收数据 socket.getOutputStream().write('5'); }else if(type == 0 && fos != null) {//接收只有1的数据 fos.write(bytes, 0, len); fos.flush(); size += len; serversListener.onData(port,ip,fileName,length,size); //接收到的数据和文件大小相等 if(size == length){ //接收完成,通知client端 type = -1; fos.close(); socket.getOutputStream().write('9'); serversListener.onOver(port,ip,fileName); fileName = null; } }else if(type == 1){//字符串最后1位数据 baos.write(bytes,0,len); } }else{ if(type == 1){ if(bytes[len -1] == '\0'){//字符串最后1位是\0,表示字符串接收结束 baos.write(bytes,0,len -1); String data = new String(baos.toByteArray(),"utf8"); baos.flush(); baos.close(); baos.reset(); String t = data.substring(0,1); if("0".equals(t)){ fileName = data.substring(1,data.length()); }else if("1".equals(t)){ length = Long.valueOf(data.substring(1,data.length())); }else if("3".equals(t)){ serversListener.onReceive(port,ip,data.substring(1,data.length())); } type = -1; socket.getOutputStream().write('1'); }else{ //正常接收 baos.write(bytes,0,len); } }else if(type == 0 && fos != null){ fos.write(bytes, 0, len); fos.flush(); size += len; serversListener.onData(port,ip,fileName,length,size); if(size == length){ type = -1; fos.close(); socket.getOutputStream().write('9'); serversListener.onOver(port,ip,fileName); fileName = null; } } } } } catch (IOException e) { e.printStackTrace(); }finally { serversListener.onDisconnect(port,ip); try { socket.getInputStream().close(); socket.getOutputStream().close(); socket.close(); if(fos != null){ fos.close(); } } catch (IOException e1) { e1.printStackTrace(); } } } public void release(){ try { serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } handlerThread.quit(); } interface OnServersListener{ void onServersIp(String serversIp,int port); void onConnect(int port,String clientIp); void onData(int port,String clientIp,String fileName,long size,long progress); void onReceive(int port, String clientIp, String data); void onOver(int port, String clientIp,String fileName); void onDisconnect(int port,String clientIp); } }
MainActivity.java
public class MainActivity extends AppCompatActivity { private TextView editText_1; private TextView editText_2; private EditText editText_data; private WifiFileServers wifiFileServers; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); editText_1 = findViewById(R.id.et_1); editText_2 = findViewById(R.id.et_2); editText_data = findViewById(R.id.et_data); //创建文件夹 File file = new File(Environment.getExternalStorageDirectory()+"/HMSDK/video"); if(file.exists()){ file.mkdir(); } receiveData(); } public void send(View view){ } public void receiveData(){ //初始化 wifiFileServers = new WifiFileServers(8068); //开启server线程 wifiFileServers.startServers(fileListener); } //释放socket资源 @Override public void onBackPressed() { super.onBackPressed(); wifiFileServers.release(); } //回调 WifiFileServers.OnServersListener fileListener = new WifiFileServers.OnServersListener() { @Override public void onServersIp(final String serversIp, final int port) { runOnUiThread(new Runnable() { @Override public void run() { editText_1.setText("IP:" + serversIp + " PORT: " + port); } }); } @Override public void onConnect(int port, final String clientIp) { runOnUiThread(new Runnable() { @Override public void run() { editText_1.setText(clientIp+"连接成功"); } }); } @Override public void onData(int port, String clientIp, final String fileName, final long size, final long progress) { runOnUiThread(new Runnable() { @Override public void run() { long p = progress*100/size; editText_2.setText(fileName+p+"%"); } }); } @Override public void onReceive(int port, String clientIp, String data) { } @Override public void onOver(int port, String clientIp, String fileName) { } @Override public void onDisconnect(int port, final String clientIp) { runOnUiThread(new Runnable() { @Override public void run() { editText_1.setText(clientIp+"断开连接"); } }); } }; }
布局就不贴了
client端ClientFileServers.java
public class ClientFileServers { private Socket socket = null; private OutputStream outputStream = null; private InputStream inputStream = null; private OnServersListener serversListener; private Handler mHandler; private HandlerThread handlerThread; private int port; public ClientFileServers() { handlerThread = new HandlerThread("ClientFileServers"); handlerThread.start(); mHandler = new Handler(handlerThread.getLooper()); } //连接 public void connect(final String ip, final int port, OnServersListener listener) { serversListener = listener; this.port = port; mHandler.post(new Runnable() { @Override public void run() { try { socket = new Socket(ip, port); outputStream = socket.getOutputStream(); inputStream = socket.getInputStream(); serversListener.onConnect(port); } catch (IOException e) { e.printStackTrace(); serversListener.onError(port, -1); } } }); } private boolean sendString(String data) throws IOException{ byte[] buffer = new byte[8192]; //先发送个0给server端,0表示接下来要发送字符串数据 outputStream.write('0'); //接收server端的反馈,0表示准备完成 if(inputStream.read(buffer) != -1){ if(buffer[0] != '0'){ return false; } } //发送数据 byte[] b = data.getBytes("utf8"); outputStream.write(b,0,b.length); //'\0'表示字符串结束 outputStream.write('\0'); //接收server反馈,1表示接收成功 if(inputStream.read(buffer) != -1){ if(buffer[0] != '1'){ return false; } } return true; } //发生文字 public void sendData(final String data){ mHandler.post(new Runnable() { @Override public void run() { try { if(!sendString(data)){ serversListener.onError(port,3); return; } serversListener.onSendData(port); } catch (IOException e) { e.printStackTrace(); synchronized (ClientFileServers.this){ try { if(outputStream != null){ outputStream.close(); outputStream = null; } if(inputStream != null){ inputStream.close(); inputStream = null; } if(socket != null){ socket.close(); socket = null; serversListener.onDisconnect(port); } } catch (IOException e1) { e1.printStackTrace(); } } } } }); } //发送文件 public void sendFile(final File file) { mHandler.post(new Runnable() { @Override public void run() { FileInputStream fis = null; try { //先发送文件名,在文件名前加个0表示这段数据是文件名,也可用json格式,看自己写法 String path = "0"+file.getName(); //通过发送字符串的形式发送 if(!sendString(path)){ serversListener.onError(port,3); return; } //再发送文件大小,1表示文件长度 String l = "1"+file.length(); if(!sendString(l)){ serversListener.onError(port,3); return; } //5表示告诉server要开始发送文件数据 byte[] b = new byte[8192]; // 8k outputStream.write('5'); //server反馈5表示server准备好接收 if(inputStream.read(b) != -1){ if(b[0] != '5'){ serversListener.onError(port,3); return ; } } //发送文件数据 fis = new FileInputStream(file); long size = 0; byte[] buffer = new byte[8192]; // 8k int len; while ((len = fis.read(buffer)) != -1) { size += len; outputStream.write(buffer, 0, len); outputStream.flush(); serversListener.onSendFile(port,file.length(),size); } //等待server端反馈,9表示接收成功 if(inputStream.read(b) != -1){ if(b[0] != '9'){ serversListener.onError(port,3); return ; } } serversListener.onReceive(port); } catch (IOException e) { e.printStackTrace(); synchronized (ClientFileServers.this){ try { if(outputStream != null){ outputStream.close(); outputStream = null; } if(inputStream != null){ inputStream.close(); inputStream = null; } if(socket != null){ socket.close(); socket = null; serversListener.onDisconnect(port); } if(fis != null){ fis.close(); } } catch (IOException e1) { e1.printStackTrace(); } } } } }); } public void release() { synchronized (ClientFileServers.this){ try { if(inputStream != null){ inputStream.close(); inputStream = null; } if (outputStream != null) { outputStream.close(); outputStream = null; } if (socket != null) { socket.close(); socket = null; serversListener.onDisconnect(port); } } catch (IOException e) { e.printStackTrace(); } } handlerThread.quit(); } interface OnServersListener { void onConnect(int port); void onSendData(int port); void onSendFile(int port,long size,long progress); void onReceive(int port); void onDisconnect(int port); void onError(int port, int error); } }
MainActivity.java
public class MainActivity extends AppCompatActivity { private String[] denied; private String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE}; private EditText editText_data; private TextView editText_ip; private TextView editText_receive; private String ip = "192.168.1.38"; private String fileName = "1520564093079.mp4"; // 1520583417803 1520564093079 1521533868730 1528278027688 1528363714863 private ClientFileServers fileServers; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); editText_ip = findViewById(R.id.et_ip); editText_data = findViewById(R.id.et_data); editText_receive = findViewById(R.id.et_receive); editText_ip.setText(ip); //权限 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { ArrayList<String> list = new ArrayList<>(); for (int i = 0; i < permissions.length; i++) { if (PermissionChecker.checkSelfPermission(this, permissions[i]) == PackageManager.PERMISSION_DENIED) { list.add(permissions[i]); } } if (list.size() != 0) { denied = new String[list.size()]; for (int i = 0; i < list.size(); i++) { denied[i] = list.get(i); ActivityCompat.requestPermissions(this, denied, 5); } } else { init(); } } else { init(); } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if (requestCode == 5) { boolean isDenied = false; for (int i = 0; i < denied.length; i++) { String permission = denied[i]; for (int j = 0; j < permissions.length; j++) { if (permissions[j].equals(permission)) { if (grantResults[j] != PackageManager.PERMISSION_GRANTED) { isDenied = true; break; } } } } if (isDenied) { Toast.makeText(this, "请开启权限", Toast.LENGTH_SHORT).show(); } else { init(); } } super.onRequestPermissionsResult(requestCode, permissions, grantResults); } private void init(){ //初始化socket fileServers = new ClientFileServers(); } public void connect(View view){ //连接server端 fileServers.connect(ip,8068,serversListener); } public void send(View view){ //发送文件 String f = Environment.getExternalStorageDirectory()+"/HMSDK/video/"+fileName; File file = new File(f); fileServers.sendFile(file); } //当客户端界面返回时,关闭相应的socket资源 @Override public void onBackPressed() { super.onBackPressed(); fileServers.release(); } //回调 private ClientFileServers.OnServersListener serversListener = new ClientFileServers.OnServersListener() { @Override public void onConnect(int port) { runOnUiThread(new Runnable() { @Override public void run() { editText_ip.setText(ip+"连接成功"); } }); } @Override public void onSendData(int port) { } @Override public void onSendFile(int port, final long size, final long progress) { runOnUiThread(new Runnable() { @Override public void run() { long p = progress*100/size; editText_receive.setText(fileName+p+"%"); } }); } @Override public void onReceive(int port) { runOnUiThread(new Runnable() { @Override public void run() { editText_receive.setText("文件接收成功"); } }); } @Override public void onDisconnect(int port) { } @Override public void onError(int port, int error) { } }; }