Coder Social home page Coder Social logo

magnusja / libaums Goto Github PK

View Code? Open in Web Editor NEW
1.3K 46.0 269.0 1.93 MB

Open source library to access USB Mass Storage devices on Android without rooting your device

License: Apache License 2.0

Java 22.80% CMake 0.26% C 1.60% Kotlin 75.34%
mass-storage-device android java usb usb-otg fat32 files usb-drive usb-flash mass-storage

libaums's Introduction

libaums

Javadocs Build Status codecov Codacy Badge Gitter chat

A library to access USB mass storage devices (pen drives, external HDDs, card readers) using the Android USB Host API. Currently it supports the SCSI command set and the FAT32 file system.

How to use

Install

The library can be included into your project like this:

implementation 'me.jahnen.libaums:core:0.10.0'

If you need the HTTP or the storage provider module:

implementation 'me.jahnen.libaums:httpserver:0.6.2'
implementation 'me.jahnen.libaums:storageprovider:0.6.2'

Basics

Query available mass storage devices

Java

UsbMassStorageDevice[] devices = UsbMassStorageDevice.getMassStorageDevices(this /* Context or Activity */);

for(UsbMassStorageDevice device: devices) {
    
    // before interacting with a device you need to call init()!
    device.init();
    
    // Only uses the first partition on the device
    FileSystem currentFs = device.getPartitions().get(0).getFileSystem();
    Log.d(TAG, "Capacity: " + currentFs.getCapacity());
    Log.d(TAG, "Occupied Space: " + currentFs.getOccupiedSpace());
    Log.d(TAG, "Free Space: " + currentFs.getFreeSpace());
    Log.d(TAG, "Chunk size: " + currentFs.getChunkSize());
}

Kotlin

val devices = UsbMassStorageDevice.getMassStorageDevices(this /* Context or Activity */)

for (device in devices) {

    // before interacting with a device you need to call init()!
    device.init()

    // Only uses the first partition on the device
    val currentFs = device.partitions[0].fileSystem
    Log.d(TAG, "Capacity: " + currentFs.capacity)
    Log.d(TAG, "Occupied Space: " + currentFs.occupiedSpace)
    Log.d(TAG, "Free Space: " + currentFs.freeSpace)
    Log.d(TAG, "Chunk size: " + currentFs.chunkSize)
}

Permissions

Your app needs to get permission from the user at run time to be able to communicate the device. From a UsbMassStorageDevice you can get the underlying android.usb.UsbDevice to do so.

Java

PendingIntent permissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
usbManager.requestPermission(device.getUsbDevice(), permissionIntent);

Kotlin

val permissionIntent = PendingIntent.getBroadcast(this, 0, Intent(ACTION_USB_PERMISSION), 0);
usbManager.requestPermission(device.usDevice, permissionIntent);

For more information regarding permissions please check out the Android documentation: https://developer.android.com/guide/topics/connectivity/usb/host.html#permission-d

Working with files and folders

Java
UsbFile root = currentFs.getRootDirectory();

UsbFile[] files = root.listFiles();
for(UsbFile file: files) {
    Log.d(TAG, file.getName());
    if(!file.isDirectory()) {
        Log.d(TAG, file.getLength());
    }
}

UsbFile newDir = root.createDirectory("foo");
UsbFile file = newDir.createFile("bar.txt");

// write to a file
OutputStream os = new UsbFileOutputStream(file);

os.write("hello".getBytes());
os.close();

// read from a file
InputStream is = new UsbFileInputStream(file);
byte[] buffer = new byte[currentFs.getChunkSize()];
is.read(buffer);
Kotlin
val root = currentFs.rootDirectory

val files = root.listFiles()
for (file in files) {
    Log.d(TAG, file.name)
    if (file.isDirectory) {
        Log.d(TAG, file.length)
    }
}

val newDir = root.createDirectory("foo")
val file = newDir.createFile("bar.txt")

// write to a file
val os = UsbFileOutputStream(file)

os.write("hello".toByteArray())
os.close()

// read from a file
val ins = UsbFileInputStream(file)
val buffer = ByteArray(currentFs.chunkSize)
ins.read(buffer)

Using buffered streams for more efficency

OutputStream os = UsbFileStreamFactory.createBufferedOutputStream(file, currentFs);
InputStream is = UsbFileStreamFactory.createBufferedInputStream(file, currentFs);

Cleaning up

// Don't forget to call UsbMassStorageDevice.close() when you are finished

device.close();

Troubleshooting

If you get the following error fairly often (mostly under Android 9.0 Pie):

java.io.IOException: Could not write to device, result == -1 errno 0 null

or something similar, you might want to try the libusb module. This uses, instead of the Android USB host API, the libusb library for low level communication with the USB mass storage device.

see discussions: #209 #237 #242

Note, that libusb is licensed under LGPL, which is different from the license this project is licensed under! This might come with some drawbacks or extra work for closed source applications, see here: https://xebia.com/blog/the-lgpl-on-android/

Provide access to external apps

Usually third party apps do not have access to the files on a mass storage device if the Android system does mount (this is usually supported on newer devices, back in 2014 there was no support for that) the device or this app integrates this library itself. To solve this issue there are two additional modules to provide access to other app. One uses the Storage Access Framework feature of Android (API level >= 19) and the other one spins up an HTTP server to allow downloading or streaming of videos or images for instance.

HTTP server

Javadocs

libaums currently supports two different HTTP server libraries.

  1. NanoHTTPD
  2. AsyncHttpServer

You can spin up a server pretty easy, you just have to decide for a HTTP server implementation. If you do not have special requirements, you can just go for one, it should not make much of a difference.

Java

UsbFile file = ... // can be directory or file

HttpServer server = AsyncHttpServer(8000); // port 8000
// or
HttpServer server = NanoHttpdServer(8000); // port 8000

UsbFileHttpServer fileServer = new UsbFileHttpServer(file, server);
fileServer.start();

Kotlin

val file: UsbFile
// can be directory or file

val server = AsyncHttpServer(8000) // port 8000
// or
val server = NanoHttpdServer(8000) // port 8000

val fileServer = UsbFileHttpServer(file, server)
fileServer.start()

The file you provide can either be an actual file or a directory:

  1. File: Accessible either via "/" or "/FILE_NAME"
  2. Directory: All files in this directory und sub directories are accessable via their names. Directory listing is not supported!

If you want to be able to access these files when your app is in background, you should implement a service for that. There is an example available in the httpserver module. You can use it, but should subclass it or create your own to adapt it to your needs.

Java

private UsbFileHttpServerService serverService;

ServiceConnection serviceConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        Log.d(TAG, "on service connected " + name);
        UsbFileHttpServerService.ServiceBinder binder = (UsbFileHttpServerService.ServiceBinder) service;
        serverService = binder.getService();
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        Log.d(TAG, "on service disconnected " + name);
        serverService = null;
    }
};

@Override
protected void onCreate(Bundle savedInstanceState) {
...
    serviceIntent = new Intent(this, UsbFileHttpServerService.class);
...
}

 @Override
protected void onStart() {
    super.onStart();

    startService(serviceIntent);
    bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE);
}

private void startHttpServer(final UsbFile file) {
...
    serverService.startServer(file, new AsyncHttpServer(8000));
...
}

Kotlin

private var serverService: UsbFileHttpServerService? = null

internal var serviceConnection: ServiceConnection = object : ServiceConnection() {
    override fun onServiceConnected(name: ComponentName, service: IBinder) {
        Log.d(TAG, "on service connected $name")
        val binder = service as UsbFileHttpServerService.ServiceBinder
        serverService = binder.getService()
    }

    override fun onServiceDisconnected(name: ComponentName) {
        Log.d(TAG, "on service disconnected $name")
        serverService = null
    }
}

