2018-01-04 19:52:25 +01:00
|
|
|
package jp.juggler.subwaytooter
|
|
|
|
|
|
|
|
import android.content.Intent
|
|
|
|
import android.net.Uri
|
|
|
|
import android.os.Bundle
|
2019-02-15 02:51:22 +01:00
|
|
|
import androidx.core.content.FileProvider
|
|
|
|
import androidx.appcompat.app.AppCompatActivity
|
2018-12-01 00:02:18 +01:00
|
|
|
import jp.juggler.util.LogCategory
|
|
|
|
import jp.juggler.util.digestSHA256Hex
|
2018-01-04 19:52:25 +01:00
|
|
|
import org.apache.commons.io.IOUtils
|
|
|
|
import java.io.File
|
|
|
|
import java.io.FileOutputStream
|
2018-12-01 00:02:18 +01:00
|
|
|
import java.util.*
|
2018-01-04 19:52:25 +01:00
|
|
|
import java.util.concurrent.atomic.AtomicReference
|
|
|
|
|
|
|
|
class ActCallback : AppCompatActivity() {
|
|
|
|
|
2018-01-21 13:46:36 +01:00
|
|
|
companion object {
|
|
|
|
private val log = LogCategory("ActCallback")
|
|
|
|
|
|
|
|
internal val last_uri = AtomicReference<Uri>(null)
|
|
|
|
internal val sent_intent = AtomicReference<Intent>(null)
|
2019-06-20 02:22:42 +02:00
|
|
|
|
2019-09-12 15:43:11 +02:00
|
|
|
private fun String?.isMediaMimeType() = when {
|
2019-06-20 02:22:42 +02:00
|
|
|
this == null -> false
|
|
|
|
this.startsWith("image/") -> true
|
|
|
|
this.startsWith("video/") -> true
|
|
|
|
this.startsWith("audio/") -> true
|
|
|
|
else -> false
|
|
|
|
|
|
|
|
}
|
2018-01-21 13:46:36 +01:00
|
|
|
}
|
2018-11-02 01:09:31 +01:00
|
|
|
|
2018-01-04 19:52:25 +01:00
|
|
|
override fun onCreate(savedInstanceState : Bundle?) {
|
2018-11-02 01:09:31 +01:00
|
|
|
log.d("onCreate flags=%x", intent.flags)
|
2018-01-04 19:52:25 +01:00
|
|
|
super.onCreate(savedInstanceState)
|
2019-09-12 15:43:11 +02:00
|
|
|
|
2018-01-04 19:52:25 +01:00
|
|
|
var intent : Intent? = intent
|
2018-11-02 01:09:31 +01:00
|
|
|
when {
|
|
|
|
intent == null -> {
|
|
|
|
// 多分起きないと思う
|
|
|
|
}
|
|
|
|
|
|
|
|
(intent.flags and Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0 -> {
|
|
|
|
// 履歴から開いた場合はIntentの中味を読まない
|
|
|
|
}
|
|
|
|
|
|
|
|
else -> {
|
|
|
|
val action = intent.action
|
|
|
|
val type = intent.type
|
|
|
|
if(
|
|
|
|
// ACTION_SEND か ACTION_SEND_MULTIPLE
|
|
|
|
Intent.ACTION_SEND == action
|
|
|
|
|| Intent.ACTION_SEND_MULTIPLE == action
|
2019-07-19 10:58:05 +02:00
|
|
|
// ACTION_VIEW かつ type が 画像かビデオか音声
|
2019-09-12 15:43:11 +02:00
|
|
|
|| Intent.ACTION_VIEW == action && type.isMediaMimeType()) {
|
2018-11-02 01:09:31 +01:00
|
|
|
|
|
|
|
// Google Photo などから送られるIntentに含まれるuriの有効期間はActivityが閉じられるまで
|
|
|
|
// http://qiita.com/pside/items/a821e2fe9ae6b7c1a98c
|
|
|
|
|
|
|
|
// 有効期間を延長する
|
|
|
|
intent = remake(intent)
|
|
|
|
if(intent != null) {
|
|
|
|
sent_intent.set(intent)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
val uri = intent.data
|
|
|
|
if(uri != null) {
|
|
|
|
last_uri.set(uri)
|
|
|
|
}
|
2018-01-04 19:52:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-11-02 01:09:31 +01:00
|
|
|
|
2018-01-04 19:52:25 +01:00
|
|
|
// どうであれメイン画面に戻る
|
|
|
|
intent = Intent(this, ActMain::class.java)
|
|
|
|
intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY or Intent.FLAG_ACTIVITY_NEW_TASK)
|
|
|
|
startActivity(intent)
|
|
|
|
finish()
|
|
|
|
}
|
|
|
|
|
2018-11-02 01:09:31 +01:00
|
|
|
private fun copyExtraTexts(dst : Intent, src : Intent) {
|
|
|
|
var sv : String?
|
2018-08-04 20:56:51 +02:00
|
|
|
//
|
|
|
|
sv = src.getStringExtra(Intent.EXTRA_TEXT)
|
2018-11-02 01:09:31 +01:00
|
|
|
if(sv != null) dst.putExtra(Intent.EXTRA_TEXT, sv)
|
2018-08-04 20:56:51 +02:00
|
|
|
//
|
|
|
|
sv = src.getStringExtra(Intent.EXTRA_SUBJECT)
|
2018-11-02 01:09:31 +01:00
|
|
|
if(sv != null) dst.putExtra(Intent.EXTRA_SUBJECT, sv)
|
2018-08-04 20:56:51 +02:00
|
|
|
}
|
|
|
|
|
2018-01-04 19:52:25 +01:00
|
|
|
private fun remake(src : Intent) : Intent? {
|
|
|
|
|
|
|
|
sweepOldCache()
|
|
|
|
|
|
|
|
try {
|
|
|
|
val action = src.action
|
|
|
|
val type = src.type
|
|
|
|
|
2019-09-12 15:43:11 +02:00
|
|
|
if(type.isMediaMimeType()) {
|
2018-01-04 19:52:25 +01:00
|
|
|
if(Intent.ACTION_VIEW == action) {
|
|
|
|
src.data?.let { uriOriginal ->
|
|
|
|
try {
|
|
|
|
val uri = saveToCache(uriOriginal)
|
|
|
|
val dst = Intent(action)
|
|
|
|
dst.setDataAndType(uri, type)
|
2018-11-02 01:09:31 +01:00
|
|
|
copyExtraTexts(dst, src)
|
2018-01-04 19:52:25 +01:00
|
|
|
return dst
|
|
|
|
} catch(ex : Throwable) {
|
|
|
|
log.trace(ex)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if(Intent.ACTION_SEND == action) {
|
|
|
|
var uri : Uri? = src.getParcelableExtra(Intent.EXTRA_STREAM)
|
|
|
|
if(uri == null) {
|
|
|
|
// text/plain
|
|
|
|
return src
|
|
|
|
} else {
|
|
|
|
try {
|
|
|
|
uri = saveToCache(uri)
|
|
|
|
|
|
|
|
val dst = Intent(action)
|
|
|
|
dst.type = type
|
|
|
|
dst.putExtra(Intent.EXTRA_STREAM, uri)
|
2018-11-02 01:09:31 +01:00
|
|
|
copyExtraTexts(dst, src)
|
2018-01-04 19:52:25 +01:00
|
|
|
return dst
|
|
|
|
} catch(ex : Throwable) {
|
|
|
|
log.trace(ex)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
} else if(Intent.ACTION_SEND_MULTIPLE == action) {
|
2018-11-02 01:09:31 +01:00
|
|
|
val list_uri =
|
|
|
|
src.getParcelableArrayListExtra<Uri>(Intent.EXTRA_STREAM) ?: return null
|
2018-01-04 19:52:25 +01:00
|
|
|
val list_dst = ArrayList<Uri>()
|
|
|
|
for(uriOriginal in list_uri) {
|
|
|
|
if(uriOriginal != null) {
|
|
|
|
try {
|
|
|
|
val uri = saveToCache(uriOriginal)
|
|
|
|
list_dst.add(uri)
|
|
|
|
} catch(ex : Throwable) {
|
|
|
|
log.trace(ex)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(list_dst.isEmpty()) return null
|
|
|
|
val dst = Intent(action)
|
|
|
|
dst.type = type
|
|
|
|
dst.putParcelableArrayListExtra(Intent.EXTRA_STREAM, list_dst)
|
2018-11-02 01:09:31 +01:00
|
|
|
copyExtraTexts(dst, src)
|
2018-01-04 19:52:25 +01:00
|
|
|
return dst
|
|
|
|
}
|
|
|
|
} else if(Intent.ACTION_SEND == action) {
|
|
|
|
|
|
|
|
// Swarmアプリから送られたインテントは getType()==null だが EXTRA_TEXT は含まれている
|
|
|
|
// EXTRA_TEXT の存在を確認してからtypeがnullもしくは text/plain なら受け取る
|
|
|
|
|
2018-08-04 20:56:51 +02:00
|
|
|
val sv = src.getStringExtra(Intent.EXTRA_TEXT)
|
2018-11-02 01:09:31 +01:00
|
|
|
if(sv?.isNotEmpty() == true && (type == null || type.startsWith("text/"))) {
|
2018-01-04 19:52:25 +01:00
|
|
|
val dst = Intent(action)
|
|
|
|
dst.type = "text/plain"
|
2018-11-02 01:09:31 +01:00
|
|
|
copyExtraTexts(dst, src)
|
2018-08-04 20:56:51 +02:00
|
|
|
|
2018-01-04 19:52:25 +01:00
|
|
|
return dst
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch(ex : Throwable) {
|
|
|
|
log.trace(ex)
|
|
|
|
}
|
|
|
|
|
|
|
|
return null
|
|
|
|
}
|
|
|
|
|
|
|
|
@Throws(Throwable::class)
|
|
|
|
private fun saveToCache(uri : Uri) : Uri {
|
|
|
|
|
|
|
|
// prepare cache directory
|
|
|
|
val cache_dir = cacheDir
|
|
|
|
|
|
|
|
cache_dir.mkdirs()
|
|
|
|
|
2018-11-02 01:09:31 +01:00
|
|
|
val name =
|
|
|
|
"img." + System.currentTimeMillis().toString() + "." + uri.toString().digestSHA256Hex()
|
2018-01-04 19:52:25 +01:00
|
|
|
|
|
|
|
val dst = File(cache_dir, name)
|
|
|
|
|
|
|
|
FileOutputStream(dst).use { outStream ->
|
|
|
|
val source = contentResolver.openInputStream(uri)
|
2018-11-02 01:09:31 +01:00
|
|
|
?: throw RuntimeException("getContentResolver.openInputStream returns null.")
|
2018-01-04 19:52:25 +01:00
|
|
|
source.use { inStream ->
|
|
|
|
IOUtils.copy(inStream, outStream)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return FileProvider.getUriForFile(this, App1.FILE_PROVIDER_AUTHORITY, dst)
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun sweepOldCache() {
|
|
|
|
// sweep old cache
|
|
|
|
try {
|
|
|
|
// prepare cache directory
|
|
|
|
val cache_dir = cacheDir
|
|
|
|
|
|
|
|
cache_dir.mkdirs()
|
|
|
|
|
|
|
|
val now = System.currentTimeMillis()
|
2019-09-12 15:43:11 +02:00
|
|
|
val files = cache_dir.listFiles()
|
|
|
|
if(files != null) for(f in files) {
|
2018-01-04 19:52:25 +01:00
|
|
|
try {
|
|
|
|
if(f.isFile
|
|
|
|
&& f.name.startsWith("img.")
|
|
|
|
&& now - f.lastModified() >= 86400000L) {
|
|
|
|
|
|
|
|
f.delete()
|
|
|
|
}
|
|
|
|
} catch(ex : Throwable) {
|
|
|
|
log.trace(ex)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
} catch(ex : Throwable) {
|
|
|
|
log.trace(ex)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|