2018-01-04 19:52:25 +01:00
|
|
|
package jp.juggler.subwaytooter
|
|
|
|
|
|
|
|
import android.annotation.SuppressLint
|
|
|
|
import android.content.Intent
|
|
|
|
import android.net.Uri
|
|
|
|
import android.os.AsyncTask
|
|
|
|
import android.os.Bundle
|
|
|
|
import android.util.JsonWriter
|
|
|
|
import android.view.View
|
|
|
|
import android.view.ViewGroup
|
2018-12-03 09:07:07 +01:00
|
|
|
import android.widget.AdapterView
|
|
|
|
import android.widget.BaseAdapter
|
|
|
|
import android.widget.ListView
|
|
|
|
import android.widget.TextView
|
2019-08-25 10:28:16 +02:00
|
|
|
import androidx.appcompat.app.AlertDialog
|
|
|
|
import androidx.appcompat.app.AppCompatActivity
|
|
|
|
import androidx.core.content.FileProvider
|
2018-01-13 07:38:32 +01:00
|
|
|
import jp.juggler.subwaytooter.dialog.ProgressDialogEx
|
2018-12-01 00:02:18 +01:00
|
|
|
import jp.juggler.util.*
|
2018-01-04 19:52:25 +01:00
|
|
|
import java.io.File
|
|
|
|
import java.io.FileOutputStream
|
2018-09-20 18:41:04 +02:00
|
|
|
import java.io.OutputStreamWriter
|
|
|
|
import java.util.zip.ZipEntry
|
|
|
|
import java.util.zip.ZipOutputStream
|
2018-01-04 19:52:25 +01:00
|
|
|
|
2018-12-03 09:07:07 +01:00
|
|
|
class ActAppSetting : AppCompatActivity() {
|
2018-01-04 19:52:25 +01:00
|
|
|
|
|
|
|
companion object {
|
|
|
|
internal val log = LogCategory("ActAppSetting")
|
|
|
|
|
|
|
|
fun open(activity : ActMain, request_code : Int) {
|
2018-05-18 22:48:29 +02:00
|
|
|
activity.startActivityForResult(
|
|
|
|
Intent(activity, ActAppSetting::class.java),
|
|
|
|
request_code
|
|
|
|
)
|
2018-01-04 19:52:25 +01:00
|
|
|
}
|
|
|
|
|
2018-12-03 09:07:07 +01:00
|
|
|
// 他の設定子画面と重複しない値にすること
|
|
|
|
private const val REQUEST_CODE_OTHER = 0
|
|
|
|
private const val REQUEST_CODE_APP_DATA_IMPORT = 1
|
2018-01-04 19:52:25 +01:00
|
|
|
}
|
|
|
|
|
2018-12-03 09:07:07 +01:00
|
|
|
private lateinit var lvList : ListView
|
2018-01-04 19:52:25 +01:00
|
|
|
|
|
|
|
override fun onCreate(savedInstanceState : Bundle?) {
|
|
|
|
super.onCreate(savedInstanceState)
|
|
|
|
App1.setActivityTheme(this, false)
|
|
|
|
|
|
|
|
setContentView(R.layout.act_app_setting)
|
2019-08-31 16:33:13 +02:00
|
|
|
App1.initEdgeToEdge(this)
|
2018-01-04 19:52:25 +01:00
|
|
|
|
2018-12-03 09:07:07 +01:00
|
|
|
Styler.fixHorizontalPadding2(findViewById(R.id.llContent))
|
|
|
|
lvList = findViewById(R.id.lvList)
|
2018-01-04 19:52:25 +01:00
|
|
|
|
2018-12-03 09:07:07 +01:00
|
|
|
val adapter = MyAdapter()
|
|
|
|
lvList.adapter = adapter
|
|
|
|
lvList.onItemClickListener = adapter
|
2018-01-04 19:52:25 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onActivityResult(requestCode : Int, resultCode : Int, data : Intent?) {
|
2018-12-03 09:07:07 +01:00
|
|
|
if(resultCode == RESULT_OK && data != null && requestCode == REQUEST_CODE_APP_DATA_IMPORT) {
|
2018-11-28 20:57:50 +01:00
|
|
|
data.handleGetContentResult(contentResolver).firstOrNull()?.uri?.let {
|
|
|
|
importAppData(false, it)
|
2018-09-07 07:51:59 +02:00
|
|
|
}
|
2018-01-04 19:52:25 +01:00
|
|
|
}
|
|
|
|
super.onActivityResult(requestCode, resultCode, data)
|
|
|
|
}
|
2018-12-03 09:07:07 +01:00
|
|
|
///////////////////////////////////////////////////////////////
|
2018-01-04 19:52:25 +01:00
|
|
|
|
2018-12-03 09:07:07 +01:00
|
|
|
class Item(
|
|
|
|
val titleId : Int,
|
|
|
|
val descId : Int? = null,
|
|
|
|
val block : (Item) -> Unit
|
|
|
|
)
|
2018-01-04 19:52:25 +01:00
|
|
|
|
2018-12-03 09:07:07 +01:00
|
|
|
inner class MyAdapter : BaseAdapter(), AdapterView.OnItemClickListener {
|
|
|
|
|
2019-08-25 10:28:16 +02:00
|
|
|
private val items = arrayOf(
|
2018-11-19 23:46:14 +01:00
|
|
|
|
2019-08-25 10:28:16 +02:00
|
|
|
Item(R.string.notifications) {
|
2018-12-03 09:07:07 +01:00
|
|
|
openChild(it, R.layout.act_app_setting_notifications)
|
|
|
|
},
|
2018-11-19 23:46:14 +01:00
|
|
|
|
2019-08-25 10:28:16 +02:00
|
|
|
Item(R.string.behavior) {
|
2018-12-03 09:07:07 +01:00
|
|
|
openChild(it, R.layout.act_app_setting_behavior)
|
|
|
|
},
|
2018-11-19 23:46:14 +01:00
|
|
|
|
2019-08-25 10:28:16 +02:00
|
|
|
Item(R.string.post) {
|
2018-12-03 09:07:07 +01:00
|
|
|
openChild(it, R.layout.act_app_setting_post)
|
|
|
|
},
|
2018-11-19 23:46:14 +01:00
|
|
|
|
2019-08-25 10:28:16 +02:00
|
|
|
Item(R.string.tablet_mode) {
|
2018-12-03 09:07:07 +01:00
|
|
|
openChild(it, R.layout.act_app_setting_tablet)
|
|
|
|
},
|
2019-08-25 10:28:16 +02:00
|
|
|
|
|
|
|
Item(R.string.media_attachment) {
|
2018-12-03 09:07:07 +01:00
|
|
|
openChild(it, R.layout.act_app_setting_media_attachment)
|
|
|
|
},
|
2018-11-19 23:46:14 +01:00
|
|
|
|
2019-08-25 10:28:16 +02:00
|
|
|
Item(R.string.animation) {
|
2018-12-03 10:27:06 +01:00
|
|
|
openChild(it, R.layout.act_app_setting_animation)
|
2018-12-03 09:07:07 +01:00
|
|
|
},
|
2019-08-25 10:28:16 +02:00
|
|
|
|
|
|
|
Item(R.string.appearance) {
|
2018-12-03 09:07:07 +01:00
|
|
|
openChild(it, R.layout.act_app_setting_appearance)
|
|
|
|
},
|
2019-08-25 10:28:16 +02:00
|
|
|
|
|
|
|
Item(R.string.color) {
|
2018-12-03 09:07:07 +01:00
|
|
|
openChild(it, R.layout.act_app_setting_color)
|
|
|
|
},
|
2019-08-25 10:28:16 +02:00
|
|
|
|
|
|
|
Item(R.string.performance) {
|
2018-12-03 09:07:07 +01:00
|
|
|
openChild(it, R.layout.act_app_setting_performance)
|
|
|
|
},
|
2019-08-25 10:28:16 +02:00
|
|
|
|
|
|
|
Item(R.string.app_data_export) {
|
2018-12-03 09:07:07 +01:00
|
|
|
exportAppData()
|
|
|
|
},
|
2019-08-25 10:28:16 +02:00
|
|
|
Item(R.string.app_data_import, R.string.app_data_import_desc) {
|
2018-12-03 09:07:07 +01:00
|
|
|
importAppData()
|
2018-11-19 23:46:14 +01:00
|
|
|
}
|
2018-12-03 09:07:07 +01:00
|
|
|
)
|
2018-01-04 19:52:25 +01:00
|
|
|
|
2018-12-03 09:07:07 +01:00
|
|
|
override fun getCount() : Int = items.size
|
2018-01-04 19:52:25 +01:00
|
|
|
|
2018-12-03 09:07:07 +01:00
|
|
|
override fun getItemId(position : Int) : Long = items[position].titleId.toLong()
|
2018-01-04 19:52:25 +01:00
|
|
|
|
2018-12-03 09:07:07 +01:00
|
|
|
override fun getItem(position : Int) : Any = items[position]
|
2018-01-04 19:52:25 +01:00
|
|
|
|
2018-12-03 09:07:07 +01:00
|
|
|
override fun onItemClick(
|
|
|
|
parent : AdapterView<*>?,
|
|
|
|
view : View?,
|
|
|
|
position : Int,
|
|
|
|
id : Long
|
|
|
|
) {
|
|
|
|
items[position].let { it.block(it) }
|
2018-01-04 19:52:25 +01:00
|
|
|
}
|
|
|
|
|
2018-12-03 09:07:07 +01:00
|
|
|
override fun getView(position : Int, convertView : View?, parent : ViewGroup?) : View {
|
|
|
|
val view : View
|
|
|
|
val holder : ViewHolder
|
|
|
|
if(convertView == null) {
|
|
|
|
view = layoutInflater.inflate(R.layout.lv_app_setting, parent, false)
|
|
|
|
holder = ViewHolder(view)
|
|
|
|
view.tag = holder
|
|
|
|
} else {
|
|
|
|
view = convertView
|
|
|
|
holder = view.tag as ViewHolder
|
|
|
|
}
|
|
|
|
holder.bind(items[position])
|
|
|
|
return view
|
2018-01-04 19:52:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-03 09:07:07 +01:00
|
|
|
inner class ViewHolder(viewRoot : View) {
|
|
|
|
private val tvTitle : TextView = viewRoot.findViewById(R.id.tvTitle)
|
|
|
|
private val tvDesc : TextView = viewRoot.findViewById(R.id.tvDesc)
|
2018-01-04 19:52:25 +01:00
|
|
|
|
2018-12-03 09:07:07 +01:00
|
|
|
fun bind(item : Item) {
|
|
|
|
tvTitle.setText(item.titleId)
|
|
|
|
vg(tvDesc, item.descId != null)
|
|
|
|
item.descId?.let { tvDesc.setText(it) }
|
2018-01-04 19:52:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-03 09:07:07 +01:00
|
|
|
///////////////////////////////////////////////////////////////
|
2018-01-04 19:52:25 +01:00
|
|
|
|
2018-12-03 09:07:07 +01:00
|
|
|
private fun openChild(item : Item, layoutId : Int) {
|
|
|
|
ActAppSettingChild.open(this, REQUEST_CODE_OTHER, layoutId, item.titleId)
|
2018-01-04 19:52:25 +01:00
|
|
|
}
|
|
|
|
|
2018-12-03 09:07:07 +01:00
|
|
|
///////////////////////////////////////////////////////////////
|
2018-01-04 19:52:25 +01:00
|
|
|
|
|
|
|
private fun exportAppData() {
|
|
|
|
|
|
|
|
@Suppress("DEPRECATION")
|
2018-01-13 07:38:32 +01:00
|
|
|
val progress = ProgressDialogEx(this)
|
2018-01-04 19:52:25 +01:00
|
|
|
|
|
|
|
val task = @SuppressLint("StaticFieldLeak")
|
2018-01-10 16:47:35 +01:00
|
|
|
object : AsyncTask<Void, String, File?>() {
|
2018-01-04 19:52:25 +01:00
|
|
|
|
|
|
|
override fun doInBackground(vararg params : Void) : File? {
|
2019-08-25 10:04:34 +02:00
|
|
|
|
2018-01-04 19:52:25 +01:00
|
|
|
try {
|
|
|
|
val cache_dir = cacheDir
|
|
|
|
cache_dir.mkdir()
|
|
|
|
|
2018-05-18 22:48:29 +02:00
|
|
|
val file = File(
|
|
|
|
cache_dir,
|
2018-09-20 18:41:04 +02:00
|
|
|
"SubwayTooter.${android.os.Process.myPid()}.${android.os.Process.myTid()}.zip"
|
2018-05-18 22:48:29 +02:00
|
|
|
)
|
2018-09-20 18:41:04 +02:00
|
|
|
|
|
|
|
// ZipOutputStreamオブジェクトの作成
|
2018-11-19 23:46:14 +01:00
|
|
|
ZipOutputStream(FileOutputStream(file)).use { zipStream ->
|
2018-09-20 18:41:04 +02:00
|
|
|
|
|
|
|
// アプリデータjson
|
|
|
|
zipStream.putNextEntry(ZipEntry("AppData.json"))
|
|
|
|
try {
|
|
|
|
val jw = JsonWriter(OutputStreamWriter(zipStream, "UTF-8"))
|
|
|
|
AppDataExporter.encodeAppData(this@ActAppSetting, jw)
|
|
|
|
jw.flush()
|
2018-11-19 23:46:14 +01:00
|
|
|
} finally {
|
2018-09-20 18:41:04 +02:00
|
|
|
zipStream.closeEntry()
|
|
|
|
}
|
2018-11-19 23:46:14 +01:00
|
|
|
|
2018-09-20 18:41:04 +02:00
|
|
|
// カラム背景画像
|
|
|
|
val appState = App1.getAppState(this@ActAppSetting)
|
|
|
|
for(column in appState.column_list) {
|
2018-11-19 23:46:14 +01:00
|
|
|
AppDataExporter.saveBackgroundImage(
|
|
|
|
this@ActAppSetting,
|
|
|
|
zipStream,
|
|
|
|
column
|
|
|
|
)
|
2018-09-20 18:41:04 +02:00
|
|
|
}
|
2018-01-04 19:52:25 +01:00
|
|
|
}
|
2018-11-19 23:46:14 +01:00
|
|
|
|
2018-01-04 19:52:25 +01:00
|
|
|
return file
|
|
|
|
} catch(ex : Throwable) {
|
|
|
|
log.trace(ex)
|
2018-01-21 13:46:36 +01:00
|
|
|
showToast(this@ActAppSetting, ex, "exportAppData failed.")
|
2018-01-04 19:52:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return null
|
|
|
|
}
|
|
|
|
|
2018-01-10 16:47:35 +01:00
|
|
|
override fun onCancelled(result : File?) {
|
|
|
|
onPostExecute(result)
|
2018-01-04 19:52:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
override fun onPostExecute(result : File?) {
|
2019-01-19 03:36:40 +01:00
|
|
|
progress.dismissSafe()
|
2018-01-04 19:52:25 +01:00
|
|
|
|
|
|
|
if(isCancelled || result == null) {
|
|
|
|
// cancelled.
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
2018-05-18 22:48:29 +02:00
|
|
|
val uri = FileProvider.getUriForFile(
|
|
|
|
this@ActAppSetting,
|
|
|
|
App1.FILE_PROVIDER_AUTHORITY,
|
|
|
|
result
|
|
|
|
)
|
2018-01-04 19:52:25 +01:00
|
|
|
val intent = Intent(Intent.ACTION_SEND)
|
|
|
|
intent.type = contentResolver.getType(uri)
|
|
|
|
intent.putExtra(Intent.EXTRA_SUBJECT, "SubwayTooter app data")
|
|
|
|
intent.putExtra(Intent.EXTRA_STREAM, uri)
|
|
|
|
|
|
|
|
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION or Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
2018-12-03 09:07:07 +01:00
|
|
|
startActivityForResult(intent, REQUEST_CODE_OTHER)
|
2018-01-04 19:52:25 +01:00
|
|
|
} catch(ex : Throwable) {
|
|
|
|
log.trace(ex)
|
2018-01-21 13:46:36 +01:00
|
|
|
showToast(this@ActAppSetting, ex, "exportAppData failed.")
|
2018-01-04 19:52:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-12 15:43:11 +02:00
|
|
|
progress.isIndeterminateEx = true
|
2018-01-04 19:52:25 +01:00
|
|
|
progress.setCancelable(true)
|
|
|
|
progress.setOnCancelListener { task.cancel(true) }
|
|
|
|
progress.show()
|
|
|
|
task.executeOnExecutor(App1.task_executor)
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun importAppData() {
|
|
|
|
try {
|
2018-09-07 07:51:59 +02:00
|
|
|
val intent = intentOpenDocument("*/*")
|
2018-01-04 19:52:25 +01:00
|
|
|
startActivityForResult(intent, REQUEST_CODE_APP_DATA_IMPORT)
|
|
|
|
} catch(ex : Throwable) {
|
2018-01-21 13:46:36 +01:00
|
|
|
showToast(this, ex, "importAppData(1) failed.")
|
2018-01-04 19:52:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun importAppData(bConfirm : Boolean, uri : Uri) {
|
|
|
|
|
|
|
|
val type = contentResolver.getType(uri)
|
|
|
|
log.d("importAppData type=%s", type)
|
|
|
|
|
|
|
|
if(! bConfirm) {
|
|
|
|
AlertDialog.Builder(this)
|
|
|
|
.setMessage(getString(R.string.app_data_import_confirm))
|
|
|
|
.setNegativeButton(R.string.cancel, null)
|
|
|
|
.setPositiveButton(R.string.ok) { _, _ -> importAppData(true, uri) }
|
|
|
|
.show()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
val data = Intent()
|
|
|
|
data.data = uri
|
|
|
|
setResult(ActMain.RESULT_APP_DATA_IMPORT, data)
|
|
|
|
finish()
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|