如何从连接到android、java解决方案的外部USB驱动器读取文件

问题描述 投票:0回答:1

我有一个 React Native 应用程序,在连接外部 USB 设备时需要找到某个根目录。 DataXYZ.txt 文件并能够共享它,因为据我所知 React Native 不提供这样的功能,我决定用 java 编写一个模块,但我无法弄清楚,请帮忙

这是一个检查设备是否已连接的模块,您需要扩展它

package com.awesomeproject.usb;

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 androidx.annotation.NonNull;

import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.LifecycleEventListener;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.modules.core.DeviceEventManagerModule;

import java.util.HashMap;

public class UsbDeviceListenerModule extends ReactContextBaseJavaModule implements LifecycleEventListener {

    private final ReactApplicationContext reactContext;
    private final BroadcastReceiver usbReceiver;
    private boolean isInitialized = false;

    public UsbDeviceListenerModule(ReactApplicationContext reactContext) {
        super(reactContext);
        this.reactContext = reactContext;

        // Регистрация слушателя жизненного цикла
        reactContext.addLifecycleEventListener(this);

        usbReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String action = intent.getAction();
                if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {
                    UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                    if (device != null) {
                        sendDeviceConnectedEvent(device);
                    }
                } else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
                    UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                    if (device != null) {
                        sendDeviceDisconnectedEvent(device);
                    }
                }
            }
        };

        // Регистрация ресивера для прослушивания подключений и отключений
        IntentFilter filter = new IntentFilter();
        filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
        filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
        reactContext.registerReceiver(usbReceiver, filter);
    }

    @NonNull
    @Override
    public String getName() {
        return "UsbDeviceListener";
    }

    @Override
    public void invalidate() {
        super.invalidate();
        // Отмена регистрации ресивера при уничтожении модуля
        reactContext.unregisterReceiver(usbReceiver);
        reactContext.removeLifecycleEventListener(this);
    }

    @Override
    public void onHostResume() {
        if (!isInitialized) {
            checkForConnectedUsbDevices();
            isInitialized = true;
        }
    }

    @Override
    public void onHostPause() {
        // Не требуется действия при паузе
    }

    @Override
    public void onHostDestroy() {
        // Не требуется действия при уничтожении
    }

    private void checkForConnectedUsbDevices() {
        UsbManager usbManager = (UsbManager) reactContext.getSystemService(Context.USB_SERVICE);
        HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();
        if (!deviceList.isEmpty()) {
            for (UsbDevice device : deviceList.values()) {
                sendDeviceConnectedEvent(device);
            }
        }
    }

    private void sendDeviceConnectedEvent(UsbDevice device) {
        WritableMap deviceData = Arguments.createMap();
        deviceData.putString("deviceName", device.getDeviceName());
        deviceData.putInt("vendorId", device.getVendorId());
        deviceData.putInt("productId", device.getProductId());
        deviceData.putInt("deviceClass", device.getDeviceClass());
        deviceData.putInt("deviceSubclass", device.getDeviceSubclass());
        deviceData.putInt("deviceProtocol", device.getDeviceProtocol());

        if (reactContext.hasActiveCatalystInstance()) {
            reactContext
                .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                .emit("UsbDeviceConnected", deviceData);
        }
    }

    private void sendDeviceDisconnectedEvent(UsbDevice device) {
        WritableMap deviceData = Arguments.createMap();
        deviceData.putString("deviceName", device.getDeviceName());

        if (reactContext.hasActiveCatalystInstance()) {
            reactContext
                .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                .emit("UsbDeviceDisconnected", deviceData);
        }
    }
}

java react-native module usb
1个回答
0
投票

您共享的模块使用“BroadcastReceiver”检测USB设备何时连接或断开。下一步是查看 USB 设备的存储以查找名为 DataXYZ.txt 的文件。如果我们找到它,我们可以创建一个意图,告诉 android 我们想要共享这个文件。我们可以显示可以处理该文件的应用程序列表,用户可以选择一个来共享该文件。这是扩展代码:

package com.awesomeproject.usb;

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.net.Uri;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.documentfile.provider.DocumentFile;

import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.LifecycleEventListener;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.modules.core.DeviceEventManagerModule;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;

public class UsbDeviceListenerModule extends ReactContextBaseJavaModule implements LifecycleEventListener {

    private static final String TAG = "UsbDeviceListener";
    private final ReactApplicationContext reactContext;
    private final BroadcastReceiver usbReceiver;
    private boolean isInitialized = false;

