You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity3D开发安卓APP实现PC USB数据接收方案求助

Got it, let's tackle this problem head-on. The issue with System.IO.Ports on Android makes total sense—it's a desktop-focused API that doesn't play nice with Android's USB subsystem. Here are three solid, actionable solutions to get your Unity Android app receiving data from a PC over USB:

1. Android USB Host API + Unity Native Plugin

Android's built-in USB Host API lets your app directly interact with USB devices when the device is in host mode. You'll need to build a small Android plugin in Android Studio, then bridge it to Unity.

Step 1: Add Required Permissions

Add these permissions to your AndroidManifest.xml (either in your Android Studio plugin project or Unity's Plugins/Android folder):

<uses-feature android:name="android.hardware.usb.host" android:required="true" />
<uses-permission android:name="android.permission.USB_PERMISSION" />

Step 2: Build the Android Plugin

Create a Java class to handle USB detection, permission requests, and data reading. Here's a simplified example:

package com.yourcompany.usbplugin;

import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager;
import android.util.Log;
import com.unity3d.player.UnityPlayer;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;

public class USBCommunication {
    private static final String ACTION_USB_PERMISSION = "com.yourcompany.usbplugin.USB_PERMISSION";
    private UsbManager usbManager;
    private InputStream inputStream;
    private Thread readThread;
    private boolean isReading = false;

    public USBCommunication() {
        usbManager = (UsbManager) UnityPlayer.currentActivity.getSystemService(Context.USB_SERVICE);
        registerPermissionReceiver();
    }

    private void registerPermissionReceiver() {
        BroadcastReceiver permissionReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String action = intent.getAction();
                if (ACTION_USB_PERMISSION.equals(action)) {
                    synchronized (this) {
                        UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                        if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                            if (device != null) openDevice(device);
                        } else {
                            Log.d("USBPlugin", "Permission denied for device " + device);
                        }
                    }
                }
            }
        };
        UnityPlayer.currentActivity.registerReceiver(permissionReceiver, new IntentFilter(ACTION_USB_PERMISSION));
    }

    public void findAndRequestDevice(int vendorId, int productId) {
        HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();
        for (UsbDevice device : deviceList.values()) {
            if (device.getVendorId() == vendorId && device.getProductId() == productId) {
                PendingIntent permissionIntent = PendingIntent.getBroadcast(UnityPlayer.currentActivity, 0, new Intent(ACTION_USB_PERMISSION), 0);
                usbManager.requestPermission(device, permissionIntent);
                break;
            }
        }
    }

    private void openDevice(UsbDevice device) {
        try {
            UsbDeviceConnection connection = usbManager.openDevice(device);
            if (connection != null && connection.claimInterface(device.getInterface(0), true)) {
                inputStream = connection.openInputStream(0);
                startReading();
            }
        } catch (IOException e) {
            Log.e("USBPlugin", "Error opening device: " + e.getMessage());
        }
    }

    private void startReading() {
        isReading = true;
        readThread = new Thread(() -> {
            byte[] buffer = new byte[1024];
            int bytesRead;
            try {
                while (isReading && inputStream != null) {
                    bytesRead = inputStream.read(buffer);
                    if (bytesRead > 0) {
                        String data = new String(buffer, 0, bytesRead);
                        UnityPlayer.UnitySendMessage("USBReceiver", "OnDataReceived", data);
                    }
                }
            } catch (IOException e) {
                Log.e("USBPlugin", "Error reading data: " + e.getMessage());
            }
        });
        readThread.start();
    }

    public void stopReading() {
        isReading = false;
        try {
            if (inputStream != null) inputStream.close();
        } catch (IOException e) {
            Log.e("USBPlugin", "Error closing stream: " + e.getMessage());
        }
    }
}

Step 3: Call the Plugin from Unity

Create a C# script to interface with the plugin:

using UnityEngine;

public class USBDataReceiver : MonoBehaviour
{
    private AndroidJavaObject usbPlugin;

    void Start()
    {
        usbPlugin = new AndroidJavaObject("com.yourcompany.usbplugin.USBCommunication");
        // Replace with your PC USB device's vendor and product IDs
        usbPlugin.Call("findAndRequestDevice", 0x1234, 0x5678);
    }

    // Called from the Android plugin when data arrives
    public void OnDataReceived(string data)
    {
        Debug.Log("Received from PC: " + data);
        // Process your data here
    }

    void OnDestroy()
    {
        usbPlugin?.Call("stopReading");
    }
}

2. ADB Reverse Proxy + Socket Communication

If you want to skip native Android code, this quick workaround uses ADB to forward a PC port to your Android device, then uses standard TCP sockets in Unity.

Step 1: Set Up Port Forwarding

On your PC, open a command prompt and run:

adb reverse tcp:8080 tcp:8080

