3

In my application am using USB host mode which gives the information about connected USB mass storage device say Usb Flash Drive in my use case.Now I need to create a file on the connected flash drive and save some data in the file. So far I have found is connecting to the device as below,

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>

In the above example I have tried to send the String value to the connected device and the int value returned is number of characters sent. But Where do this information is stored on the connected device I mean location?

Is there a way to create a file on connected device once the connection to the device is established? Links to related blog posts are helpful.

I have found this on stack but the solution not helped in any way.

Any help is appreciated.Thanks.

Shree
  • 354
  • 2
  • 21
  • `But Where do this information is stored on the connected device I mean location?`. Well you could have a look on the device by other mean.s. Then you would soon discover what changed. – greenapps Feb 09 '18 at 10:37
  • Please react to the point to my comment. – greenapps Feb 09 '18 at 10:40
  • `mOutputEndpoint = tOut;` Of both variables you dont show the type. Why did you declare them somewhere else? – greenapps Feb 09 '18 at 10:41
  • You could have told that before of course. Where is it that you wanted the bytes to be stored? Which place did you indicate? – greenapps Feb 09 '18 at 10:42
  • And before you try to write something would not it be better trying to read first? – greenapps Feb 09 '18 at 10:44
  • they are of type USbEndPoint. Do you have any idea where it get stores? – Shree Feb 09 '18 at 10:45
  • Use an empty flash drive and you will soon know. And why should those bytes be written to file? Or stored? Cannot it be interpreted as command? – greenapps Feb 09 '18 at 10:46
  • 1
    Why dont you use the Storage Access Framework or Storage Volumes to do so? – greenapps Feb 09 '18 at 10:49
  • Please show how you register your receiver then i will try your code. I will not chat. – greenapps Feb 09 '18 at 10:50
  • Meanwhile i expect you to answer my question about SAF and SV. – greenapps Feb 09 '18 at 11:26
  • How did you define `ACTION_USB_PERMISSION` ? – greenapps Feb 09 '18 at 13:11
  • Please post complete code. Your variables with names starting with `m` are not declared nor initialized. This takes too much time to test. Please post code that can be copy-pasted. You are supposed to post complete code. – greenapps Feb 09 '18 at 13:27
  • Check my edited post. Just copy and paste the xml and .java file as it is and run and lemme know where am going wrong. Thanks – Shree Feb 10 '18 at 04:53
  • @greenapps, Any update? – Shree Feb 10 '18 at 11:17
  • Sorry. After the weekend. Have to see olympics now ;-). This gives you time to investigate SAF. – greenapps Feb 10 '18 at 11:20
  • The broadcast receiver is never invoked. I wonder how the used permission could ever work: `private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";` I also tried `"android.hardware.usb.action.USB_PERMISSION"` but that did not help. Anything needed in manifest you did not tell? ` – greenapps Feb 11 '18 at 10:53
  • Already answered [here](https://stackoverflow.com/questions/26283639/android-usb-host-api-and-usb-storage) – artkoenig Feb 15 '18 at 21:28

2 Answers2

4

You are searching bulk endpoints which means you are trying to sector read/write using BBB (See USB Specs for Mass Storage class BBB).

Now I need to create a file on the connected flash drive and save some data in the file.
Using endpoints you perform sector read/write but you have to write filesystem driver (Like FAT32 or EXT4 etc) on top of it. File creation is a filesystem operation, not sector level read/write.

Is there a way to create a file on connected device once the connection to the device is established?
You have to use Android filesystem mounting facility and then use the generic file API to create files.

Kuldeep Dhaka
  • 533
  • 5
  • 22
0

After going with all suggested ideas I have found the solution which works as accepted. Use UsbHost Api to get the device related information and then use Storage Access Framework to perform the filing operation.

Shree
  • 354
  • 2
  • 21
  • i need a little help in ios – Jigar Mar 07 '18 at 07:31
  • Tell me Jigar, How can I help you? – Shree Mar 07 '18 at 09:19
  • fbskd showing popup when i try to use login method, "xyz app want to signin" similar to this https://stackoverflow.com/questions/46451983/facebook-login-shows-an-additional-confirmation-popup-on-ios-11 – Jigar Mar 07 '18 at 09:25
  • 1
    Sorry I have no idea about this. If the issue is similar to the link you have mentioned, please comment their to get help from somebody. – Shree Mar 07 '18 at 11:33