    public UsbDeviceListenerModule(ReactApplicationContext reactContext) {
        super(reactContext);
        this.reactContext = reactContext;

        // Регистрация слушателя жизненного цикла
        reactContext.addLifecycleEventListener(this);

        usbReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String action = intent.getAction();
                if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {
                    UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                    if (device != null) {
                        sendDeviceConnectedEvent(device);
                        findAndShareFile(device);
                    }
                } else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
                    UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                    if (device != null) {
                        sendDeviceDisconnectedEvent(device);
                    }
                }
            }
        };

        // Регистрация ресивера для прослушивания подключений и отключений
        IntentFilter filter = new IntentFilter();
        filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
        filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
        reactContext.registerReceiver(usbReceiver, filter);
    }

    @NonNull
    @Override
    public String getName() {
        return "UsbDeviceListener";
    }

    @Override
    public void invalidate() {
        super.invalidate();
        // Отмена регистрации ресивера при уничтожении модуля
        reactContext.unregisterReceiver(usbReceiver);
        reactContext.removeLifecycleEventListener(this);
    }

    @Override
    public void onHostResume() {
        if (!isInitialized) {
            checkForConnectedUsbDevices();
            isInitialized = true;
        }
    }

    @Override
    public void onHostPause() {
        // Не требуется действия при паузе
    }

    @Override
    public void onHostDestroy() {
        // Не требуется действия при уничтожении
    }

    private void checkForConnectedUsbDevices() {
        UsbManager usbManager = (UsbManager) reactContext.getSystemService(Context.USB_SERVICE);
        HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();
        if (!deviceList.isEmpty()) {
            for (UsbDevice device : deviceList.values()) {
                sendDeviceConnectedEvent(device);
                findAndShareFile(device);
            }
        }
    }

    private void findAndShareFile(UsbDevice device) {
        File usbDirectory = new File("/storage");

        if (usbDirectory.exists() && usbDirectory.isDirectory()) {
            File file = searchFileInDirectory(usbDirectory, "DataXYZ.txt");

            if (file != null && file.exists()) {
                shareFile(file);
            } else {
                Log.e(TAG, "DataXYZ.txt not found on USB device: " + device.getDeviceName());
            }
        } else {
            Log.e(TAG, "USB directory not found or is not a directory");
        }
    }

    private File searchFileInDirectory(File directory, String fileName) {
        File[] files = directory.listFiles();

        if (files != null) {
            for (File file : files) {
                if (file.isDirectory()) {
                    File foundFile = searchFileInDirectory(file, fileName);
                    if (foundFile != null) {
                        return foundFile;
                    }
                } else if (fileName.equalsIgnoreCase(file.getName())) {
                    return file;
                }
            }
        }
        return null;
    }

    private void shareFile(File file) {
        Uri fileUri = Uri.fromFile(file);

        Intent shareIntent = new Intent();
        shareIntent.setAction(Intent.ACTION_SEND);
        shareIntent.setType("text/plain");
        shareIntent.putExtra(Intent.EXTRA_STREAM, fileUri);
        shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

        Intent chooserIntent = Intent.createChooser(shareIntent, "Share file via");

        chooserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        reactContext.startActivity(chooserIntent);
    }

    private void sendDeviceConnectedEvent(UsbDevice device) {
        WritableMap deviceData = Arguments.createMap();
        deviceData.putString("deviceName", device.getDeviceName());
        deviceData.putInt("vendorId", device.getVendorId());
        deviceData.putInt("productId", device.getProductId());
        deviceData.putInt("deviceClass", device.getDeviceClass());
        deviceData.putInt("deviceSubclass", device.getDeviceSubclass());
        deviceData.putInt("deviceProtocol", device.getDeviceProtocol());

        if (reactContext.hasActiveCatalystInstance()) {
            reactContext
        .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                .emit("UsbDeviceConnected", deviceData);
        }
    }

    private void sendDeviceDisconnectedEvent(UsbDevice device) {
        WritableMap deviceData = Arguments.createMap();
        deviceData.putString("deviceName", device.getDeviceName());

        if (reactContext.hasActiveCatalystInstance()) {
            reactContext
        .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                .emit("UsbDeviceDisconnected", deviceData);
        }
    }
}

确保添加:“READ_EXTERNAL_STORAGE”权限和任何其他必要的权限。此外,您需要更新文件位置。

© www.soinside.com 2019 - 2024. All rights reserved.