This maps port 8080 on your PC to port 8080 on your Android device.

Step 2: PC Side - Socket Server

Write a simple Python server to send data:

import socket

server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('localhost', 8080))
server_socket.listen(1)

print("Waiting for Android connection...")
conn, addr = server_socket.accept()
print("Connected to", addr)

while True:
    data = input("Enter data to send: ")
    conn.send(data.encode('utf-8'))

Step 3: Unity Side - Socket Client

Add this C# script to a Unity GameObject:

using UnityEngine;
using System.Net.Sockets;
using System.Text;
using System.Threading;

public class SocketDataReceiver : MonoBehaviour
{
    private TcpClient client;
    private NetworkStream stream;
    private Thread readThread;
    private bool isConnected = false;

    void Start()
    {
        readThread = new Thread(ConnectAndRead);
        readThread.Start();
    }

    private void ConnectAndRead()
    {
        try
        {
            client = new TcpClient("localhost", 8080);
            isConnected = true;
            stream = client.GetStream();
            byte[] buffer = new byte[1024];
            int bytesRead;

            while (isConnected)
            {
                bytesRead = stream.Read(buffer, 0, buffer.Length);
                if (bytesRead > 0)
                {
                    string data = Encoding.UTF8.GetString(buffer, 0, bytesRead);
                    Debug.Log("Received: " + data);
                    // Process data here
                }
            }
        }
        catch (System.Exception e)
        {
            Debug.LogError("Socket error: " + e.Message);
            isConnected = false;
        }
    }

    void OnDestroy()
    {
        isConnected = false;
        stream?.Close();
        client?.Close();
        readThread?.Abort();
    }
}

Note: This requires USB debugging to be enabled on your Android device—great for prototyping, but not ideal for production.

3. Pre-built USB Serial Library for Android

Libraries like usb-serial-for-android handle low-level serial communication, so you don't have to write it from scratch.

Step 1: Import the Library

Download the library's AAR/JAR file and place it in Unity's Plugins/Android folder.

Step 2: Unity C# Wrapper

Here's a simplified wrapper to use the library:

using UnityEngine;
using System.Threading;
using System.Text;

public class UsbSerialReceiver : MonoBehaviour
{
    private AndroidJavaObject serialPort;
    private Thread readThread;
    private bool isReading = false;

    void Start()
    {
        AndroidJavaObject usbManager = new AndroidJavaClass("android.hardware.usb.UsbManager")
            .CallStatic<AndroidJavaObject>("getSystemService", UnityPlayer.currentActivity);
        AndroidJavaObject deviceList = usbManager.Call<AndroidJavaObject>("getDeviceList");
        AndroidJavaObject entrySet = deviceList.Call<AndroidJavaObject>("entrySet");
        AndroidJavaIterator iterator = entrySet.Call<AndroidJavaIterator>("iterator");

        while (iterator.Call<bool>("hasNext"))
        {
            AndroidJavaObject entry = iterator.Call<AndroidJavaObject>("next");
            AndroidJavaObject device = entry.Call<AndroidJavaObject>("getValue");
            int vendorId = device.Call<int>("getVendorId");
            int productId = device.Call<int>("getProductId");

            if (vendorId == 0x1234 && productId == 0x5678)
            {
                AndroidJavaObject driver = new AndroidJavaObject("com.hoho.android.usbserial.driver.Cp21xxSerialDriver", device);
                serialPort = driver.Call<AndroidJavaObject>("getPorts")[0];
                serialPort.Call("open", usbManager);
                serialPort.Call("setParameters", 9600, 8, 1, 0);
                StartReading();
                break;
            }
        }
    }

    private void StartReading()
    {
        isReading = true;
        readThread = new Thread(() =>
        {
            byte[] buffer = new byte[1024];
            int bytesRead;
            AndroidJavaObject inputStream = serialPort.Call<AndroidJavaObject>("getInputStream");

            while (isReading)
            {
                bytesRead = inputStream.Call<int>("read", buffer);
                if (bytesRead > 0)
                {
                    string data = Encoding.UTF8.GetString(buffer, 0, bytesRead);
                    Debug.Log("Received serial data: " + data);
                }
            }
        });
        readThread.Start();
    }

    void OnDestroy()
    {
        isReading = false;
        serialPort?.Call("close");
        readThread?.Abort();
    }
}

Note: Don't forget to add the USB permissions to your AndroidManifest.xml as in the first solution.

Which Solution Should You Pick?

  • Option 1: Best for production apps needing full USB control, no ADB dependency. Requires basic Android dev knowledge.
  • Option 2: Fastest prototyping solution, but relies on USB debugging.
  • Option 3: Balances ease of use and functionality for serial USB devices (like Arduino).

内容的提问来源于stack exchange,提问作者Kheoss - Vlad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:44:43