using temp file for stream conversion
This commit is contained in:
parent
03778784bc
commit
de0a5be100
|
@ -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)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -8,8 +8,8 @@ import org.mariotaku.twidere.extension.model.filename
|
||||||
import org.mariotaku.twidere.extension.model.readMimeMessageFrom
|
import org.mariotaku.twidere.extension.model.readMimeMessageFrom
|
||||||
import org.mariotaku.twidere.extension.model.writeMimeMessageTo
|
import org.mariotaku.twidere.extension.model.writeMimeMessageTo
|
||||||
import org.mariotaku.twidere.model.Draft
|
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.sync.FileBasedDraftsSyncAction
|
||||||
|
import org.mariotaku.twidere.util.tempFileInputStream
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
@ -27,20 +27,21 @@ internal class GoogleDriveDraftsSyncAction(
|
||||||
|
|
||||||
@Throws(IOException::class)
|
@Throws(IOException::class)
|
||||||
override fun Draft.saveToRemote(): DriveFileInfo {
|
override fun Draft.saveToRemote(): DriveFileInfo {
|
||||||
val os = DirectByteArrayOutputStream()
|
tempFileInputStream(context) { os ->
|
||||||
this.writeMimeMessageTo(context, os)
|
this.writeMimeMessageTo(context, os)
|
||||||
val driveId = this.remote_extras
|
}.use {
|
||||||
val `is` = os.inputStream(true)
|
val driveId = this.remote_extras
|
||||||
val fileConfig: (File) -> Unit = {
|
val fileConfig: (File) -> Unit = {
|
||||||
it.modifiedTime = DateTime(timestamp)
|
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)
|
@Throws(IOException::class)
|
||||||
|
|
|
@ -9,8 +9,8 @@ import org.mariotaku.twidere.extension.model.serialize
|
||||||
import org.mariotaku.twidere.extension.newPullParser
|
import org.mariotaku.twidere.extension.newPullParser
|
||||||
import org.mariotaku.twidere.extension.newSerializer
|
import org.mariotaku.twidere.extension.newSerializer
|
||||||
import org.mariotaku.twidere.model.FiltersData
|
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.sync.FileBasedFiltersDataSyncAction
|
||||||
|
import org.mariotaku.twidere.util.tempFileInputStream
|
||||||
import java.io.FileNotFoundException
|
import java.io.FileNotFoundException
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
|
@ -56,9 +56,9 @@ internal class GoogleDriveFiltersDataSyncAction(
|
||||||
override fun newSaveToRemoteSession(): GoogleDriveUploadSession<FiltersData> {
|
override fun newSaveToRemoteSession(): GoogleDriveUploadSession<FiltersData> {
|
||||||
return object : GoogleDriveUploadSession<FiltersData>(fileName, commonFolderId, xmlMimeType, drive) {
|
return object : GoogleDriveUploadSession<FiltersData>(fileName, commonFolderId, xmlMimeType, drive) {
|
||||||
override fun FiltersData.toInputStream(): InputStream {
|
override fun FiltersData.toInputStream(): InputStream {
|
||||||
val os = DirectByteArrayOutputStream()
|
return tempFileInputStream(context) {
|
||||||
this.serialize(os.newSerializer(charset = Charsets.UTF_8, indent = true))
|
this.serialize(it.newSerializer(charset = Charsets.UTF_8, indent = true))
|
||||||
return os.inputStream(true)
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,8 @@ import com.google.api.services.drive.Drive
|
||||||
import com.google.api.services.drive.model.File
|
import com.google.api.services.drive.model.File
|
||||||
import org.mariotaku.twidere.extension.newPullParser
|
import org.mariotaku.twidere.extension.newPullParser
|
||||||
import org.mariotaku.twidere.extension.newSerializer
|
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.sync.FileBasedPreferencesValuesSyncAction
|
||||||
|
import org.mariotaku.twidere.util.tempFileInputStream
|
||||||
import java.io.FileNotFoundException
|
import java.io.FileNotFoundException
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
|
@ -48,9 +48,9 @@ internal class GoogleDrivePreferencesValuesSyncAction(
|
||||||
override fun newSaveToRemoteSession(): GoogleDriveUploadSession<Map<String, String>> {
|
override fun newSaveToRemoteSession(): GoogleDriveUploadSession<Map<String, String>> {
|
||||||
return object : GoogleDriveUploadSession<Map<String, String>>(fileName, commonFolderId, xmlMimeType, drive) {
|
return object : GoogleDriveUploadSession<Map<String, String>>(fileName, commonFolderId, xmlMimeType, drive) {
|
||||||
override fun Map<String, String>.toInputStream(): InputStream {
|
override fun Map<String, String>.toInputStream(): InputStream {
|
||||||
val os = DirectByteArrayOutputStream()
|
return tempFileInputStream(context) {
|
||||||
this.serialize(os.newSerializer(charset = Charsets.UTF_8, indent = true))
|
this.serialize(it.newSerializer(charset = Charsets.UTF_8, indent = true))
|
||||||
return os.inputStream(true)
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,10 +25,12 @@ abstract internal class GoogleDriveUploadSession<in Data>(
|
||||||
abstract fun Data.toInputStream(): InputStream
|
abstract fun Data.toInputStream(): InputStream
|
||||||
|
|
||||||
fun uploadData(data: Data): Boolean {
|
fun uploadData(data: Data): Boolean {
|
||||||
drive.updateOrCreate(name = name, mimeType = mimeType, parent = parentId,
|
data.toInputStream().use {
|
||||||
spaces = appDataFolderSpace, stream = data.toInputStream(), fileConfig = {
|
drive.updateOrCreate(name = name, mimeType = mimeType, parent = parentId,
|
||||||
it.modifiedTime = DateTime(localModifiedTime)
|
spaces = appDataFolderSpace, stream = it, fileConfig = {
|
||||||
})
|
it.modifiedTime = DateTime(localModifiedTime)
|
||||||
|
})
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,12 +43,8 @@ import org.mariotaku.twidere.model.UserKey
|
||||||
import org.mariotaku.twidere.model.util.AccountUtils
|
import org.mariotaku.twidere.model.util.AccountUtils
|
||||||
import org.mariotaku.twidere.model.util.ParcelableStatusUtils
|
import org.mariotaku.twidere.model.util.ParcelableStatusUtils
|
||||||
import org.mariotaku.twidere.task.twitter.GetStatusesTask
|
import org.mariotaku.twidere.task.twitter.GetStatusesTask
|
||||||
import org.mariotaku.twidere.util.JsonSerializer
|
import org.mariotaku.twidere.util.*
|
||||||
import org.mariotaku.twidere.util.SharedPreferencesWrapper
|
|
||||||
import org.mariotaku.twidere.util.TwidereArrayUtils
|
|
||||||
import org.mariotaku.twidere.util.UserColorNameManager
|
|
||||||
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper
|
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper
|
||||||
import java.io.ByteArrayInputStream
|
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.CopyOnWriteArrayList
|
import java.util.concurrent.CopyOnWriteArrayList
|
||||||
|
@ -237,10 +233,9 @@ abstract class MicroBlogAPIStatusesLoader(
|
||||||
val databaseItemLimit = preferences[loadItemLimitKey]
|
val databaseItemLimit = preferences[loadItemLimitKey]
|
||||||
try {
|
try {
|
||||||
val statuses = data.subList(0, Math.min(databaseItemLimit, data.size))
|
val statuses = data.subList(0, Math.min(databaseItemLimit, data.size))
|
||||||
fileCache.save(key, ByteArrayInputStream(byteArrayOf())) { current, total -> true }
|
fileCache.save(key, tempFileInputStream(context) { os ->
|
||||||
fileCache.get(key)?.outputStream()?.use {
|
LoganSquare.serialize(statuses, os, ParcelableStatus::class.java)
|
||||||
LoganSquare.serialize(statuses, it, ParcelableStatus::class.java)
|
}) { current, total -> true }
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
// Ignore
|
// Ignore
|
||||||
if (BuildConfig.DEBUG && e !is IOException) {
|
if (BuildConfig.DEBUG && e !is IOException) {
|
||||||
|
|
|
@ -259,7 +259,13 @@ class LengthyOperationsService : BaseIntentService("lengthy_operations") {
|
||||||
val exception = result.exception
|
val exception = result.exception
|
||||||
val exceptions = result.exceptions
|
val exceptions = result.exceptions
|
||||||
if (exception != null) {
|
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
|
failed = true
|
||||||
Log.w(LOGTAG, exception)
|
Log.w(LOGTAG, exception)
|
||||||
} else for (e in exceptions) {
|
} else for (e in exceptions) {
|
||||||
|
|
|
@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue