在USB主机模式下,将数据从安卓设备发送到连接的USB存储设备

3
在我的应用程序中,我使用USB主机模式来获取有关已连接的USB大容量存储设备(例如USB闪存驱动器)的信息。现在,我需要在连接的闪存驱动器上创建一个文件,并将一些数据保存到该文件中。目前为止,我发现可以按以下方式连接到该设备:

MainActivity.java

public class MainActivity extends AppCompatActivity {

        private static final String TAG = MainActivity.class.getSimpleName();
        private Button mCheckForDevice;
        private TextView mDeviceInfo;
        private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";
        private PendingIntent mPermissionIntent;
        private UsbManager mUsbManager;
        private UsbDevice mDeviceFound;
        private UsbDeviceConnection mConnection;
        private UsbInterface mUsbInterface = null;
        private UsbEndpoint mInputEndpoint = null;
        private UsbEndpoint mOutputEndpoint = null;

        @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mCheckForDevice = (Button) findViewById(R.id.check);
            mDeviceInfo = (TextView) findViewById(R.id.deviceInfo);
            count=0;

            mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
            mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);

            final HashMap<String, UsbDevice> deviceList = mUsbManager.getDeviceList();
            Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
            IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
            registerReceiver(mUsbReceiver, filter);


            while (deviceIterator.hasNext()) {
                final UsbDevice device = deviceIterator.next();
                mDeviceFound = device;
                i += "\n" +
                        "DeviceID: " + device.getDeviceId() + "\n" +
                        "DeviceName: " + device.getDeviceName() + "\n" +
                        "VendorID: " + device.getVendorId() + "\n" +
                        "ProductID: " + device.getProductId() + "\n" +
                        "Serial Number: " + device.getSerialNumber() + "\n";
            }
            mCheckForDevice.setOnClickListener(new View.OnClickListener() {
                @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
                @Override
                public void onClick(View v) {
                    if(deviceList.size() > 0){
                        checkInfo(mDeviceFound);
                    }else{
                        Toast.makeText(getApplicationContext(), "No device found", Toast.LENGTH_SHORT).show();
                    }
                }
            });
        }
        String i = "";
        private int count ;
        private void checkInfo(UsbDevice device) {
            count++;
            if(count == 1) {
                mUsbManager.requestPermission(device, mPermissionIntent);
                mDeviceInfo.setText(i);

            } else
                Toast.makeText(this, "Already connected", Toast.LENGTH_SHORT).show();
        }

        @Override
        protected void onPause() {
            super.onPause();
            count=0;
            try {
                unregisterReceiver(mUsbReceiver);
            }catch (Exception e){
                e.printStackTrace();
            }
        }

        private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {

            public void onReceive(Context context, Intent intent) {
                String action = intent.getAction();
//            Toast.makeText(context, "onReceive", Toast.LENGTH_SHORT).show(); writeToFile("onReceive");
                if (ACTION_USB_PERMISSION.equals(action)) {
                    synchronized (this) {
                        UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                        if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                            Toast.makeText(context, "Permission Granted", Toast.LENGTH_SHORT).show();
                            connectUsb(device);
                        } else {
                            Log.d(TAG, "permission denied for device " + device);
                            Toast.makeText(context, "permission denied for device" + device, Toast.LENGTH_SHORT).show();
                        }
                    }
                }
            }
        };


        private void connectUsb(UsbDevice device) {
            if(device != null){
                for(int i=0;i<device.getInterfaceCount();i++){
                    mUsbInterface = device.getInterface(i);
                    UsbEndpoint tOut = null;
                    UsbEndpoint tIn = null;
                    int usbEndPointCount = mUsbInterface.getEndpointCount();
                    if(usbEndPointCount >=2){
                        for(int j =0;j<usbEndPointCount;j++){
                            if(mUsbInterface.getEndpoint(j).getType() == UsbConstants.USB_ENDPOINT_XFER_BULK){
                                if(mUsbInterface.getEndpoint(j).getDirection() == UsbConstants.USB_DIR_OUT){
                                    tOut = mUsbInterface.getEndpoint(j);
                                }else if(mUsbInterface.getEndpoint(j).getDirection() == UsbConstants.USB_DIR_IN){
                                    tIn = mUsbInterface.getEndpoint(j);
                                }
                            }
                        }
                        if(tIn!=null & tOut !=null){
                            mInputEndpoint = tIn;
                            mOutputEndpoint = tOut;
                        }
                    }
                }
                mConnection = mUsbManager.openDevice(device);
                if (mConnection.claimInterface(mUsbInterface, true)) {
                    Toast.makeText(this, "Connected to device", Toast.LENGTH_SHORT).show();

                    String msg = "Hello world";
                    byte[] byteArray = msg.getBytes();
                    int dataTransfered = mConnection.bulkTransfer(mOutputEndpoint,byteArray,byteArray.length, 0);

                    int controlTransfer = mConnection.controlTransfer( UsbConstants.USB_DIR_OUT, 1,0,0,byteArray,byteArray.length,0);
                    Toast.makeText(this, "controlTransfer " +controlTransfer, Toast.LENGTH_SHORT).show();

                } else {
                    Log.i(TAG, "Could not connect!");
                    Toast.makeText(this, "Could not connect", Toast.LENGTH_SHORT).show();
                }
            }else{
                Toast.makeText(this, "Null", Toast.LENGTH_SHORT).show();
            }
        }

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">


    <Button
        android:id="@+id/check"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Search for devices "
        android:textColor="@color/black"
        android:textSize="15sp" />

    <TextView
        android:id="@+id/deviceInfo"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_below="@+id/check"
        android:layout_marginTop="14dp"
        android:textColor="@color/black"
        android:textSize="15sp" />