override protected fun onCreate(savedInstanceState: Bundle) {
    serviceIntent = Intent(this, UsbFileHttpServerService::class.java)
}

override protected fun onStart() {
    super.onStart()

    startService(serviceIntent)
    bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE)
}

See the example app for additional details on that.

Storage Access Framework

Javadocs

To learn more about this visit: https://developer.android.com/guide/topics/providers/document-provider.html

To integrate this module in your app the only thing you have to do is add the definition in your AndroidManifest.xml.

<provider
    android:name="me.jahnen.libaums.storageprovider.UsbDocumentProvider"
    android:authorities="me.jahnen.libaums.storageprovider.documents"
    android:exported="true"
    android:grantUriPermissions="true"
    android:permission="android.permission.MANAGE_DOCUMENTS"
    android:enabled="@bool/isAtLeastKitKat">
    <intent-filter>
        <action android:name="android.content.action.DOCUMENTS_PROVIDER" />
    </intent-filter>
</provider>

After that apps using the Storage Access Framework will be able to access the files of the USB mass storage device.

Hints

  1. In the app/ directory you can find an example application using the library.
  2. When copying a file always set the length via UsbFile.setLength(long) first. Otherwise the ClusterChain has to be increased for every call to write. This is very inefficent.
  3. Always use FileSystem.getChunkSize() bytes as buffer size, because this alignes with the block sizes drives are using. Everything else is also most likeley a decrease in performance.
  4. A good idea is to wrap the UsbFileInputStream/UsbFileOutputStream into BufferedInputStream/BufferedOutputStream. Also see UsbFileStreamFactory.
Thesis

The library was developed by Mr. Jahnen as part of his bachelor's thesis in 2014. It's a sub-topic of the research topic "Secure Copy Protection for Mobile Apps" by Mr. Kannengießer. The full thesis document can be downloaded here.

Libaums - Library to access USB Mass Storage Devices
License: Apache 2.0 (see license.txt for details)
Author: Magnus Jahnen, [email protected] Advisor: Nils Kannengießer, nils.kannengiesser at tum.de
Supervisor: Prof. Uwe Baumgarten, baumgaru at in.tum.de

Technische Universität München (TUM)
Lehrstuhl/Fachgebiet für Betriebssysteme
www.os.in.tum.de

libaums's People

Contributors

dazmk avatar deadolus avatar depau avatar derpalus avatar haoxi911 avatar jmue avatar magnusja avatar nicolausyes avatar smart40 avatar timcrid avatar undownding avatar vlog-yamamoto avatar zdronz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

libaums's Issues

Delete directory bug

This bug can be reproduced on delete operation very often. Or any other operation that initialize ClusterChain. It fails with OutOfMemoryError exception.

Usually, it is reproducible on deleting (or listing) directory with subdirectory inside that has some files.
For example.

  • directory
    • subdirectory
      • file1
      • file2

If the directory without subdirectories is deleting in most of situations everything is ok.

What is in the backtrace.

 Process: xxx, PID: 14420
    java.lang.RuntimeException: An error occured while executing doInBackground()
            at android.os.AsyncTask$3.done(AsyncTask.java:300)
            at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
            at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
            at java.util.concurrent.FutureTask.run(FutureTask.java:242)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
            at java.lang.Thread.run(Thread.java:841)
     Caused by: java.lang.OutOfMemoryError
            at java.util.ArrayList.add(ArrayList.java:118)
            at com.github.mjdev.libaums.fs.fat32.FAT.getChain(FAT.java:121)
            at com.github.mjdev.libaums.fs.fat32.ClusterChain.<init>(ClusterChain.java:63)
            at com.github.mjdev.libaums.fs.fat32.FatDirectory.init(FatDirectory.java:154)
            at com.github.mjdev.libaums.fs.fat32.FatDirectory.listFiles(FatDirectory.java:442)

What is in the log before failing.

It is always the same. You can see that two blocks are repeating infinitely until there is no more free memory on device and then application is crashing.
The code is failing in this place in FAT.java.

