using temp file for stream conversion

This commit is contained in:
Mariotaku Lee 2017-01-24 21:17:04 +08:00
parent 03778784bc
commit de0a5be100
No known key found for this signature in database
GPG Key ID: 15C10F89D7C33535
9 changed files with 94 additions and 60 deletions

View File

@ -0,0 +1,27 @@
package org.mariotaku.twidere.util
import android.support.test.InstrumentationRegistry
import android.support.test.runner.AndroidJUnit4
import org.junit.Assert
import org.junit.Test
import org.junit.runner.RunWith
import java.util.*
/**
* Created by mariotaku on 2017/1/24.
*/
@RunWith(AndroidJUnit4::class)
class IOFunctionsKtTest {
@Test
fun testTempFileInputStream() {
val context = InstrumentationRegistry.getTargetContext()
val random = Random()
val testData = ByteArray(1024)
random.nextBytes(testData)
val compareData = tempFileInputStream(context) { os ->
os.write(testData)
}.readBytes(1024)
Assert.assertArrayEquals(testData, compareData)
}
}

View File

@ -8,8 +8,8 @@ import org.mariotaku.twidere.extension.model.filename
import org.mariotaku.twidere.extension.model.readMimeMessageFrom
import org.mariotaku.twidere.extension.model.writeMimeMessageTo
import org.mariotaku.twidere.model.Draft
import org.mariotaku.twidere.util.io.DirectByteArrayOutputStream
import org.mariotaku.twidere.util.sync.FileBasedDraftsSyncAction
import org.mariotaku.twidere.util.tempFileInputStream
import java.io.IOException
import java.util.*
@ -27,20 +27,21 @@ internal class GoogleDriveDraftsSyncAction(
@Throws(IOException::class)
override fun Draft.saveToRemote(): DriveFileInfo {
val os = DirectByteArrayOutputStream()
this.writeMimeMessageTo(context, os)
val driveId = this.remote_extras
val `is` = os.inputStream(true)
val fileConfig: (File) -> Unit = {
it.modifiedTime = DateTime(timestamp)
tempFileInputStream(context) { os ->
this.writeMimeMessageTo(context, os)
}.use {
val driveId = this.remote_extras
val fileConfig: (File) -> Unit = {
it.modifiedTime = DateTime(timestamp)
}
val file = if (driveId != null) {
drive.files().performUpdate(driveId, filename, draftMimeType, stream = it, fileConfig = fileConfig)
} else {
drive.updateOrCreate(name = filename, mimeType = draftMimeType, parent = folderId,
spaces = appDataFolderSpace, stream = it, fileConfig = fileConfig)
}
return DriveFileInfo(file.id, file.name, Date(file.modifiedTime.value))
}
val file = if (driveId != null) {
drive.files().performUpdate(driveId, filename, draftMimeType, stream = `is`, fileConfig = fileConfig)
} else {
drive.updateOrCreate(name = filename, mimeType = draftMimeType, parent = folderId,
spaces = appDataFolderSpace, stream = `is`, fileConfig = fileConfig)
}
return DriveFileInfo(file.id, file.name, Date(file.modifiedTime.value))
}
@Throws(IOException::class)

View File

@ -9,8 +9,8 @@ import org.mariotaku.twidere.extension.model.serialize
import org.mariotaku.twidere.extension.newPullParser
import org.mariotaku.twidere.extension.newSerializer
import org.mariotaku.twidere.model.FiltersData
import org.mariotaku.twidere.util.io.DirectByteArrayOutputStream
import org.mariotaku.twidere.util.sync.FileBasedFiltersDataSyncAction
import org.mariotaku.twidere.util.tempFileInputStream
import java.io.FileNotFoundException
import java.io.IOException
import java.io.InputStream
@ -56,9 +56,9 @@ internal class GoogleDriveFiltersDataSyncAction(
override fun newSaveToRemoteSession(): GoogleDriveUploadSession<FiltersData> {
return object : GoogleDriveUploadSession<FiltersData>(fileName, commonFolderId, xmlMimeType, drive) {
override fun FiltersData.toInputStream(): InputStream {
val os = DirectByteArrayOutputStream()
this.serialize(os.newSerializer(charset = Charsets.UTF_8, indent = true))
return os.inputStream(true)
return tempFileInputStream(context) {
this.serialize(it.newSerializer(charset = Charsets.UTF_8, indent = true))
}
}
}
}

View File

@ -6,8 +6,8 @@ import com.google.api.services.drive.Drive
import com.google.api.services.drive.model.File
import org.mariotaku.twidere.extension.newPullParser
import org.mariotaku.twidere.extension.newSerializer
import org.mariotaku.twidere.util.io.DirectByteArrayOutputStream
import org.mariotaku.twidere.util.sync.FileBasedPreferencesValuesSyncAction
import org.mariotaku.twidere.util.tempFileInputStream
import java.io.FileNotFoundException
import java.io.IOException
import java.io.InputStream
@ -48,9 +48,9 @@ internal class GoogleDrivePreferencesValuesSyncAction(
override fun newSaveToRemoteSession(): GoogleDriveUploadSession<Map<String, String>> {
return object : GoogleDriveUploadSession<Map<String, String>>(fileName, commonFolderId, xmlMimeType, drive) {
override fun Map<String, String>.toInputStream(): InputStream {
val os = DirectByteArrayOutputStream()
this.serialize(os.newSerializer(charset = Charsets.UTF_8, indent = true))
return os.inputStream(true)
return tempFileInputStream(context) {
this.serialize(it.newSerializer(charset = Charsets.UTF_8, indent = true))
}
}
}
}

View File

@ -25,10 +25,12 @@ abstract internal class GoogleDriveUploadSession<in Data>(
abstract fun Data.toInputStream(): InputStream
fun uploadData(data: Data): Boolean {
drive.updateOrCreate(name = name, mimeType = mimeType, parent = parentId,
spaces = appDataFolderSpace, stream = data.toInputStream(), fileConfig = {
it.modifiedTime = DateTime(localModifiedTime)
})
data.toInputStream().use {
drive.updateOrCreate(name = name, mimeType = mimeType, parent = parentId,
spaces = appDataFolderSpace, stream = it, fileConfig = {
it.modifiedTime = DateTime(localModifiedTime)
})
}
return true
}

View File

@ -43,12 +43,8 @@ import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.model.util.AccountUtils
import org.mariotaku.twidere.model.util.ParcelableStatusUtils
import org.mariotaku.twidere.task.twitter.GetStatusesTask
import org.mariotaku.twidere.util.JsonSerializer
import org.mariotaku.twidere.util.SharedPreferencesWrapper
import org.mariotaku.twidere.util.TwidereArrayUtils
import org.mariotaku.twidere.util.UserColorNameManager
import org.mariotaku.twidere.util.*
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper
import java.io.ByteArrayInputStream
import java.io.IOException
import java.util.*
import java.util.concurrent.CopyOnWriteArrayList
@ -237,10 +233,9 @@ abstract class MicroBlogAPIStatusesLoader(
val databaseItemLimit = preferences[loadItemLimitKey]
try {
val statuses = data.subList(0, Math.min(databaseItemLimit, data.size))
fileCache.save(key, ByteArrayInputStream(byteArrayOf())) { current, total -> true }
fileCache.get(key)?.outputStream()?.use {
LoganSquare.serialize(statuses, it, ParcelableStatus::class.java)
}
fileCache.save(key, tempFileInputStream(context) { os ->
LoganSquare.serialize(statuses, os, ParcelableStatus::class.java)
}) { current, total -> true }
} catch (e: Exception) {
// Ignore
if (BuildConfig.DEBUG && e !is IOException) {

View File

@ -259,7 +259,13 @@ class LengthyOperationsService : BaseIntentService("lengthy_operations") {
val exception = result.exception
val exceptions = result.exceptions
if (exception != null) {
Toast.makeText(context, exception.message, Toast.LENGTH_SHORT).show()
val cause = exception.cause
if (cause is MicroBlogException) {
Toast.makeText(context, cause.errors?.firstOrNull()?.message ?: cause.message,
Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(context, exception.message, Toast.LENGTH_SHORT).show()
}
failed = true
Log.w(LOGTAG, exception)
} else for (e in exceptions) {

View File

@ -0,0 +1,27 @@
package org.mariotaku.twidere.util
import android.content.Context
import java.io.File
import java.io.FileInputStream
import java.io.InputStream
import java.io.OutputStream
/**
* Created by mariotaku on 2017/1/24.
*/
fun tempFileInputStream(context: Context, write: (OutputStream) -> Unit): InputStream {
val file = File.createTempFile("twidere__temp_is_file", "tmp", context.cacheDir)
file.outputStream().use { write(it) }
return TempFileInputStream(file)
}
internal class TempFileInputStream(val file: File) : FileInputStream(file) {
override fun close() {
try {
super.close()
} finally {
file.delete()
}
}
}

View File

@ -1,24 +0,0 @@
package org.mariotaku.twidere.util.io
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.InputStream
class DirectByteArrayOutputStream : ByteArrayOutputStream() {
fun inputStream(close: Boolean): InputStream {
return DirectInputStream(this, close)
}
internal class DirectInputStream(
val os: DirectByteArrayOutputStream,
val close: Boolean
) : ByteArrayInputStream(os.buf, 0, os.count) {
override fun close() {
if (close) {
os.close()
}
super.close()
}
}
}