</RelativeLayout>

在上面的示例中,我尝试将String值发送到连接的设备,并返回的int值是发送的字符数。但是这些信息存储在连接的设备上的位置在哪里?
一旦与设备建立连接,是否有办法在连接的设备上创建文件?相关博客帖子的链接会很有帮助。
我在Stack Overflow上找到了这个,但解决方案没有任何帮助。
非常感谢您的帮助。

这些信息存储在连接设备中的哪个位置?你可以通过其他方式查看设备,然后很快就会发现有什么变化。 - greenapps
请回复我的评论。 - greenapps
mOutputEndpoint = tOut; 这两个变量的类型没有显示。你为什么要在其他地方声明它们? - greenapps
当然你之前可以告诉我。你想把字节存储在哪里?你指的是哪个地方? - greenapps
1
为什么不使用存储访问框架或存储卷来实现呢? - greenapps
显示剩余12条评论
2个回答

4
您正在搜索批量端点,这意味着您正在尝试使用BBB进行扇区读/写(请参阅USB规范的大容量存储类BBB)。
现在我需要在连接的闪存驱动器上创建一个文件,并在文件中保存一些数据。使用端点执行扇区读/写,但您必须在其上编写文件系统驱动程序(例如FAT32或EXT4等)。文件创建是文件系统操作,不是扇区级别的读/写。
一旦建立与设备的连接,是否有一种方法可以在已连接设备上创建文件?您必须使用Android文件系统挂载功能,然后使用通用文件API来创建文件。

@artkoenig和Kuldeep Singh Dhaka,感谢你们的回复。 - Shree

0

在尝试了所有建议的想法后,我找到了可接受的解决方案。使用UsbHost Api获取设备相关信息,然后使用Storage Access Framework执行文件操作。


我需要在iOS方面的一点帮助。 - Jigar
告诉我,Jigar,我能为你做些什么? - Shree
当我尝试使用登录方法时,fbskd会显示弹出窗口,类似于“xyz应用程序想要登录”的内容。与此类似的问题可以参考https://dev59.com/9FYO5IYBdhLWcg3wDNQb。 - Jigar
1
抱歉,我对此一无所知。如果问题与您提到的链接类似,请在那里留言以寻求他人的帮助。 - Shree

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接