result.add(currentCluster);
D/ScsiBlockDevice﹕ reading: ScsiRead10 [blockAddress=54752, transferBytes=16384, blockSize=512, transferBlocks=32, getdCbwDataTransferLength()=16384]
D/ScsiBlockDevice﹕ read time: 2
D/ScsiBlockDevice﹕ reading: ScsiRead10 [blockAddress=25050, transferBytes=1024, blockSize=512, transferBlocks=2, getdCbwDataTransferLength()=1024]
D/ScsiBlockDevice﹕ read time: 1
D/ScsiBlockDevice﹕ reading: ScsiRead10 [blockAddress=54752, transferBytes=16384, blockSize=512, transferBlocks=32, getdCbwDataTransferLength()=16384]
D/ScsiBlockDevice﹕ read time: 1
D/ScsiBlockDevice﹕ reading: ScsiRead10 [blockAddress=25050, transferBytes=1024, blockSize=512, transferBlocks=2, getdCbwDataTransferLength()=1024]
D/ScsiBlockDevice﹕ read time: 1
D/ScsiBlockDevice﹕ reading: ScsiRead10 [blockAddress=54752, transferBytes=16384, blockSize=512, transferBlocks=32, getdCbwDataTransferLength()=16384]
D/ScsiBlockDevice﹕ read time: 2
D/ScsiBlockDevice﹕ reading: ScsiRead10 [blockAddress=25050, transferBytes=1024, blockSize=512, transferBlocks=2, getdCbwDataTransferLength()=1024]
D/ScsiBlockDevice﹕ read time: 0
D/ScsiBlockDevice﹕ reading: ScsiRead10 [blockAddress=54752, transferBytes=16384, blockSize=512, transferBlocks=32, getdCbwDataTransferLength()=16384]
D/ScsiBlockDevice﹕ read time: 2
D/ScsiBlockDevice﹕ reading: ScsiRead10 [blockAddress=25050, transferBytes=1024, blockSize=512, transferBlocks=2, getdCbwDataTransferLength()=1024]
D/ScsiBlockDevice﹕ read time: 1
D/ScsiBlockDevice﹕ reading: ScsiRead10 [blockAddress=54752, transferBytes=16384, blockSize=512, transferBlocks=32, getdCbwDataTransferLength()=16384]
D/ScsiBlockDevice﹕ read time: 2
D/ScsiBlockDevice﹕ reading: ScsiRead10 [blockAddress=25050, transferBytes=1024, blockSize=512, transferBlocks=2, getdCbwDataTransferLength()=1024]
D/ScsiBlockDevice﹕ read time: 1
D/ScsiBlockDevice﹕ reading: ScsiRead10 [blockAddress=54752, transferBytes=16384, blockSize=512, transferBlocks=32, getdCbwDataTransferLength()=16384]
D/ScsiBlockDevice﹕ read time: 2
D/ScsiBlockDevice﹕ reading: ScsiRead10 [blockAddress=25050, transferBytes=1024, blockSize=512, transferBlocks=2, getdCbwDataTransferLength()=1024]
D/ScsiBlockDevice﹕ read time: 1
D/ScsiBlockDevice﹕ reading: ScsiRead10 [blockAddress=54752, transferBytes=16384, blockSize=512, transferBlocks=32, getdCbwDataTransferLength()=16384]
D/ScsiBlockDevice﹕ read time: 2
D/ScsiBlockDevice﹕ reading: ScsiRead10 [blockAddress=25050, transferBytes=1024, blockSize=512, transferBlocks=2, getdCbwDataTransferLength()=1024]
D/ScsiBlockDevice﹕ read time: 1
D/ScsiBlockDevice﹕ reading: ScsiRead10 [blockAddress=54752, transferBytes=16384, blockSize=512, transferBlocks=32, getdCbwDataTransferLength()=16384]
D/ScsiBlockDevice﹕ read time: 2
D/ScsiBlockDevice﹕ reading: ScsiRead10 [blockAddress=25050, transferBytes=1024, blockSize=512, transferBlocks=2, getdCbwDataTransferLength()=1024]
D/ScsiBlockDevice﹕ read time: 1
D/ScsiBlockDevice﹕ reading: ScsiRead10 [blockAddress=54752, transferBytes=16384, blockSize=512, transferBlocks=32, getdCbwDataTransferLength()=16384]
D/ScsiBlockDevice﹕ read time: 2
D/ScsiBlockDevice﹕ reading: ScsiRead10 [blockAddress=25050, transferBytes=1024, blockSize=512, transferBlocks=2, getdCbwDataTransferLength()=1024]
D/ScsiBlockDevice﹕ read time: 1
D/ScsiBlockDevice﹕ reading: ScsiRead10 [blockAddress=54752, transferBytes=16384, blockSize=512, transferBlocks=32, getdCbwDataTransferLength()=16384]
D/ScsiBlockDevice﹕ read time: 2
D/ScsiBlockDevice﹕ reading: ScsiRead10 [blockAddress=25050, transferBytes=1024, blockSize=512, transferBlocks=2, getdCbwDataTransferLength()=1024]
D/ScsiBlockDevice﹕ read time: 1
D/ScsiBlockDevice﹕ reading: ScsiRead10 [blockAddress=54752, transferBytes=16384, blockSize=512, transferBlocks=32, getdCbwDataTransferLength()=16384]
D/ScsiBlockDevice﹕ read time: 3
D/ScsiBlockDevice﹕ reading: ScsiRead10 [blockAddress=25050, transferBytes=1024, blockSize=512, transferBlocks=2, getdCbwDataTransferLength()=1024]
D/ScsiBlockDevice﹕ read time: 1
D/dalvikvm﹕ GC_FOR_ALLOC freed 512K, 12% free 17413K/19760K, paused 9ms, total 9ms
D/ScsiBlockDevice﹕ reading: ScsiRead10 [blockAddress=54752, transferBytes=16384, blockSize=512, transferBlocks=32, getdCbwDataTransferLength()=16384]
D/ScsiBlockDevice﹕ read time: 11
D/ScsiBlockDevice﹕ reading: ScsiRead10 [blockAddress=25050, transferBytes=1024, blockSize=512, transferBlocks=2, getdCbwDataTransferLength()=1024]
D/ScsiBlockDevice﹕ read time: 1
D/ScsiBlockDevice﹕ reading: ScsiRead10 [blockAddress=54752, transferBytes=16384, blockSize=512, transferBlocks=32, getdCbwDataTransferLength()=16384]
D/ScsiBlockDevice﹕ read time: 2
D/ScsiBlockDevice﹕ reading: ScsiRead10 [blockAddress=25050, transferBytes=1024, blockSize=512, transferBlocks=2, getdCbwDataTransferLength()=1024]
D/ScsiBlockDevice﹕ read time: 1
D/ScsiBlockDevice﹕ reading: ScsiRead10 [blockAddress=54752, transferBytes=16384, blockSize=512, transferBlocks=32, getdCbwDataTransferLength()=16384]
D/ScsiBlockDevice﹕ read time: 1
D/ScsiBlockDevice﹕ reading: ScsiRead10 [blockAddress=25050, transferBytes=1024, blockSize=512, transferBlocks=2, getdCbwDataTransferLength()=1024]
D/ScsiBlockDevice﹕ read time: 1
D/ScsiBlockDevice﹕ reading: ScsiRead10 [blockAddress=54752, transferBytes=16384, blockSize=512, transferBlocks=32, getdCbwDataTransferLength()=16384]
D/ScsiBlockDevice﹕ read time: 2
D/ScsiBlockDevice﹕ reading: ScsiRead10 [blockAddress=25050, transferBytes=1024, blockSize=512, transferBlocks=2, getdCbwDataTransferLength()=1024]
D/ScsiBlockDevice﹕ read time: 1

File dates seem incorrect.

  1. lastModified is older than createdAt,
  2. The returned values are different in between different calls (values from debug).
renamedFile.lastModified() = 1467586800661
renamedFile.lastModified() = 1467586800487
renamedFile.createdAt()    = 1467632242549
renamedFile.createdAt()    = 1467632242909

Conflicting Provider

Conflicting provider error when installing app which includes libaums-storageprovider over gradle compile and example app is installed.

Video file corrupting when writing in real time...

Hello,
In my project I'm writing real time encoded mp4 video file to USB drive. At the end of recording mp4 file should have some header information. For that ffmpeg seeks for some positions in file and writes some bytes. Some of them are 4 (length of bytes) some of them 40, 64, 233 etc. However in some cases file is being corrupted. I tried to write with same logic to android's sdcard and it is going everytime with success but with USB sometimes fails. Is it related to cluster size or something else? Could you please explain it. I don't know how FAT's behaviour when writing file. Also have a look at http://stackoverflow.com/questions/9108548/android-usb-host-bulktransfer-is-losing-data . Maybe the real cause is android's native bulkTransfer API does not work properly?

Occasional crash while reading USB file content

App crashes occasionally with the following stacktrace. Environment: Samsung S7 and Moto X Play phones running Android Marshmallow 6.0.1. USB is Sandisk dual drive.

04­19 16:31:34.189 29157 29157 D UsbDeviceConnectionJNI: close
04­19 16:31:34.189 3445 3445 D EdgeLight: Turning off
04­19 16:31:34.189 29157 30411 E NanoHTTPD: Could not send response to the client
04­19 16:31:34.189 29157 30411 E NanoHTTPD: java.io.IOException: reading failed!
04­19 16:31:34.189 29157 30411 E NanoHTTPD: at com.github.mjdev.libaums.driver.scsi.ScsiBlockDevice.transferCommand(ScsiBlockDevice.java:149)
04­19 16:31:34.189 29157 30411 E NanoHTTPD: at com.github.mjdev.libaums.driver.scsi.ScsiBlockDevice.read(ScsiBlockDevice.java:215)
04­19 16:31:34.189 29157 30411 E NanoHTTPD: at com.github.mjdev.libaums.partition.Partition.read(Partition.java:124)
04­19 16:31:34.189 29157 30411 E NanoHTTPD: at com.github.mjdev.libaums.fs.fat32.ClusterChain.read(ClusterChain.java:94)
04­19 16:31:34.189 29157 30411 E NanoHTTPD: at com.github.mjdev.libaums.fs.fat32.FatFile.read(FatFile.java:159)
04­19 16:31:34.189 29157 30411 E NanoHTTPD: at com.github.mjdev.libaums.fs.UsbFileInputStream.read(UsbFileInputStream.java:104)
04­19 16:31:34.189 29157 30411 E NanoHTTPD: at fi.iki.elonen.NanoHTTPD$Response.sendBody(NanoHTTPD.java:1476)
04­19 16:31:34.189 29157 30411 E NanoHTTPD: at fi.iki.elonen.NanoHTTPD$Response.sendBodyWithCorrectEncoding(NanoHTTPD.java:1453)
04­19 16:31:34.189 29157 30411 E NanoHTTPD: at fi.iki.elonen.NanoHTTPD$Response.sendBodyWithCorrectTransferAndEncoding(NanoHTTPD.java:1443)
04­19 16:31:34.189 29157 30411 E NanoHTTPD: at fi.iki.elonen.NanoHTTPD$Response.send(NanoHTTPD.java:1429)
04­19 16:31:34.189 29157 30411 E NanoHTTPD: at fi.iki.elonen.NanoHTTPD$HTTPSession.execute(NanoHTTPD.java:852)
04­19 16:31:34.189 29157 30411 E NanoHTTPD: at fi.iki.elonen.NanoHTTPD$ClientHandler.run(NanoHTTPD.java:189)
04­19 16:31:34.189 29157 30411 E NanoHTTPD: at java.lang.Thread.run(Thread.java:818)
04­19 16:31:34.189 29157 30430 E UsbDeviceConnectionJNI: device is closed in native_control_request
04­19 16:31:34.189 29157 30430 E ScsiBlockDevice: Writing all bytes on command ScsiRead10 [blockAddress=12048, transferBytes=1024, blockSize=512, transferBlocks=2, getdCbwDataTransferLength()=1024] failed!
04­19 16:31:34.189 29157 30430 E UsbDeviceConnectionJNI: device is closed in native_control_request
04­19 16:31:34.189 29157 30430 E NanoHTTPD: Could not send response to the client
04­19 16:31:34.189 29157 30430 E NanoHTTPD: java.io.IOException: reading failed!
04­19 16:31:34.189 29157 30430 E NanoHTTPD: at com.github.mjdev.libaums.driver.scsi.ScsiBlockDevice.transferCommand(ScsiBlockDevice.java:149)
04­19 16:31:34.189 29157 30430 E NanoHTTPD: at com.github.mjdev.libaums.driver.scsi.ScsiBlockDevice.read(ScsiBlockDevice.java:215)
04­19 16:31:34.189 29157 30430 E NanoHTTPD: at com.github.mjdev.libaums.partition.Partition.read(Partition.java:133)
04­19 16:31:34.189 29157 30430 E NanoHTTPD: at com.github.mjdev.libaums.fs.fat32.FAT.getChain(FAT.java:134)
04­19 16:31:34.189 29157 30430 E NanoHTTPD: at com.github.mjdev.libaums.fs.fat32.ClusterChain.(ClusterChain.java:63)
04­19 16:31:34.189 29157 30430 E NanoHTTPD: at com.github.mjdev.libaums.fs.fat32.FatFile.initChain(FatFile.java:89)
04­19 16:31:34.189 29157 30430 E NanoHTTPD: at com.github.mjdev.libaums.fs.fat32.FatFile.read(FatFile.java:157)
04­19 16:31:34.189 29157 30430 E NanoHTTPD: at com.github.mjdev.libaums.fs.UsbFileInputStream.read(UsbFileInputStream.java:104)
04­19 16:31:34.189 29157 30430 E NanoHTTPD: at fi.iki.elonen.NanoHTTPD$Response.sendBody(NanoHTTPD.java:1476)
04­19 16:31:34.189 29157 30430 E NanoHTTPD: at fi.iki.elonen.NanoHTTPD$Response.sendBodyWithCorrectEncoding(NanoHTTPD.java:1453)
04­19 16:31:34.189 29157 30430 E NanoHTTPD: at fi.iki.elonen.NanoHTTPD$Response.sendBodyWithCorrectTransferAndEncoding(NanoHTTPD.java:1443)
04­19 16:31:34.189 29157 30430 E NanoHTTPD: at fi.iki.elonen.NanoHTTPD$Response.send(NanoHTTPD.java:1429)
04­19 16:31:34.189 29157 30430 E NanoHTTPD: at fi.iki.elonen.NanoHTTPD$HTTPSession.execute(NanoHTTPD.java:852)
04­19 16:31:34.189 29157 30430 E NanoHTTPD: at fi.iki.elonen.NanoHTTPD$ClientHandler.run(NanoHTTPD.java:189)
04­19 16:31:34.189 29157 30430 E NanoHTTPD: at java.lang.Thread.run(Thread.java:818)

Issue to Access USB Mass Storage over Type C

Hello,

I am developing an application to access USB mass storage connected to Android phone. I am using libaums library. When I run application in devices with micro USB interface, I am able to access and explore the drive. When I run application in device with USB Type C connector (Nexus 5X and Nexus 6P), I face the issue. I am seeing the follwing exception in the logcat.

01-06 12:03:29.181 30348 30348 E TYPEC : error setting up device
01-06 12:03:29.181 30348 30348 E TYPEC : java.io.IOException: reading failed!
01-06 12:03:29.181 30348 30348 E TYPEC : at com.test.libaums.driver.scsi.ScsiBlockDevice.transferCommand(ScsiBlockDevice.java:144)
01-06 12:03:29.181 30348 30348 E TYPEC : at com.test.libaums.driver.scsi.ScsiBlockDevice.init(ScsiBlockDevice.java:77)
01-06 12:03:29.181 30348 30348 E TYPEC : at com.test.libaums.UsbMassStorageDevice.setupDevice(UsbMassStorageDevice.java:312)
01-06 12:03:29.181 30348 30348 E TYPEC : at com.test.libaums.UsbMassStorageDevice.init(UsbMassStorageDevice.java:268)
01-06 12:03:29.181 30348 30348 E TYPEC : at com.test.kt.TYPEC.setupDevice(TYPEC.java:409)
01-06 12:03:29.181 30348 30348 E TYPEC : at com.test.kt.TYPEC.access$600(TYPEC.java:92)
01-06 12:03:29.181 30348 30348 E TYPEC : at com.test.kt.TYPEC$7.onReceive(TYPEC.java:315)
01-06 12:03:29.181 30348 30348 E TYPEC : at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:881)
01-06 12:03:29.181 30348 30348 E TYPEC : at android.os.Handler.handleCallback(Handler.java:739)
01-06 12:03:29.181 30348 30348 E TYPEC : at android.os.Handler.dispatchMessage(Handler.java:95)
01-06 12:03:29.181 30348 30348 E TYPEC : at android.os.Looper.loop(Looper.java:148)
01-06 12:03:29.181 30348 30348 E TYPEC : at android.app.ActivityThread.main(ActivityThread.java:5417)
01-06 12:03:29.181 30348 30348 E TYPEC : at java.lang.reflect.Method.invoke(Native Method)
01-06 12:03:29.181 30348 30348 E TYPEC : at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
01-06 12:03:29.181 30348 30348 E TYPEC : at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

It looks like device doesn't respond to SCSI inquiry.

Any help to resolve the issue is highly appreciated.

Thanks,
Anu

How to read hidden area of USB?

Hi,

I use libaums to access private partition in usb mass storage. Then I want to access hidden partition in usb mass storage. I have the vendor specific opcode to read and write hidden entry. Firstly, how to read the capacity of hidden area and the block size, also last block address? Is there something to do with private static final int FLAG_HIDDEN = 0x02; and
boolean isHidden() { return isFlagSet(FLAG_HIDDEN); } ? Or do I need to create new class like ScsiReadHidden like ScsiRead10 class?

Unfortunately, Usbfileman has stopped

05-17 12:08:18.481 20116-20116/com.github.mjdev.usbfileman I/ScsiBlockDevice: Block size: 512
05-17 12:08:18.481 20116-20116/com.github.mjdev.usbfileman I/ScsiBlockDevice: Last block address: 15556607
05-17 12:08:18.496 20116-20116/com.github.mjdev.usbfileman W/Partition: unsupported partition type: 110
05-17 12:08:18.496 20116-20116/com.github.mjdev.usbfileman W/Partition: unsupported partition type: 116
05-17 12:08:18.496 20116-20116/com.github.mjdev.usbfileman D/AndroidRuntime: Shutting down VM
05-17 12:08:18.501 20116-20116/com.github.mjdev.usbfileman E/AndroidRuntime: FATAL EXCEPTION: main
                                                                             Process: com.github.mjdev.usbfileman, PID: 20116
                                                                             java.lang.RuntimeException: Error receiving broadcast Intent { act=com.github.mjdev.libaums.USB_PERMISSION flg=0x10 (has extras) } in com.github.mjdev.libaums.usbfileman.MainActivity$1@28a6c7ab
                                                                                 at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:933)
                                                                                 at android.os.Handler.handleCallback(Handler.java:739)
                                                                                 at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                                 at android.os.Looper.loop(Looper.java:145)
                                                                                 at android.app.ActivityThread.main(ActivityThread.java:5942)
                                                                                 at java.lang.reflect.Method.invoke(Native Method)
                                                                                 at java.lang.reflect.Method.invoke(Method.java:372)
                                                                                 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1400)
                                                                                 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1195)
                                                                              Caused by: java.lang.IndexOutOfBoundsException: Invalid index 1, size is 0
                                                                                 at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
                                                                                 at java.util.ArrayList.get(ArrayList.java:308)
                                                                                 at com.github.mjdev.libaums.usbfileman.MainActivity.setupDevice(MainActivity.java:424)
                                                                                 at com.github.mjdev.libaums.usbfileman.MainActivity.access$000(MainActivity.java:79)
                                                                                 at com.github.mjdev.libaums.usbfileman.MainActivity$1.onReceive(MainActivity.java:98)
                                                                                 at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:923)
                                                                                 at android.os.Handler.handleCallback(Handler.java:739) 
                                                                                 at android.os.Handler.dispatchMessage(Handler.java:95) 
                                                                                 at android.os.Looper.loop(Looper.java:145) 
                                                                                 at android.app.ActivityThread.main(ActivityThread.java:5942) 
                                                                                 at java.lang.reflect.Method.invoke(Native Method) 
                                                                                 at java.lang.reflect.Method.invoke(Method.java:372) 
                                                                                 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1400) 
                                                                                 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1195) 
05-17 12:08:18.551 20116-20116/com.github.mjdev.usbfileman I/Process: Sending signal. PID: 20116 SIG: 9

Above is my logcat. I think the error is caused by me changing from API level 23 to level 22.

Uri to file path or usbFile to File

Can't get path for usbFile
I try to extract thumbnail for video using
InputStream is = new UsbFileInputStream(usbFile); not posible.
Further problem is to play that video clip from USB in VideoView without copying.

Formatting an uninitialized USB drive

I was looking for a way to format an uninitialized USB drive, but couldn't directly find it. Is this already implemented? If not, is it something that is desired to have in this library?

Subtle bug in SCSI command length

First of all - awesome project!

I wanted to point out something which seems to be an accident.
In ScsiRead10 and all other command classes, the LENGTH field is declared in hex:
private static final byte LENGTH = 0x10;
This command should be length 10 as per spec - but in this code will actually be 16 (decimal)!

Luckily, these commands still seem to work as is - I noticed this when creating other SCSI commands by copy pasting and blindly putting other lengths in hex.

Folder names are displayed in all caps.

If all the characters in a folder name are lower case letters, then the libaums library is displaying them in upper case characters.

untitled

screenshot_2016-11-29-20-18-29

on Running with Storage Access Framework

screenshot_2016-11-29-20-18-45

Problem is consistent and easily reproducible.

Can not write random on file...

Hi,
I'm trying to write file by random accessing on it. There is RandomAccessFile class on java 7. I tried to write to usb drive using your UsbFile class, but somehow there is only zero bytes. With copying all things are OK. How can I do the same thing on this lib? Because, in this lib there is only UsbFile class which I can use?
Best regards, Shukhrat

ZipInputStream from UsbFileInputStream fails with BufferOverflowException

I'm trying to decompress a file in the drive. For such I am doing something similar to this:

UsbFile zippedFile = getFile(path);
ZipInputStream zipInputStream = new ZipInputStream(new UsbFileInputStream(zippedFile));
ZipEntry entry;
while ((entry = zipInputStream.getNextEntry()) != null) {
   …
}
…

However, this code fails when getNextEntry() is called. I've given it a look at it seems to be related to the UsbFileInputStream implementation, although I am not 100% sure what is causing such behavior.

Create folder operation successful but after unplug/plug device folder is not there

I had noticed this behaviour at least since 3.0 but after pulling the latest code (5dfe700) it is still noticeable.

Steps to reproduce (even with the given test libaums app) are:

  1. Under any folder in root create a subfolder.
  2. The operation will go ok and the folder will be there.
  3. Unplug and plug the device.
  4. Navigate into that folder. The created folder is not there.

Writing on USB drive failing sometimes...

I'm using this lib for writing and reading video files. Sometimes when I write by part I get exceptions shown in below stack:

02-10 15:34:06.980    2802-6916/? W/System.err﹕ java.io.IOException: reading failed!
02-10 15:34:06.980    2802-6916/? W/System.err﹕ at com.github.mjdev.libaums.driver.scsi.ScsiBlockDevice.transferCommand(ScsiBlockDevice.java:149)
02-10 15:34:06.980    2802-6916/? W/System.err﹕ at com.github.mjdev.libaums.driver.scsi.ScsiBlockDevice.read(ScsiBlockDevice.java:215)
02-10 15:34:06.980    2802-6916/? W/System.err﹕ at com.github.mjdev.libaums.partition.Partition.read(Partition.java:133)
02-10 15:34:06.980    2802-6916/? W/System.err﹕ at com.github.mjdev.libaums.fs.fat32.FAT.alloc(FAT.java:202)
02-10 15:34:06.980    2802-6916/? W/System.err﹕ at com.github.mjdev.libaums.fs.fat32.ClusterChain.setClusters(ClusterChain.java:199)
02-10 15:34:06.980    2802-6916/? W/System.err﹕ at com.github.mjdev.libaums.fs.fat32.ClusterChain.setLength(ClusterChain.java:230)
02-10 15:34:06.980    2802-6916/? W/System.err﹕ at com.github.mjdev.libaums.fs.fat32.FatFile.setLength(FatFile.java:151)
02-10 15:34:06.980    2802-6916/? W/System.err﹕ at com.github.mjdev.libaums.fs.fat32.FatFile.write(FatFile.java:167)

I don't have any idea why this happens, because sometimes it works OK.

The sample file manager doesn't work with Android M

I downloaded the code yesterday and tried to run the file manager app with Android M as the target. It crashed. Haven't analyzed it yet but it could be something to do with the new runtime permissions. Here's the log:

