无网络PC通过USB与多个Android设备通讯

本文介绍了在无网络环境下,如何通过USB让PC与多个Android设备进行通讯。利用ADB将USB模拟为网卡,Android设备作为服务端监听命令,PC作为客户端发送指令,实现在PC上自动检测并上传Android设备数据的功能。详细阐述了实现思路,并提供了Android服务端(MainActivity.java, TcpConnectRunnable.java)和PC客户端(FrmClient.cs, SocketClient.cs, DriverDetector.cs)的实现代码。" 104944928,1254369,使用Tkinter创建文件浏览工具,"['前端开发', 'Python', 'GUI']

前言

应用场景

适用于工作环境无网络,只能通过USB将多台Android端数据上传到一台PC端的情况。

实现效果
  1. 启动PC端工作站
  2. 自动检测通过USB连接的Android端设备
  3. 自动启动Android端数据上传app
  4. 通过Socket向Android端发送命令
  5. Android端通过Socket上传数据
  6. 上传完成后自动关闭app

PC端工作站可长时间开启,外业人员工作回来后,将设备插到电脑上即可,上传操作将会自动执行,可同时插入多台Android设备。

实现思路
  • 通过ADB将USB模拟为网卡
  • Android端作为服务端,创建ServerSocket,监听客户端命令
  • PC端作为客户端,请求建立Socket连接,向Android端发送命令

Android服务端实现

MainActivity.java
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    private TextView tvText;

    private TcpConnectRunnable tcpConnectRunnable = new TcpConnectRunnable(new TcpConnectRunnable.Callback() {
        @Override
        public void call(final String msg) {
            // 回调信息显示到消息输出窗口
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    tvText.append(msg + "\r\n");
                    if (msg.contains("quit")) {
                        finish();
                    }
                }
            });
        }
    });

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        tvText = findViewById(R.id.tv_message);

        // 清空消息输出窗口
        findViewById(R.id.btn_clear).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                tvText.setText("");
            }
        });

        // 开启Socket服务器
        new Thread(tcpConnectRunnable).start();
    }

    @Override
    protected void onDestroy() {
        tcpConnectRunnable.stop();
        super.onDestroy();
    }
}
TcpConnectRunnable.java
import android.text.TextUtils;
import android.util.Log;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * Socket服务器,持续监听客户端连接
 */
public class TcpConnectRunnable implements Runnable {

    private static final String TAG = TcpConnectRunnable.class.getSimpleName();
    private final int SERVER_PORT = 10086;
    private ServerSocket serverSocket;
    private Socket client;
    private Callback callback;

    private boolean isRun = false;

    public TcpConnectRunnable(Callback callback) {
        this.callback = callback;
    }

    /**
     * 停止
     */
    public void stop() {
        isRun = false;
    }

    @Override
    public void run() {
        isRun = true;

        try {
            String ip = InetAddress.getLocalHost().getHostAddress();
            serverSocket = new ServerSocket(SERVER_PORT);
            callback.call("建立服务器:[" + ip + ":" + SERVER_PORT + "]");
        }catch (IOException e) {
            callback.call("建立服务器异常:" + e.getMessage());
        }

        while (isRun) {
            BufferedOutputStream out = null;
            BufferedReader in = null;
            try {
                client = serverSocket.accept();
                callback.call("建立连接:" + client.getInetAddress().toString() + ":" + client.getPort());
                out = new BufferedOutputStream(client.getOutputStream());
                in = new BufferedReader(new InputStreamReader(client.getInputStream()));

                if (isRun == false) {
                    break;
                }
                String request = receive(in);
                if (TextUtils.isEmpty(request))
                {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    continue;
                }
                callback.call("client: " + request);

                if ("quit".equals(request)) {
                    callback.call("origin request: " + request);
                    break;
                }

                if (isRun == false) {
                    break;
                }
                send(out, request);
            } catch (IOException e) {
                Log.e(TAG, "run: ", e);
                callback.call(e.getMessage());
            } finally {
                close(out);
                close(in);
                close(client);
            }
        }
    }

    /**
     * 向客户端发送数据
     * @param out
     * @param msg
     * @throws IOException
     */
    private void send(OutputStream out, String msg) throws IOException {
        msg += "\n";
        out.write(msg.getBytes("utf-8"));
    }

    /**
     * 接收客户端的请求,并返回应答
     * @param in
     * @return
     * @throws IOException
     */
    private String receive(BufferedReader in) throws IOException {
        String r = in.readLine();
        if (TextUtils.isEmpty(r)) {
            return "";
        }
  
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值