Fix some crashes when restoring backups
This commit is contained in:
parent
5ecdecea98
commit
eb662f1234
5 changed files with 51 additions and 22 deletions
|
@ -125,7 +125,7 @@ dependencies {
|
||||||
compile "com.squareup.retrofit2:adapter-rxjava:$RETROFIT_VERSION"
|
compile "com.squareup.retrofit2:adapter-rxjava:$RETROFIT_VERSION"
|
||||||
|
|
||||||
// IO
|
// IO
|
||||||
compile 'com.squareup.okio:okio:1.6.0'
|
compile 'com.squareup.okio:okio:1.7.0'
|
||||||
|
|
||||||
// JSON
|
// JSON
|
||||||
compile 'com.google.code.gson:gson:2.6.2'
|
compile 'com.google.code.gson:gson:2.6.2'
|
||||||
|
|
|
@ -14,6 +14,11 @@ import eu.kanade.tachiyomi.ui.base.fragment.BaseRxFragment
|
||||||
import eu.kanade.tachiyomi.util.toast
|
import eu.kanade.tachiyomi.util.toast
|
||||||
import kotlinx.android.synthetic.main.fragment_backup.*
|
import kotlinx.android.synthetic.main.fragment_backup.*
|
||||||
import nucleus.factory.RequiresPresenter
|
import nucleus.factory.RequiresPresenter
|
||||||
|
import rx.Observable
|
||||||
|
import rx.android.schedulers.AndroidSchedulers
|
||||||
|
import rx.internal.util.SubscriptionList
|
||||||
|
import rx.schedulers.Schedulers
|
||||||
|
import timber.log.Timber
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
@ -28,11 +33,16 @@ class BackupFragment : BaseRxFragment<BackupPresenter>() {
|
||||||
private var backupDialog: Dialog? = null
|
private var backupDialog: Dialog? = null
|
||||||
private var restoreDialog: Dialog? = null
|
private var restoreDialog: Dialog? = null
|
||||||
|
|
||||||
|
private lateinit var subscriptions: SubscriptionList
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedState: Bundle?): View {
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedState: Bundle?): View {
|
||||||
return inflater.inflate(R.layout.fragment_backup, container, false)
|
return inflater.inflate(R.layout.fragment_backup, container, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedState: Bundle?) {
|
override fun onViewCreated(view: View, savedState: Bundle?) {
|
||||||
|
baseActivity.requestPermissionsOnMarshmallow()
|
||||||
|
subscriptions = SubscriptionList()
|
||||||
|
|
||||||
backup_button.setOnClickListener {
|
backup_button.setOnClickListener {
|
||||||
val today = SimpleDateFormat("yyyy-MM-dd").format(Date())
|
val today = SimpleDateFormat("yyyy-MM-dd").format(Date())
|
||||||
val file = File(activity.externalCacheDir, "tachiyomi-$today.json")
|
val file = File(activity.externalCacheDir, "tachiyomi-$today.json")
|
||||||
|
@ -48,11 +58,16 @@ class BackupFragment : BaseRxFragment<BackupPresenter>() {
|
||||||
val intent = Intent(Intent.ACTION_GET_CONTENT)
|
val intent = Intent(Intent.ACTION_GET_CONTENT)
|
||||||
intent.addCategory(Intent.CATEGORY_OPENABLE)
|
intent.addCategory(Intent.CATEGORY_OPENABLE)
|
||||||
intent.type = "application/octet-stream"
|
intent.type = "application/octet-stream"
|
||||||
val chooser = Intent.createChooser(intent, getString(R.string.file_select_cover))
|
val chooser = Intent.createChooser(intent, getString(R.string.file_select_backup))
|
||||||
startActivityForResult(chooser, REQUEST_BACKUP_OPEN)
|
startActivityForResult(chooser, REQUEST_BACKUP_OPEN)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
subscriptions.unsubscribe()
|
||||||
|
super.onDestroyView()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called from the presenter when the backup is completed.
|
* Called from the presenter when the backup is completed.
|
||||||
*
|
*
|
||||||
|
@ -99,8 +114,18 @@ class BackupFragment : BaseRxFragment<BackupPresenter>() {
|
||||||
.progress(true, 0)
|
.progress(true, 0)
|
||||||
.show()
|
.show()
|
||||||
|
|
||||||
val stream = context.contentResolver.openInputStream(data.data)
|
// When using cloud services, we have to open the input stream in a background thread.
|
||||||
presenter.restoreBackup(stream)
|
Observable.fromCallable { context.contentResolver.openInputStream(data.data) }
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe({
|
||||||
|
presenter.restoreBackup(it)
|
||||||
|
}, {
|
||||||
|
context.toast(it.message)
|
||||||
|
Timber.e(it, it.message)
|
||||||
|
})
|
||||||
|
.apply { subscriptions.add(this) }
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
package eu.kanade.tachiyomi.ui.base.activity
|
package eu.kanade.tachiyomi.ui.base.activity
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
|
import android.content.pm.PackageManager
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
|
import android.os.Build
|
||||||
import android.support.design.widget.Snackbar
|
import android.support.design.widget.Snackbar
|
||||||
|
import android.support.v4.app.ActivityCompat
|
||||||
|
import android.support.v4.content.ContextCompat
|
||||||
import android.support.v7.app.AppCompatActivity
|
import android.support.v7.app.AppCompatActivity
|
||||||
import android.support.v7.widget.Toolbar
|
import android.support.v7.widget.Toolbar
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
@ -42,6 +47,22 @@ open class BaseActivity : AppCompatActivity() {
|
||||||
supportActionBar?.subtitle = getString(titleResource)
|
supportActionBar?.subtitle = getString(titleResource)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests read and write permissions on Android M and higher.
|
||||||
|
*/
|
||||||
|
fun requestPermissionsOnMarshmallow() {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
if (ContextCompat.checkSelfPermission(this,
|
||||||
|
Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
|
||||||
|
|
||||||
|
ActivityCompat.requestPermissions(this,
|
||||||
|
arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE),
|
||||||
|
1)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected val app: App
|
protected val app: App
|
||||||
get() = App.get(this)
|
get() = App.get(this)
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,11 @@
|
||||||
package eu.kanade.tachiyomi.ui.manga
|
package eu.kanade.tachiyomi.ui.manga
|
||||||
|
|
||||||
import android.Manifest
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
|
||||||
import android.os.Build
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.support.v4.app.ActivityCompat
|
|
||||||
import android.support.v4.app.Fragment
|
import android.support.v4.app.Fragment
|
||||||
import android.support.v4.app.FragmentManager
|
import android.support.v4.app.FragmentManager
|
||||||
import android.support.v4.app.FragmentPagerAdapter
|
import android.support.v4.app.FragmentPagerAdapter
|
||||||
import android.support.v4.content.ContextCompat
|
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
import eu.kanade.tachiyomi.event.MangaEvent
|
import eu.kanade.tachiyomi.event.MangaEvent
|
||||||
|
@ -69,19 +64,6 @@ class MangaActivity : BaseRxActivity<MangaPresenter>() {
|
||||||
setToolbarTitle(manga.title)
|
setToolbarTitle(manga.title)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun requestPermissionsOnMarshmallow() {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
||||||
if (ContextCompat.checkSelfPermission(this,
|
|
||||||
Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
|
|
||||||
|
|
||||||
ActivityCompat.requestPermissions(this,
|
|
||||||
arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE),
|
|
||||||
1)
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class MangaDetailAdapter(fm: FragmentManager, activity: MangaActivity) : FragmentPagerAdapter(fm) {
|
internal class MangaDetailAdapter(fm: FragmentManager, activity: MangaActivity) : FragmentPagerAdapter(fm) {
|
||||||
|
|
||||||
private var pageCount: Int = 0
|
private var pageCount: Int = 0
|
||||||
|
|
|
@ -265,6 +265,7 @@
|
||||||
|
|
||||||
<!-- File Picker Titles -->
|
<!-- File Picker Titles -->
|
||||||
<string name="file_select_cover">Select cover image</string>
|
<string name="file_select_cover">Select cover image</string>
|
||||||
|
<string name="file_select_backup">Select backup file</string>
|
||||||
|
|
||||||
<!--UpdateCheck-->
|
<!--UpdateCheck-->
|
||||||
<string name="update_check_title">New update available!</string>
|
<string name="update_check_title">New update available!</string>
|
||||||
|
|
Reference in a new issue