カラム背景画像の保存フォルダにgetExternalFilesDirを使う。回転が必要な画像や画面の長辺の1.5倍以上の画像は変換する。

This commit is contained in:
tateisu 2018-09-07 20:34:54 +09:00
parent bd03761042
commit b5a6712402
3 changed files with 110 additions and 28 deletions

View File

@ -1,6 +1,5 @@
package jp.juggler.subwaytooter
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.net.Uri
@ -18,6 +17,10 @@ import android.widget.TextView
import com.jrummyapps.android.colorpicker.ColorPickerDialog
import com.jrummyapps.android.colorpicker.ColorPickerDialogListener
import jp.juggler.subwaytooter.api.TootApiClient
import jp.juggler.subwaytooter.api.TootApiResult
import jp.juggler.subwaytooter.api.TootTask
import jp.juggler.subwaytooter.api.TootTaskRunner
import jp.juggler.subwaytooter.util.*
import org.apache.commons.io.IOUtils
import java.io.File
@ -25,6 +28,7 @@ import java.io.FileOutputStream
import java.text.NumberFormat
import java.util.Locale
import kotlin.math.max
class ActColumnCustomize : AppCompatActivity(), View.OnClickListener, ColorPickerDialogListener {
@ -183,7 +187,7 @@ class ActColumnCustomize : AppCompatActivity(), View.OnClickListener, ColorPicke
}
R.id.btnColumnBackgroundImage -> {
val intent = intentOpenDocument("image/*")
val intent = intentGetContent(false, getString(R.string.pick_image), "image/*")
startActivityForResult(intent, REQUEST_CODE_PICK_BACKGROUND)
}
@ -221,24 +225,76 @@ class ActColumnCustomize : AppCompatActivity(), View.OnClickListener, ColorPicke
override fun onActivityResult(requestCode : Int, resultCode : Int, data : Intent?) {
if(requestCode == REQUEST_CODE_PICK_BACKGROUND && data != null && resultCode == RESULT_OK) {
data.handleGetContentResult(contentResolver).firstOrNull()?.let { pair->
try{
val backgroundDir = getDir(Column.DIR_BACKGROUND_IMAGE, Context.MODE_PRIVATE)
val file = File(backgroundDir,column.column_id)
FileOutputStream(file).use{ outStream->
contentResolver.openInputStream(pair.first).use{ inStream->
IOUtils.copy(inStream,outStream)
}
}
column.column_bg_image = Uri.fromFile(file).toString()
show()
}catch(ex:Throwable){
showToast(this@ActColumnCustomize,true,ex.withCaption("can't update background image."))
}
data.handleGetContentResult(contentResolver).firstOrNull()?.let { pair ->
updateBackground(pair.first)
}
}
}
private fun updateBackground(uriArg : Uri) {
TootTaskRunner(this).run(object : TootTask {
override fun background(client : TootApiClient) : TootApiResult? {
try {
val backgroundDir = Column.getBackgroundImageDir(this@ActColumnCustomize)
val file =
File(backgroundDir, "${column.column_id}:${System.currentTimeMillis()}")
val fileUri = Uri.fromFile(file)
client.publishApiProgress("loading image from ${uriArg}")
contentResolver.openInputStream(uriArg).use { inStream ->
FileOutputStream(file).use { outStream ->
IOUtils.copy(inStream, outStream)
}
}
// リサイズや回転が必要ならする
client.publishApiProgress("check resize/rotation…")
val size = (max(
resources.displayMetrics.widthPixels,
resources.displayMetrics.heightPixels
) * 1.5f ).toInt()
val bitmap = createResizedBitmap(
this@ActColumnCustomize,
fileUri,
size,
skipIfNoNeedToResizeAndRotate = true
)
if(bitmap != null) {
try {
client.publishApiProgress("save resized(${bitmap.width}x${bitmap.height}) image to ${file}")
FileOutputStream(file).use { os ->
bitmap.compress(Bitmap.CompressFormat.PNG, 100, os)
}
}finally{
bitmap.recycle()
}
}
val result = TootApiResult()
result.data = fileUri.toString()
return result
} catch(ex : Throwable) {
log.trace(ex)
return TootApiResult(ex.withCaption("can't update background image."))
}
}
override fun handleResult(result : TootApiResult?) {
when {
result == null -> return
result.error != null -> showToast(this@ActColumnCustomize, true, result.error)
else -> {
column.column_bg_image = result.data as String
show()
}
}
}
})
}
private fun initUI() {
setContentView(R.layout.act_column_customize)
@ -443,7 +499,7 @@ class ActColumnCustomize : AppCompatActivity(), View.OnClickListener, ColorPicke
// 画像をロードして、成功したら表示してURLを覚える
val resize_max = (0.5f + 64f * density).toInt()
val uri = Uri.parse(url)
last_image_bitmap = createResizedBitmap( this, uri, resize_max )
last_image_bitmap = createResizedBitmap(this, uri, resize_max)
if(last_image_bitmap != null) {
ivColumnBackground.setImageBitmap(last_image_bitmap)
last_image_uri = url

View File

@ -225,7 +225,7 @@ class AppState(internal val context : Context, internal val pref : SharedPrefere
}
internal fun restartTTS() {
fun restartTTS() {
log.d("restart TextToSpeech")
tts?.shutdown()
tts = null
@ -280,11 +280,13 @@ class AppState(internal val context : Context, internal val pref : SharedPrefere
enableSpeech()
// 背景フォルダの掃除
val backgroundDir = context.getDir(Column.DIR_BACKGROUND_IMAGE,Context.MODE_PRIVATE)
backgroundDir.list().forEach {name->
val file = File(backgroundDir,name)
val backgroundImageDir = Column.getBackgroundImageDir(context)
backgroundImageDir.list().forEach {name->
val file = File(backgroundImageDir,name)
if( file.isFile ){
val column = Column.findColumnById( name )
val delm = name.indexOf(':')
val id = if(delm!=-1) name.substring(0, delm) else name
val column = Column.findColumnById( id )
if( column == null) file.delete()
}
}
@ -330,7 +332,7 @@ class AppState(internal val context : Context, internal val pref : SharedPrefere
log.d("initializing TextToSpeech…")
object : AsyncTask<Void, Void, TextToSpeech?>() {
internal var tmp_tts : TextToSpeech? = null
var tmp_tts : TextToSpeech? = null
override fun doInBackground(vararg params : Void) : TextToSpeech {
val tts = TextToSpeech(context, tts_init_listener)
@ -338,7 +340,7 @@ class AppState(internal val context : Context, internal val pref : SharedPrefere
return tts
}
internal val tts_init_listener : TextToSpeech.OnInitListener =
val tts_init_listener : TextToSpeech.OnInitListener =
TextToSpeech.OnInitListener { status ->
val tts = this.tmp_tts

View File

@ -4,6 +4,7 @@ import android.annotation.SuppressLint
import android.content.Context
import android.net.Uri
import android.os.AsyncTask
import android.os.Environment
import android.os.SystemClock
import android.view.Gravity
import jp.juggler.subwaytooter.api.*
@ -13,6 +14,7 @@ import jp.juggler.subwaytooter.util.*
import org.json.JSONArray
import org.json.JSONException
import org.json.JSONObject
import java.io.File
import java.lang.ref.WeakReference
import java.nio.ByteBuffer
import java.text.SimpleDateFormat
@ -55,7 +57,7 @@ class Column(
companion object {
private val log = LogCategory("Column")
const val DIR_BACKGROUND_IMAGE = "columnBackground"
private const val DIR_BACKGROUND_IMAGE = "columnBackground"
private const val READ_LIMIT = 80 // API側の上限が80です。ただし指定しても40しか返ってこないことが多い
private const val LOOP_TIMEOUT = 10000L
@ -403,6 +405,28 @@ class Column(
return columnIdMap[id]?.get()
}
}
fun getBackgroundImageDir(context : Context) : File {
val externalDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES)
if( externalDir == null) {
log.e("getExternalFilesDir is null.")
}else{
val state = Environment.getExternalStorageState()
if( state != Environment.MEDIA_MOUNTED ){
log.e("getExternalStorageState: ${state}")
}else {
log.i("externalDir: ${externalDir}")
externalDir.mkdir()
val backgroundDir = File(externalDir,DIR_BACKGROUND_IMAGE)
backgroundDir.mkdir()
log.i("backgroundDir: ${backgroundDir} exists=${backgroundDir.exists()}")
return backgroundDir
}
}
val backgroundDir = context.getDir(Column.DIR_BACKGROUND_IMAGE,Context.MODE_PRIVATE)
log.i("backgroundDir: ${backgroundDir} exists=${backgroundDir.exists()}")
return backgroundDir
}
}
private var callback_ref : WeakReference<Callback>? = null
@ -2196,15 +2220,15 @@ class Column(
TYPE_DOMAIN_BLOCKS -> return parseDomainList(client, PATH_DOMAIN_BLOCK)
TYPE_LIST_LIST -> if(isMisskey){
TYPE_LIST_LIST -> return if(isMisskey){
val params = makeMisskeyBaseParameter(parser)
return parseListList(
parseListList(
client,
"/api/users/lists/list",
misskeyParams = params
)
}else{
return parseListList(client, PATH_LIST_LIST)
parseListList(client, PATH_LIST_LIST)
}