mirror of
https://github.com/oxen-io/session-android.git
synced 2025-02-22 04:38:26 +00:00
fix: saving log external instead of session blob
This commit is contained in:
parent
a55c9a969b
commit
e8a2bbe76d
@ -154,7 +154,7 @@ dependencies {
|
|||||||
testImplementation 'org.robolectric:shadows-multidex:4.4'
|
testImplementation 'org.robolectric:shadows-multidex:4.4'
|
||||||
}
|
}
|
||||||
|
|
||||||
def canonicalVersionCode = 228
|
def canonicalVersionCode = 229
|
||||||
def canonicalVersionName = "1.11.11"
|
def canonicalVersionName = "1.11.11"
|
||||||
|
|
||||||
def postFixSize = 10
|
def postFixSize = 10
|
||||||
|
@ -7,10 +7,7 @@ import android.content.ClipboardManager
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.AsyncTask
|
import android.os.*
|
||||||
import android.os.Bundle
|
|
||||||
import android.os.Handler
|
|
||||||
import android.os.Looper
|
|
||||||
import android.view.ActionMode
|
import android.view.ActionMode
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
@ -323,7 +320,17 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun shareLogs() {
|
private fun shareLogs() {
|
||||||
ShareLogsDialog().show(supportFragmentManager,"Share Logs Dialog")
|
Permissions.with(this)
|
||||||
|
.request(Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||||
|
.maxSdkVersion(Build.VERSION_CODES.P)
|
||||||
|
.withPermanentDenialDialog(getString(R.string.MediaPreviewActivity_signal_needs_the_storage_permission_in_order_to_write_to_external_storage_but_it_has_been_permanently_denied))
|
||||||
|
.onAnyDenied {
|
||||||
|
Toast.makeText(this, R.string.MediaPreviewActivity_unable_to_write_to_external_storage_without_permission, Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
.onAllGranted {
|
||||||
|
ShareLogsDialog().show(supportFragmentManager,"Share Logs Dialog")
|
||||||
|
}
|
||||||
|
.execute()
|
||||||
}
|
}
|
||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
|
@ -1,8 +1,15 @@
|
|||||||
package org.thoughtcrime.securesms.preferences
|
package org.thoughtcrime.securesms.preferences
|
||||||
|
|
||||||
|
import android.content.ContentResolver
|
||||||
|
import android.content.ContentValues
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.media.MediaScannerConnection
|
||||||
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
import android.os.Environment
|
||||||
|
import android.provider.MediaStore
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
import android.webkit.MimeTypeMap
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
@ -12,9 +19,15 @@ import kotlinx.coroutines.Job
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import network.loki.messenger.BuildConfig
|
import network.loki.messenger.BuildConfig
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
|
import org.session.libsignal.utilities.ExternalStorageUtil
|
||||||
import org.thoughtcrime.securesms.ApplicationContext
|
import org.thoughtcrime.securesms.ApplicationContext
|
||||||
import org.thoughtcrime.securesms.conversation.v2.utilities.BaseDialog
|
import org.thoughtcrime.securesms.conversation.v2.utilities.BaseDialog
|
||||||
import org.thoughtcrime.securesms.providers.BlobProvider
|
import org.thoughtcrime.securesms.util.StreamUtil
|
||||||
|
import java.io.File
|
||||||
|
import java.io.FileOutputStream
|
||||||
|
import java.io.IOException
|
||||||
|
import java.util.*
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
class ShareLogsDialog : BaseDialog() {
|
class ShareLogsDialog : BaseDialog() {
|
||||||
|
|
||||||
@ -39,16 +52,41 @@ class ShareLogsDialog : BaseDialog() {
|
|||||||
shareJob = lifecycleScope.launch(Dispatchers.IO) {
|
shareJob = lifecycleScope.launch(Dispatchers.IO) {
|
||||||
val persistentLogger = ApplicationContext.getInstance(context).persistentLogger
|
val persistentLogger = ApplicationContext.getInstance(context).persistentLogger
|
||||||
try {
|
try {
|
||||||
val logs = persistentLogger.logs.get()
|
val context = requireContext()
|
||||||
val fileName = "${Build.MANUFACTURER}-${Build.DEVICE}-API${Build.VERSION.SDK_INT}-v${BuildConfig.VERSION_NAME}.txt"
|
val outputUri: Uri = ExternalStorageUtil.getDownloadUri()
|
||||||
val logUri = BlobProvider().forData(logs.toByteArray())
|
val mediaUri = getExternalFile()
|
||||||
.withFileName(fileName)
|
if (mediaUri == null) {
|
||||||
.withMimeType("text/plain")
|
// show toast saying media saved
|
||||||
.createForSingleSessionOnDisk(requireContext(),null)
|
dismiss()
|
||||||
|
return@launch
|
||||||
|
}
|
||||||
|
|
||||||
|
val inputStream = persistentLogger.logs.get().byteInputStream()
|
||||||
|
val updateValues = ContentValues()
|
||||||
|
if (outputUri.scheme == ContentResolver.SCHEME_FILE) {
|
||||||
|
FileOutputStream(mediaUri.path).use { outputStream ->
|
||||||
|
StreamUtil.copy(inputStream, outputStream)
|
||||||
|
MediaScannerConnection.scanFile(context, arrayOf(mediaUri.path), arrayOf("text/plain"), null)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
context.contentResolver.openOutputStream(mediaUri, "w").use { outputStream ->
|
||||||
|
val total: Long = StreamUtil.copy(inputStream, outputStream)
|
||||||
|
if (total > 0) {
|
||||||
|
updateValues.put(MediaStore.MediaColumns.SIZE, total)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Build.VERSION.SDK_INT > 28) {
|
||||||
|
updateValues.put(MediaStore.MediaColumns.IS_PENDING, 0)
|
||||||
|
}
|
||||||
|
if (updateValues.size() > 0) {
|
||||||
|
requireContext().contentResolver.update(mediaUri, updateValues, null, null)
|
||||||
|
}
|
||||||
|
|
||||||
val shareIntent = Intent().apply {
|
val shareIntent = Intent().apply {
|
||||||
action = Intent.ACTION_SEND
|
action = Intent.ACTION_SEND
|
||||||
putExtra(Intent.EXTRA_STREAM, logUri)
|
putExtra(Intent.EXTRA_STREAM, mediaUri)
|
||||||
|
data = mediaUri
|
||||||
type = "text/plain"
|
type = "text/plain"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,4 +100,56 @@ class ShareLogsDialog : BaseDialog() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
private fun pathTaken(outputUri: Uri, dataPath: String): Boolean {
|
||||||
|
requireContext().contentResolver.query(outputUri, arrayOf(MediaStore.MediaColumns.DATA),
|
||||||
|
MediaStore.MediaColumns.DATA + " = ?", arrayOf(dataPath),
|
||||||
|
null).use { cursor ->
|
||||||
|
if (cursor == null) {
|
||||||
|
throw IOException("Something is wrong with the filename to save")
|
||||||
|
}
|
||||||
|
return cursor.moveToFirst()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getExternalFile(): Uri? {
|
||||||
|
val context = requireContext()
|
||||||
|
val base = "${Build.MANUFACTURER}-${Build.DEVICE}-API${Build.VERSION.SDK_INT}-v${BuildConfig.VERSION_NAME}-${System.currentTimeMillis()}"
|
||||||
|
val extension = "txt"
|
||||||
|
val fileName = "$base.$extension"
|
||||||
|
val mimeType = MimeTypeMap.getSingleton().getExtensionFromMimeType("text/plain")
|
||||||
|
val outputUri: Uri = ExternalStorageUtil.getDownloadUri()
|
||||||
|
val contentValues = ContentValues()
|
||||||
|
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, fileName)
|
||||||
|
contentValues.put(MediaStore.MediaColumns.MIME_TYPE, mimeType)
|
||||||
|
contentValues.put(MediaStore.MediaColumns.DATE_ADDED, TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()))
|
||||||
|
contentValues.put(MediaStore.MediaColumns.DATE_MODIFIED, TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()))
|
||||||
|
if (Build.VERSION.SDK_INT > 28) {
|
||||||
|
contentValues.put(MediaStore.MediaColumns.IS_PENDING, 1)
|
||||||
|
} else if (Objects.equals(outputUri.scheme, ContentResolver.SCHEME_FILE)) {
|
||||||
|
val outputDirectory = File(outputUri.path)
|
||||||
|
var outputFile = File(outputDirectory, "$base.$extension")
|
||||||
|
var i = 0
|
||||||
|
while (outputFile.exists()) {
|
||||||
|
outputFile = File(outputDirectory, base + "-" + ++i + "." + extension)
|
||||||
|
}
|
||||||
|
if (outputFile.isHidden) {
|
||||||
|
throw IOException("Specified name would not be visible")
|
||||||
|
}
|
||||||
|
return Uri.fromFile(outputFile)
|
||||||
|
} else {
|
||||||
|
var outputFileName = fileName
|
||||||
|
val externalPath = context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS)!!
|
||||||
|
var dataPath = String.format("%s/%s", externalPath, outputFileName)
|
||||||
|
var i = 0
|
||||||
|
while (pathTaken(outputUri, dataPath)) {
|
||||||
|
outputFileName = base + "-" + ++i + "." + extension
|
||||||
|
dataPath = String.format("%s/%s", externalPath, outputFileName)
|
||||||
|
}
|
||||||
|
contentValues.put(MediaStore.MediaColumns.DATA, dataPath)
|
||||||
|
}
|
||||||
|
return context.contentResolver.insert(outputUri, contentValues)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user