03-24 01:09:41.037 32060-32060/? W/MemoryReductionHack: Couldn't update the Loader
03-24 01:09:41.060 32060-32080/? I/GMPM: App measurement is starting up
03-24 01:09:41.082 32060-32080/? E/GMPM: getGoogleAppId failed with status: 10
03-24 01:09:41.083 32060-32080/? E/GMPM: Uploading is not possible. App measurement disabled
03-24 01:09:41.139 32060-32060/? W/StaticBindingVerifier: Verify
03-24 01:09:41.167 32060-32088/? W/LightSharedPreferencesImpl: Failed to load preference file from Disk!
java.io.FileNotFoundException: /data/user/0/com.facebook.katana/app_light_prefs/com.facebook.katana/analytics_flexible_sampling_policy: open failed: ENOENT (No such file or directory)
at libcore.io.IoBridge.open(IoBridge.java:452)
at java.io.FileInputStream.(FileInputStream.java:76)
at com.facebook.crudolib.prefs.LightSharedPreferencesStorage.a(ufi_enabled/:56)
at com.facebook.crudolib.prefs.LightSharedPreferencesImpl$1.run(ui thread:61)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:423)
at com.facebook.common.executors.WrappingExecutorService$1.run(verified_server_address:77)
at com.facebook.common.executors.DefaultConstrainedListeningExecutorService$Worker.run(vibrator:327)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at com.facebook.common.executors.NamedThreadFactory$1.run(video-player-readable-cache:42)
at java.lang.Thread.run(Thread.java:818)
Caused by: android.system.ErrnoException: open failed: ENOENT (No such file or directory)
at libcore.io.Posix.open(Native Method)
at libcore.io.BlockGuardOs.open(BlockGuardOs.java:186)
at libcore.io.IoBridge.open(IoBridge.java:438)
at java.io.FileInputStream.(FileInputStream.java:76) 
at com.facebook.crudolib.prefs.LightSharedPreferencesStorage.a(ufi_enabled/:56) 
at com.facebook.crudolib.prefs.LightSharedPreferencesImpl$1.run(ui thread:61) 
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:423) 
at com.facebook.common.executors.WrappingExecutorService$1.run(verified_server_address:77) 
at com.facebook.common.executors.DefaultConstrainedListeningExecutorService$Worker.run(vibrator:327) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) 
at com.facebook.common.executors.NamedThreadFactory$1.run(video-player-readable-cache:42) 
at java.lang.Thread.run(Thread.java:818) 

createDirectory function create that can not be deleted file.

createDirectory function creates a cannot delete file under the directory it created.
There is also a problem in create directory's volume label from log.

Operation is as follows:

  1. createDirectory "a" in Android
  2. USB device detach from Android
  3. USB device attach to PC (My PC is mac)
  4. Delete Directory "a" in PC
  5. USB device detach from PC use eject function.
  6. USB device attach to Android
  7. createDirectory "a" create that can not be deleted file.

log is following in libaums-develop application.

