Loading app/src/main/java/at/bitfire/davdroid/DavUtils.kt +1 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ object DavUtils { } const val MIME_TYPE_ALL = "*/*" const val MIME_TYPE_OCTET_STREAM = "application/octet-stream" @Suppress("FunctionName") Loading app/src/main/java/at/bitfire/davdroid/model/WebDavDocument.kt +11 −1 Original line number Diff line number Diff line package at.bitfire.davdroid.model import android.annotation.SuppressLint import android.os.Bundle import android.provider.DocumentsContract.Document import android.webkit.MimeTypeMap import androidx.room.Entity import androidx.room.ForeignKey import androidx.room.Index import androidx.room.PrimaryKey import at.bitfire.davdroid.DavUtils.MIME_TYPE_OCTET_STREAM import okhttp3.HttpUrl import java.io.FileNotFoundException Loading Loading @@ -49,6 +52,7 @@ data class WebDavDocument( ): IdEntity { @SuppressLint("InlinedApi") fun toBundle(parent: WebDavDocument?): Bundle { if (parent?.isDirectory == false) throw IllegalArgumentException("Parent must be a directory") Loading @@ -68,7 +72,13 @@ data class WebDavDocument( if (mayBind != false) flags += Document.FLAG_DIR_SUPPORTS_CREATE } else { bundle.putString(Document.COLUMN_MIME_TYPE, mimeType) val reportedMimeType = mimeType ?: MimeTypeMap.getSingleton().getMimeTypeFromExtension( MimeTypeMap.getFileExtensionFromUrl(name) ) ?: MIME_TYPE_OCTET_STREAM bundle.putString(Document.COLUMN_MIME_TYPE, reportedMimeType) if (mimeType?.startsWith("image/") == true) flags += Document.FLAG_SUPPORTS_THUMBNAIL if (mayWriteContent != false) Loading app/src/main/java/at/bitfire/davdroid/webdav/DavDocumentsProvider.kt +13 −4 Original line number Diff line number Diff line Loading @@ -495,7 +495,7 @@ class DavDocumentsProvider: DocumentsProvider() { val client = httpClient(doc.mountId) val modeFlags = ParcelFileDescriptor.parseMode(mode) val readOnly = when (mode) { val readAccess = when (mode) { "r" -> true "w", "wt" -> false else -> throw UnsupportedOperationException("Mode $mode not supported by WebDAV") Loading @@ -512,7 +512,7 @@ class DavDocumentsProvider: DocumentsProvider() { return if ( Build.VERSION.SDK_INT >= 26 && // openProxyFileDescriptor exists since Android 8.0 readOnly && // WebDAV doesn't support random write access natively readAccess && // WebDAV doesn't support random write access natively fileInfo.size != null && // file descriptor must return a useful value on getFileSize() (fileInfo.eTag != null || fileInfo.lastModified != null) && // we need a method to determine whether the document has changed during access fileInfo.supportsPartial != false // WebDAV server must support random access Loading @@ -520,12 +520,21 @@ class DavDocumentsProvider: DocumentsProvider() { val accessor = RandomAccessCallback(context!!, client, url, doc.mimeType, fileInfo, signal) storageManager.openProxyFileDescriptor(modeFlags, accessor, accessor.workerHandler) } else { val fd = StreamingFileDescriptor(context!!, client, url, doc.mimeType, signal) { val fd = StreamingFileDescriptor(context!!, client, url, doc.mimeType, signal) { transferred -> // called when transfer is finished val now = System.currentTimeMillis() if (!readAccess /* write access */) { // write access, update file size doc.size = transferred doc.lastModified = now documentDao.update(doc) } notifyFolderChanged(doc.parentId) } if (readOnly) if (readAccess) fd.download() else fd.upload() Loading app/src/main/java/at/bitfire/davdroid/webdav/DocumentsCursor.kt +1 −1 Original line number Diff line number Diff line Loading @@ -6,7 +6,7 @@ import android.provider.DocumentsContract class DocumentsCursor(columns: Array<out String>): MatrixCursor(columns) { val documentsExtras = Bundle(1) private val documentsExtras = Bundle(1) override fun getExtras() = documentsExtras Loading app/src/main/java/at/bitfire/davdroid/webdav/StreamingFileDescriptor.kt +8 −4 Original line number Diff line number Diff line Loading @@ -30,7 +30,7 @@ class StreamingFileDescriptor( val url: HttpUrl, val mimeType: String?, val cancellationSignal: CancellationSignal?, val finishedCallback: () -> Unit val finishedCallback: OnSuccessCallback ) { companion object { Loading @@ -39,6 +39,7 @@ class StreamingFileDescriptor( } val dav = DavResource(client.okHttpClient, url) var transferred: Long = 0 private val notificationManager = NotificationManagerCompat.from(context) private val notification = NotificationCompat.Builder(context, NotificationUtils.CHANNEL_STATUS) Loading Loading @@ -77,7 +78,7 @@ class StreamingFileDescriptor( notificationManager.cancel(notificationTag, NotificationUtils.NOTIFY_WEBDAV_ACCESS) finishedCallback() finishedCallback.onSuccess(transferred) } cancellationSignal?.setOnCancelListener { Loading Loading @@ -117,7 +118,6 @@ class StreamingFileDescriptor( body.byteStream().use { source -> // read first chunk var bytes = source.read(buffer) var transferred = 0L while (bytes != -1) { // update notification (if file size is known) if (length != -1L) Loading Loading @@ -162,7 +162,6 @@ class StreamingFileDescriptor( ParcelFileDescriptor.AutoCloseInputStream(readFd).use { input -> val buffer = ByteArray(BUFFER_SIZE) var transferred = 0L // read first chunk var size = input.read(buffer) Loading @@ -183,4 +182,9 @@ class StreamingFileDescriptor( } } fun interface OnSuccessCallback { fun onSuccess(transferred: Long) } } No newline at end of file Loading
app/src/main/java/at/bitfire/davdroid/DavUtils.kt +1 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ object DavUtils { } const val MIME_TYPE_ALL = "*/*" const val MIME_TYPE_OCTET_STREAM = "application/octet-stream" @Suppress("FunctionName") Loading
app/src/main/java/at/bitfire/davdroid/model/WebDavDocument.kt +11 −1 Original line number Diff line number Diff line package at.bitfire.davdroid.model import android.annotation.SuppressLint import android.os.Bundle import android.provider.DocumentsContract.Document import android.webkit.MimeTypeMap import androidx.room.Entity import androidx.room.ForeignKey import androidx.room.Index import androidx.room.PrimaryKey import at.bitfire.davdroid.DavUtils.MIME_TYPE_OCTET_STREAM import okhttp3.HttpUrl import java.io.FileNotFoundException Loading Loading @@ -49,6 +52,7 @@ data class WebDavDocument( ): IdEntity { @SuppressLint("InlinedApi") fun toBundle(parent: WebDavDocument?): Bundle { if (parent?.isDirectory == false) throw IllegalArgumentException("Parent must be a directory") Loading @@ -68,7 +72,13 @@ data class WebDavDocument( if (mayBind != false) flags += Document.FLAG_DIR_SUPPORTS_CREATE } else { bundle.putString(Document.COLUMN_MIME_TYPE, mimeType) val reportedMimeType = mimeType ?: MimeTypeMap.getSingleton().getMimeTypeFromExtension( MimeTypeMap.getFileExtensionFromUrl(name) ) ?: MIME_TYPE_OCTET_STREAM bundle.putString(Document.COLUMN_MIME_TYPE, reportedMimeType) if (mimeType?.startsWith("image/") == true) flags += Document.FLAG_SUPPORTS_THUMBNAIL if (mayWriteContent != false) Loading
app/src/main/java/at/bitfire/davdroid/webdav/DavDocumentsProvider.kt +13 −4 Original line number Diff line number Diff line Loading @@ -495,7 +495,7 @@ class DavDocumentsProvider: DocumentsProvider() { val client = httpClient(doc.mountId) val modeFlags = ParcelFileDescriptor.parseMode(mode) val readOnly = when (mode) { val readAccess = when (mode) { "r" -> true "w", "wt" -> false else -> throw UnsupportedOperationException("Mode $mode not supported by WebDAV") Loading @@ -512,7 +512,7 @@ class DavDocumentsProvider: DocumentsProvider() { return if ( Build.VERSION.SDK_INT >= 26 && // openProxyFileDescriptor exists since Android 8.0 readOnly && // WebDAV doesn't support random write access natively readAccess && // WebDAV doesn't support random write access natively fileInfo.size != null && // file descriptor must return a useful value on getFileSize() (fileInfo.eTag != null || fileInfo.lastModified != null) && // we need a method to determine whether the document has changed during access fileInfo.supportsPartial != false // WebDAV server must support random access Loading @@ -520,12 +520,21 @@ class DavDocumentsProvider: DocumentsProvider() { val accessor = RandomAccessCallback(context!!, client, url, doc.mimeType, fileInfo, signal) storageManager.openProxyFileDescriptor(modeFlags, accessor, accessor.workerHandler) } else { val fd = StreamingFileDescriptor(context!!, client, url, doc.mimeType, signal) { val fd = StreamingFileDescriptor(context!!, client, url, doc.mimeType, signal) { transferred -> // called when transfer is finished val now = System.currentTimeMillis() if (!readAccess /* write access */) { // write access, update file size doc.size = transferred doc.lastModified = now documentDao.update(doc) } notifyFolderChanged(doc.parentId) } if (readOnly) if (readAccess) fd.download() else fd.upload() Loading
app/src/main/java/at/bitfire/davdroid/webdav/DocumentsCursor.kt +1 −1 Original line number Diff line number Diff line Loading @@ -6,7 +6,7 @@ import android.provider.DocumentsContract class DocumentsCursor(columns: Array<out String>): MatrixCursor(columns) { val documentsExtras = Bundle(1) private val documentsExtras = Bundle(1) override fun getExtras() = documentsExtras Loading
app/src/main/java/at/bitfire/davdroid/webdav/StreamingFileDescriptor.kt +8 −4 Original line number Diff line number Diff line Loading @@ -30,7 +30,7 @@ class StreamingFileDescriptor( val url: HttpUrl, val mimeType: String?, val cancellationSignal: CancellationSignal?, val finishedCallback: () -> Unit val finishedCallback: OnSuccessCallback ) { companion object { Loading @@ -39,6 +39,7 @@ class StreamingFileDescriptor( } val dav = DavResource(client.okHttpClient, url) var transferred: Long = 0 private val notificationManager = NotificationManagerCompat.from(context) private val notification = NotificationCompat.Builder(context, NotificationUtils.CHANNEL_STATUS) Loading Loading @@ -77,7 +78,7 @@ class StreamingFileDescriptor( notificationManager.cancel(notificationTag, NotificationUtils.NOTIFY_WEBDAV_ACCESS) finishedCallback() finishedCallback.onSuccess(transferred) } cancellationSignal?.setOnCancelListener { Loading Loading @@ -117,7 +118,6 @@ class StreamingFileDescriptor( body.byteStream().use { source -> // read first chunk var bytes = source.read(buffer) var transferred = 0L while (bytes != -1) { // update notification (if file size is known) if (length != -1L) Loading Loading @@ -162,7 +162,6 @@ class StreamingFileDescriptor( ParcelFileDescriptor.AutoCloseInputStream(readFd).use { input -> val buffer = ByteArray(BUFFER_SIZE) var transferred = 0L // read first chunk var size = input.read(buffer) Loading @@ -183,4 +182,9 @@ class StreamingFileDescriptor( } } fun interface OnSuccessCallback { fun onSuccess(transferred: Long) } } No newline at end of file