Perpustakaan untuk mengakses perangkat penyimpanan massal USB (pen drive, HDD eksternal, pembaca kartu) menggunakan Android USB Host API. Saat ini mendukung kumpulan perintah SCSI dan sistem file FAT32.
Perpustakaan dapat dimasukkan ke dalam proyek Anda seperti ini:
implementation 'me.jahnen.libaums:core:0.10.0'
Jika Anda memerlukan HTTP atau modul penyedia penyimpanan:
implementation 'me.jahnen.libaums:httpserver:0.6.2'
implementation 'me.jahnen.libaums:storageprovider:0.6.2'
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 ());
}
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)
}
Aplikasi Anda perlu mendapatkan izin dari pengguna pada waktu proses agar dapat mengkomunikasikan perangkat. Dari UsbMassStorageDevice
Anda bisa mendapatkan android.usb.UsbDevice
yang mendasarinya untuk melakukannya.
PendingIntent permissionIntent = PendingIntent . getBroadcast ( this , 0 , new Intent ( ACTION_USB_PERMISSION ), 0 );
usbManager . requestPermission ( device . getUsbDevice (), permissionIntent );
val permissionIntent = PendingIntent .getBroadcast( this , 0 , Intent ( ACTION_USB_PERMISSION ), 0 );
usbManager.requestPermission(device.usDevice, permissionIntent);
Untuk informasi lebih lanjut mengenai izin, silakan lihat dokumentasi Android: https://developer.android.com/guide/topics/connectivity/usb/host.html#permission-d
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 );
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)
OutputStream os = UsbFileStreamFactory . createBufferedOutputStream ( file , currentFs );
InputStream is = UsbFileStreamFactory . createBufferedInputStream ( file , currentFs );
// Don't forget to call UsbMassStorageDevice.close() when you are finished
device . close ();
Jika Anda cukup sering mendapatkan kesalahan berikut (kebanyakan di Android 9.0 Pie):
java.io.IOException: Could not write to device, result == -1 errno 0 null
atau yang serupa, Anda mungkin ingin mencoba modul libusb. Hal ini menggunakan, alih-alih API host USB Android, pustaka libusb untuk komunikasi tingkat rendah dengan perangkat penyimpanan massal USB.
lihat diskusi: #209 #237 #242
Perhatikan , bahwa libusb dilisensikan di bawah LGPL, yang berbeda dengan lisensi yang dilisensikan oleh proyek ini! Ini mungkin disertai beberapa kekurangan atau kerja ekstra untuk aplikasi sumber tertutup, lihat di sini: https://xebia.com/blog/the-lgpl-on-android/
Biasanya aplikasi pihak ketiga tidak memiliki akses ke file di perangkat penyimpanan massal jika sistem Android melakukan mount (ini biasanya didukung pada perangkat yang lebih baru, pada tahun 2014 tidak ada dukungan untuk itu) perangkat atau aplikasi ini mengintegrasikan perpustakaan ini sendiri . Untuk mengatasi masalah ini ada dua modul tambahan untuk menyediakan akses ke aplikasi lain. Yang satu menggunakan fitur Storage Access Framework Android (API level >= 19) dan yang lainnya menjalankan server HTTP untuk memungkinkan pengunduhan atau streaming video atau gambar misalnya.
libaums saat ini mendukung dua perpustakaan server HTTP yang berbeda.
Anda dapat menjalankan server dengan cukup mudah, Anda hanya perlu memutuskan implementasi server HTTP. Jika Anda tidak memiliki persyaratan khusus, Anda dapat memilih satu saja, itu tidak akan membuat banyak perbedaan.
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 ();
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()
File yang Anda berikan dapat berupa file sebenarnya atau direktori:
Jika Anda ingin dapat mengakses file-file ini saat aplikasi Anda berada di latar belakang, Anda harus menerapkan layanan untuk itu. Ada contoh yang tersedia di modul httpserver
. Anda dapat menggunakannya, tetapi harus membuat subkelasnya atau membuatnya sendiri untuk menyesuaikannya dengan kebutuhan Anda.
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 ));
...
}
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 )
}
Lihat contoh aplikasi untuk detail tambahan mengenai hal itu.
Untuk mempelajari lebih lanjut tentang kunjungan ini: https://developer.android.com/guide/topics/providers/document-provider.html
Untuk mengintegrasikan modul ini ke dalam aplikasi Anda, satu-satunya hal yang harus Anda lakukan adalah menambahkan definisi di AndroidManifest.xml Anda.
< 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 >
Setelah itu aplikasi yang menggunakan Storage Access Framework akan dapat mengakses file perangkat penyimpanan massal USB.
app/
Anda dapat menemukan contoh aplikasi menggunakan perpustakaan.UsbFile.setLength(long)
terlebih dahulu. Kalau tidak, ClusterChain harus ditingkatkan untuk setiap panggilan untuk menulis. Hal ini sangat tidak efisien.FileSystem.getChunkSize()
sebagai ukuran buffer, karena ini sesuai dengan ukuran blok yang digunakan drive. Segala sesuatu yang lain kemungkinan besar juga merupakan penurunan kinerja.UsbFileStreamFactory
. Perpustakaan ini dikembangkan oleh Bapak Jahnen sebagai bagian dari tesis sarjananya pada tahun 2014. Ini adalah sub-topik dari topik penelitian "Perlindungan Salinan Aman untuk Aplikasi Seluler" oleh Bapak Kannengießer. Dokumen skripsi selengkapnya dapat diunduh di sini.
Libaums - Perpustakaan untuk mengakses Perangkat Penyimpanan Massal USB
Lisensi: Apache 2.0 (lihat lisensi.txt untuk detailnya)
Penulis: Magnus Jahnen, [email protected] Penasihat: Nils Kannengießer, nils.kannengiesser di tum.de
Pembimbing: Prof. Uwe Baumgarten, baumgaru di in.tum.de
Technische Universität München (TUM)
Lehrstuhl/Fachgebiet untuk Betriebssysteme
www.os.in.tum.de