1
0

ShareActivity.kt 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. package io.github.zadam.triliumsender
  2. import android.content.Context
  3. import android.content.Intent
  4. import android.net.Uri
  5. import android.os.AsyncTask
  6. import android.os.Bundle
  7. import android.support.v7.app.AppCompatActivity
  8. import android.util.Log
  9. import android.widget.Toast
  10. import okhttp3.*
  11. import okhttp3.internal.Util
  12. import okio.BufferedSink
  13. import okio.Okio
  14. import okio.Source
  15. import android.graphics.BitmapFactory
  16. import android.graphics.Bitmap
  17. import java.io.*
  18. import android.opengl.ETC1.getHeight
  19. import android.opengl.ETC1.getWidth
  20. import android.R.attr.bitmap
  21. import android.opengl.ETC1.getHeight
  22. import android.R.attr.maxWidth
  23. import android.opengl.ETC1.getWidth
  24. import android.R.attr.maxHeight
  25. class ShareActivity : AppCompatActivity() {
  26. override fun onCreate(savedInstanceState: Bundle?) {
  27. super.onCreate(savedInstanceState)
  28. setContentView(R.layout.activity_share)
  29. val prefs = this.getSharedPreferences(MainActivity.PREFRENCES_NAME, Context.MODE_PRIVATE);
  30. val triliumAddress = prefs.getString(MainActivity.PREF_TRILIUM_ADDRESS, "");
  31. val token = prefs.getString(MainActivity.PREF_TOKEN, "");
  32. if (triliumAddress.isBlank() || token.isBlank()) {
  33. Toast.makeText(this, "Trilium Sender is not configured. Can't sent the image.", Toast.LENGTH_LONG).show()
  34. finish()
  35. return
  36. }
  37. val imageUri = intent.extras!!.get(Intent.EXTRA_STREAM) as Uri
  38. val mimeType = contentResolver.getType(imageUri)
  39. val sendImageTask = SendImageTask(imageUri, mimeType, triliumAddress, token)
  40. sendImageTask.execute(null as Void?)
  41. }
  42. inner class SendImageResult (val success: Boolean, val contentLength: Long? = null)
  43. inner class SendImageTask internal constructor(private val imageUri: Uri, private val mimeType: String,
  44. private val triliumAddress: String, private val token: String) : AsyncTask<Void, Void, SendImageResult>() {
  45. val TAG : String = "SendImageTask"
  46. override fun doInBackground(vararg params: Void): SendImageResult {
  47. val imageStream = contentResolver.openInputStream(imageUri);
  48. val imageBody = RequestBodyUtil.create(MediaType.parse(mimeType)!!, scaleImage(imageStream, mimeType))
  49. val contentLength = imageBody.contentLength()
  50. val requestBody = MultipartBody.Builder()
  51. .setType(MultipartBody.FORM)
  52. .addFormDataPart("upload", "image", imageBody)
  53. .build()
  54. val client = OkHttpClient()
  55. val request = Request.Builder()
  56. .url(triliumAddress + "/api/sender/image")
  57. .addHeader("Authorization", token)
  58. .post(requestBody)
  59. .build()
  60. try {
  61. val response = client.newCall(request).execute()
  62. return SendImageResult(response.code() == 200, contentLength)
  63. }
  64. catch (e: Exception) {
  65. Log.e(TAG, "Sending to Trilium failed", e)
  66. return SendImageResult(false)
  67. }
  68. }
  69. override fun onPostExecute(result: SendImageResult) {
  70. if (result.success) {
  71. Toast.makeText(this@ShareActivity, "Image sent to Trilium (" + (result.contentLength!! / 1000) + " KB)", Toast.LENGTH_LONG).show()
  72. }
  73. else {
  74. Toast.makeText(this@ShareActivity, "Sending to Trilium failed", Toast.LENGTH_LONG).show()
  75. }
  76. finish()
  77. }
  78. override fun onCancelled() {
  79. }
  80. }
  81. private fun scaleImage(inputStream: InputStream, mimeType: String): InputStream {
  82. // we won't do anything with GIFs, PNGs etc. This is minority use case anyway
  83. if (mimeType != "image/jpeg") {
  84. return inputStream;
  85. }
  86. val options = BitmapFactory.Options()
  87. val bitmap = BitmapFactory.decodeStream(inputStream, null, options)
  88. val maxWidth = 2000
  89. val maxHeight = 2000
  90. val scale = Math.min(maxHeight.toFloat() / bitmap.width, maxWidth.toFloat() / bitmap.height)
  91. val newWidth : Int = if (scale < 1) (bitmap.width * scale).toInt() else bitmap.width;
  92. val newHeight : Int = if (scale < 1) (bitmap.height * scale).toInt() else bitmap.height;
  93. val scaledBitmap = Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, true);
  94. val baos = ByteArrayOutputStream()
  95. scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 75, baos)
  96. val bitmapdata = baos.toByteArray()
  97. return ByteArrayInputStream(bitmapdata)
  98. }
  99. object RequestBodyUtil {
  100. fun create(mediaType: MediaType, inputStream: InputStream): RequestBody {
  101. return object : RequestBody() {
  102. override fun contentType(): MediaType? {
  103. return mediaType
  104. }
  105. override fun contentLength(): Long {
  106. try {
  107. return inputStream.available().toLong()
  108. } catch (e: IOException) {
  109. return 0
  110. }
  111. }
  112. @Throws(IOException::class)
  113. override fun writeTo(sink: BufferedSink) {
  114. var source: Source? = null
  115. try {
  116. source = Okio.source(inputStream)
  117. sink.writeAll(source!!)
  118. } finally {
  119. Util.closeQuietly(source)
  120. }
  121. }
  122. }
  123. }
  124. }
  125. }