03-17 10:39:25.272  18396-18396/com.github.mjdev.usbfileman I/art﹕ Late-enabling -Xcheck:jni
03-17 10:39:25.392  18396-18396/com.github.mjdev.usbfileman W/MainActivity﹕ no device found!
03-17 10:39:25.401  18396-18416/com.github.mjdev.usbfileman D/OpenGLRenderer﹕ Use EGL_SWAP_BEHAVIOR_PRESERVED: true
03-17 10:39:25.406  18396-18396/com.github.mjdev.usbfileman D/Atlas﹕ Validating map...
03-17 10:39:25.441  18396-18416/com.github.mjdev.usbfileman I/Adreno-EGL﹕ <qeglDrvAPI_eglInitialize:379>: QUALCOMM Build: 01/14/15, ab0075f, Id3510ff6dc
03-17 10:39:25.443  18396-18416/com.github.mjdev.usbfileman I/OpenGLRenderer﹕ Initialized EGL, version 1.4
03-17 10:39:25.476  18396-18416/com.github.mjdev.usbfileman D/OpenGLRenderer﹕ Enabling debug mode 0
03-17 10:39:25.505  18396-18396/com.github.mjdev.usbfileman D/MainActivity﹕ on service connected ComponentInfo{com.github.mjdev.usbfileman/com.github.mjdev.libaums.server.http.UsbFileHttpServerService}
03-17 10:39:32.024  18396-18396/com.github.mjdev.usbfileman D/MainActivity﹕ USB device attached
03-17 10:39:32.063  18396-18396/com.github.mjdev.usbfileman I/UsbMassStorageDevice﹕ found usb device: UsbDevice[mName=/dev/bus/usb/001/002,mVendorId=1921,mProductId=53232,mClass=0,mSubclass=0,mProtocol=0,mManufacturerName=SanDisk,mProductName=iXpand Flash Drive,mSerialNumber=AB0123456789,mConfigurations=[
    UsbConfiguration[mId=1,mName=null,mAttributes=128,mMaxPower=250,mInterfaces=[
    UsbInterface[mId=0,mAlternateSetting=0,mName=null,mClass=8,mSubclass=6,mProtocol=80,mEndpoints=[
    UsbEndpoint[mAddress=130,mAttributes=2,mMaxPacketSize=512,mInterval=0]
    UsbEndpoint[mAddress=3,mAttributes=2,mMaxPacketSize=512,mInterval=0]]]]
03-17 10:39:32.063  18396-18396/com.github.mjdev.usbfileman I/UsbMassStorageDevice﹕ found usb interface: UsbInterface[mId=0,mAlternateSetting=0,mName=null,mClass=8,mSubclass=6,mProtocol=80,mEndpoints=[
    UsbEndpoint[mAddress=130,mAttributes=2,mMaxPacketSize=512,mInterval=0]
    UsbEndpoint[mAddress=3,mAttributes=2,mMaxPacketSize=512,mInterval=0]]
03-17 10:39:32.063  18396-18396/com.github.mjdev.usbfileman I/UsbMassStorageDevice﹕ found usb endpoint: UsbEndpoint[mAddress=130,mAttributes=2,mMaxPacketSize=512,mInterval=0]
03-17 10:39:32.063  18396-18396/com.github.mjdev.usbfileman I/UsbMassStorageDevice﹕ found usb endpoint: UsbEndpoint[mAddress=3,mAttributes=2,mMaxPacketSize=512,mInterval=0]
03-17 10:39:33.919  18396-18396/com.github.mjdev.usbfileman D/UsbMassStorageDevice﹕ setup device
03-17 10:39:33.928  18396-18396/com.github.mjdev.usbfileman D/ScsiBlockDevice﹕ inquiry response: ScsiInquiryResponse [peripheralQualifier=0, peripheralDeviceType=0, removableMedia=false, spcVersion=0, responseDataFormat=1]
03-17 10:39:33.934  18396-18396/com.github.mjdev.usbfileman I/ScsiBlockDevice﹕ Block size: 512
03-17 10:39:33.934  18396-18396/com.github.mjdev.usbfileman I/ScsiBlockDevice﹕ Last block address: 62333951
03-17 10:39:33.943  18396-18396/com.github.mjdev.usbfileman I/FAT﹕ fat is mirrored, fat count: 2
03-17 10:39:33.961  18396-18396/com.github.mjdev.usbfileman D/FatDirectory﹕ volume label: USBSTORAGE
03-17 10:39:33.961  18396-18396/com.github.mjdev.usbfileman D/MainActivity﹕ Capacity: 31910789120
03-17 10:39:33.961  18396-18396/com.github.mjdev.usbfileman D/MainActivity﹕ Occupied Space: 58884096
03-17 10:39:33.961  18396-18396/com.github.mjdev.usbfileman D/MainActivity﹕ Free Space: 31851905024
03-17 10:39:37.218  18396-18396/com.github.mjdev.usbfileman W/art﹕ Before Android 4.1, method int android.support.v7.widget.ListViewCompat.lookForSelectablePosition(int, boolean) would have incorrectly overridden the package-private method in android.widget.ListView
03-17 10:39:47.829  18396-18396/com.github.mjdev.usbfileman D/FsInfoStructure﹕ writing to device
03-17 10:39:47.833  18396-18396/com.github.mjdev.usbfileman I/FAT﹕ allocating clusters finished
03-17 10:39:47.833  18396-18396/com.github.mjdev.usbfileman D/FatDirectory﹕ adding entry: [FatLfnDirectoryEntry getName()=a] with short name: A
03-17 10:39:47.834  18396-18396/com.github.mjdev.usbfileman W/ScsiBlockDevice﹕ we have to round up size to next block sector
03-17 10:39:47.846  18396-18396/com.github.mjdev.usbfileman W/ScsiBlockDevice﹕ we have to round up size to next block sector
03-17 10:39:58.429  18396-18396/com.github.mjdev.usbfileman D/MainActivity﹕ USB device detached
03-17 10:39:58.429  18396-18396/com.github.mjdev.usbfileman D/UsbMassStorageDevice﹕ close device
03-17 10:39:58.429  18396-18396/com.github.mjdev.usbfileman E/UsbMassStorageDevice﹕ could not release interface!
03-17 10:39:58.429  18396-18396/com.github.mjdev.usbfileman D/UsbDeviceConnectionJNI﹕ close
03-17 10:39:58.439  18396-18396/com.github.mjdev.usbfileman W/MainActivity﹕ no device found!
03-17 10:40:38.407  18396-18396/com.github.mjdev.usbfileman D/MainActivity﹕ USB device attached
03-17 10:40:38.438  18396-18396/com.github.mjdev.usbfileman I/UsbMassStorageDevice﹕ found usb device: UsbDevice[mName=/dev/bus/usb/001/002,mVendorId=1921,mProductId=53232,mClass=0,mSubclass=0,mProtocol=0,mManufacturerName=SanDisk,mProductName=iXpand Flash Drive,mSerialNumber=AB0123456789,mConfigurations=[
    UsbConfiguration[mId=1,mName=null,mAttributes=128,mMaxPower=250,mInterfaces=[
    UsbInterface[mId=0,mAlternateSetting=0,mName=null,mClass=8,mSubclass=6,mProtocol=80,mEndpoints=[
    UsbEndpoint[mAddress=130,mAttributes=2,mMaxPacketSize=512,mInterval=0]
    UsbEndpoint[mAddress=3,mAttributes=2,mMaxPacketSize=512,mInterval=0]]]]
03-17 10:40:38.438  18396-18396/com.github.mjdev.usbfileman I/UsbMassStorageDevice﹕ found usb interface: UsbInterface[mId=0,mAlternateSetting=0,mName=null,mClass=8,mSubclass=6,mProtocol=80,mEndpoints=[
    UsbEndpoint[mAddress=130,mAttributes=2,mMaxPacketSize=512,mInterval=0]
    UsbEndpoint[mAddress=3,mAttributes=2,mMaxPacketSize=512,mInterval=0]]
03-17 10:40:38.438  18396-18396/com.github.mjdev.usbfileman I/UsbMassStorageDevice﹕ found usb endpoint: UsbEndpoint[mAddress=130,mAttributes=2,mMaxPacketSize=512,mInterval=0]
03-17 10:40:38.438  18396-18396/com.github.mjdev.usbfileman I/UsbMassStorageDevice﹕ found usb endpoint: UsbEndpoint[mAddress=3,mAttributes=2,mMaxPacketSize=512,mInterval=0]
03-17 10:40:40.030  18396-18396/com.github.mjdev.usbfileman D/UsbMassStorageDevice﹕ setup device
03-17 10:40:40.035  18396-18396/com.github.mjdev.usbfileman D/ScsiBlockDevice﹕ inquiry response: ScsiInquiryResponse [peripheralQualifier=0, peripheralDeviceType=0, removableMedia=false, spcVersion=0, responseDataFormat=1]
03-17 10:40:40.037  18396-18396/com.github.mjdev.usbfileman I/ScsiBlockDevice﹕ Block size: 512
03-17 10:40:40.037  18396-18396/com.github.mjdev.usbfileman I/ScsiBlockDevice﹕ Last block address: 62333951
03-17 10:40:40.045  18396-18396/com.github.mjdev.usbfileman I/FAT﹕ fat is mirrored, fat count: 2
03-17 10:40:40.059  18396-18396/com.github.mjdev.usbfileman D/FatDirectory﹕ volume label: USBSTORAGE
03-17 10:40:40.060  18396-18396/com.github.mjdev.usbfileman D/MainActivity﹕ Capacity: 31910789120
03-17 10:40:40.060  18396-18396/com.github.mjdev.usbfileman D/MainActivity﹕ Occupied Space: 58949632
03-17 10:40:40.060  18396-18396/com.github.mjdev.usbfileman D/MainActivity﹕ Free Space: 31851839488
03-17 10:40:45.406  18396-18416/com.github.mjdev.usbfileman D/OpenGLRenderer﹕ endAllStagingAnimators on 0xb4bff200 (RippleDrawable) with handle 0xb4b73e40
03-17 10:40:51.984  18396-18396/com.github.mjdev.usbfileman D/FsInfoStructure﹕ writing to device
03-17 10:40:51.988  18396-18396/com.github.mjdev.usbfileman I/FAT﹕ allocating clusters finished
03-17 10:40:51.988  18396-18396/com.github.mjdev.usbfileman D/FatDirectory﹕ adding entry: [FatLfnDirectoryEntry getName()=a] with short name: A
03-17 10:40:52.001  18396-18396/com.github.mjdev.usbfileman W/FatDirectory﹕ volume label in non root dir!
03-17 10:40:52.001  18396-18396/com.github.mjdev.usbfileman D/FatDirectory﹕ volume label: �ヒ
03-17 10:40:52.001  18396-18396/com.github.mjdev.usbfileman W/ScsiBlockDevice﹕ we have to round up size to next block sector

PC's ls log

vLog-no-MacBook-Pro-2:~ yamamoto$ ls /Volumes/USBSTORAGE/a/
0bâ?␀␀␀ÿ.ÿ?␀         ”Xœ‘Z¬oj.`Äà

Device
Nexus 5 Ver.5.1.1
Nexus 6 Ver.6.0.1

UsbDrive
iXpand Flash Drive 32GB
SanDisk Ultra USB 3.0 16GB.

Partition size related problems on some devices .....

Hello,
I have problems with some usb drives. During setting up usb device, drive partitions are being returned like zero (0). I understand if it is not right file system. However, I test with fat32 file system formatted usb drives. I call init() method before getting partitions as provided in example code:
**
* Sets the device up and shows the contents of the root directory.
*/
private void setupDevice() {
try {
device.init();
if (device.getPartitions().size() != 0) {
//do your stuff
}

What is the cause of problem where partition size is 0 ?

libaums sample code error

hi i have problem with this library
I write a sample app to read usb mass storage when i attach usb sotrage and run
FileSystem currentFs = device.getPartitions().get(0).getFileSystem();
device.getPartitions() is empty I debug that my partitionType is -1 why?(my file system is FAT32)
then I try to download and run your code but i faced this error:
Installation failed with message INSTALL_FAILED_CONFLICTING_PROVIDER.
It is possible that this issue is resolved by uninstalling an existing version of the apk if it is present, and then re-installing.
can help me

How to write files to usb from internal storage

Hi how can we write files from internal storage to usb.i have copy files from usb to internal storage but dont find how to copy files from internal to the usb storage. can you please help

USBFile .close/flush updates the memory of its parent Dir , ignoring the changes happened to that Dir post file creation

I faced this problem when I had to download a list of files on the USB.

Initially i created 10 empty UsbFiles on the USB drive and inserted them into a hashmap with key as the downloadUrl.
(lets say the files created are test1.txt, test2.txt .... test10.txt)

and now to write the downloaded data into the files, i iterate the map and get the UsbFile for the corresponding downloadUrl. consider the order of files that is being written is as shown below,

test8.txt,
test10.txt
...

test1.txt.

After writing all the files, if i goto a file explorer and check the Usb storage, all i could see is only test1.txt. (the file which was written at the last, and which was created at first)

I guess the reason for this problem, when the "parent" of the UsbFile is being updated, via. usbfile.flush(), the memory associated with the corresponding instance of the "parent" is considered as the latest content of the "parent", ignoring all the other changes happened after usbfile creation. (when test1 was created, its parent had only one child and which was retained even when the file was written at last)

On debugging, i was able to see this
map.get(downloadUrl_of_test1.txt).getParent().listFiles() will have only 1 child.
map.get(downloadUrl_of_test2.txt).getParent().listFiles() will have 2 children

map.get(downloadUrl_of_test8.txt).getParent().listFiles() will have 8 children

Since the test1.txt is written after all other files, and its parent directory contains only 1 child, at the end of downloading files, we are able to see only test1.txt (as the write is being done on Parent level, based on what i understood fromt he comments)

            // we only have to update the parent because we are always writing
    // everything
    // immediately to the device
    // the parent directory is responsible for updating the
    // FatDirectoryEntry which
    // contains things like the file size and the date time fields

Instead of map, if i create a file, download and write the content to it and follow the same for the other files, i'm able to see all the files with appropriate data after completing the process.

Let me know if you need any more clarity on this issue.

Capacity of USB drive.

Hello.
How can I know the capacity of USB drive? Seems there is not any API which gives that feature. I need to know how much free space left for writing

NullPointerException when calling root directorys getName() method

When a UsbFile is a root directory it's entry class member is null. So calling method getName() will result in a NullPointerException.

java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.github.mjdev.libaums.fs.fat32.FatLfnDirectoryEntry.getName()' on a null object reference

Doubt: is possible to use to enable the usb mass storage?

I installed the app and I tried to plug a usb pendrive on the smartphone, and the files were listed with success.
But I need to enable/disable the usb mass storage when the user interacts with a button at my activity, to make possible the PC Host read some files on my device. I'm with no luck to find a way to do this without root permission on API 15.
Is possible to use libaums to make this work?
Thanks.

Small fix in example app

Your library really saved my day in order to copy files to USB storage.

I think there's some bug in your MainActivity:

in line 750: should check entry.getName().lastIndexOf("."), in case there's no file extension.
I think it can be fixed like this:
int index = entry.getName().lastIndexOf(".")>0?entry.getName().lastIndexOf("."):entry.getName().length();

Getting file size returns negative value ...

When some of my files bigger than 2 GB, method calling usbFile.getLength() returns negative value. In the root I saw that you changed long to int format (on getUnsignedInt32(int offset, long value) method). It is the cause of returning negative value for a usb file. Why did you change long value to int?

FS Corruption when using UsbFile.moveTo()

I'm seeing filesystem corruption when moving directories using UsbFile.moveTo().

I've been testing this by creating the following directory structure (in the root directory of the filesystem):

Alpha <DIR>
   File1.txt
Beta <DIR>
    File2.txt

If I invoke alphaUsbFile.moveTo(betaUsbFile), the directory structure will appear as follows:

Beta <DIR>
   Alpha <DIR>
      File1.txt

That is, File2.txt is inexplicably deleted.

Further file operations will, over time, result in total destruction of the filesystem, i.e. file listings return hierarchies of garbage directories/files. For example. deleting the "Beta" directory tends to do so.

Have seen this behavior with both "master" and "develop" branches. Thanks for any suggestions, and also generally for your excellent work on this library!

can not read Fat 16 usb

this library is petty perfect

but I can not read Fat 16 usb

What am I doing wrong?

or this library can not read Fat 16 ?

(sorry for my poor English)

createDirectory deletes all other files in directory

Steps to reproduce

  1. getRootDirectory().search(path) to find a UsbFile
  2. call createDirectory on returned UsbFile
    result
    the directory is created but all other files are deleted

the problem is that the UsbFile returned by search is not fully initialised and the 'entries' field is
zero even though the directory does have entries.

Workaround is to call list() or listFIles() after search(path) which will init the UsbFile

Solution could be to ensure that UsbFile returned from search(path) is fully
initialised or init() is called in all methods such as createDirectory and createFile

Move fails for file which is under the root folder

java.lang.RuntimeException: An error occurred while executing doInBackground() at android.os.AsyncTask$3.done(AsyncTask.java:309) at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354) at java.util.concurrent.FutureTask.setException(FutureTask.java:223) at java.util.concurrent.FutureTask.run(FutureTask.java:242) at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) at java.lang.Thread.run(Thread.java:818) Caused by: java.lang.NullPointerException: Attempt to invoke direct method 'void com.github.mjdev.libaums.fs.fat32.FatDirectory.init()' on a null object reference at com.github.mjdev.libaums.fs.fat32.FatDirectory.move(FatDirectory.java:612) at com.github.mjdev.libaums.fs.fat32.FatFile.moveTo(FatFile.java:200)

Is it possible to connect with camera device?

I try to use your library (very nice to use API by the way!) to connect to Nikon camera.
I've already managed to do this using MTP protocol, without your library before.
But I need to send data to the device too (using MTP protocol it's possible from API level 24...).

I would like to use your library, but I don't see any devices listed using getMassStorageDevices, when I connect my Nikon, while I see it and can copy files from it using pure MTP (so I guess permissions should be fine).

Writing to ScsiBlockDevice failed

I added a new android module implementing SAF Document Provider @ https://github.com/jmue/libaums/tree/feature/storageprovider. If I run my sample app usbstorageprovider @ https://github.com/jmue/libaums/tree/test I can browse my usb device. However, if I add this module to your sample app I get the following error:

03-24 20:51:06.162 5010-5815/com.github.mjdev.usbfileman E/ScsiBlockDevice: Writing all bytes on command ScsiRead10 [blockAddress=574, transferBytes=1024, blockSize=512, transferBlocks=2, getdCbwDataTransferLength()=1024] failed! 03-24 20:51:06.164 5010-5815/com.github.mjdev.usbfileman W/DocumentsProvider: Failed during query java.io.FileNotFoundException: reading failed! at com.github.mjdev.libaums.storageprovider.UsbDocumentProvider.queryChildDocuments(UsbDocumentProvider.java:177) at android.provider.DocumentsProvider.query(DocumentsProvider.java:497) at android.content.ContentProvider.query(ContentProvider.java:966) at android.content.ContentProvider$Transport.query(ContentProvider.java:211) at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:112) at android.os.Binder.execTransact(Binder.java:446)

Add caching

  • Caching of FAT
  • Caching of UsbFiles when requested via find() or listFiles()
  • Buffering, e.g. FsInfoStruct

Junk files created randomly

@magnusja

I'm not able to square out a scenario for this problem, but when I download files to the USB drive / copy files from Internal storage to Usb drive , I get some junk files randomly.

I have been using UsbFileOutputstream and UsbFileInputStream for writing / reading data to and from the UsbFiles.

Have u faced any such problems during the course of your development or any one reported earlier?

Delete all files bug.

When I try to delete all files in root directory, it fails to delete a last file.
It looks like there are 2 problems in the code.

  1. FatDirectory.init() :
    if (entries.size() == 0)
    readEntries(); -> this code read a last entry again..
  2. FatDirectory.write()
    If entries.size() == 0 and writeVolumeLabel == false, it does not write well.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.