diff --git a/app/build.gradle b/app/build.gradle
index d5bb3a07..aef7c858 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -19,8 +19,8 @@ android {
applicationId "xyz.quaver.pupil"
minSdkVersion 16
targetSdkVersion 29
- versionCode 48
- versionName "4.12"
+ versionCode 49
+ versionName "4.13"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true
vectorDrawables.useSupportLibrary = true
@@ -35,9 +35,6 @@ android {
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
release {
- minifyEnabled true
- shrinkResources true
-
buildConfigField('Boolean', 'CENSOR', 'false')
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
diff --git a/app/release/output.json b/app/release/output.json
index 96e20465..1a1b13cc 100644
--- a/app/release/output.json
+++ b/app/release/output.json
@@ -1 +1 @@
-[{"outputType":{"type":"APK"},"apkData":{"type":"MAIN","splits":[],"versionCode":48,"versionName":"4.12","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release","dirName":""},"path":"app-release.apk","properties":{}}]
\ No newline at end of file
+[{"outputType":{"type":"APK"},"apkData":{"type":"MAIN","splits":[],"versionCode":49,"versionName":"4.13","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release","dirName":""},"path":"app-release.apk","properties":{}}]
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index addcb73f..b61f152c 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -8,6 +8,7 @@
+
+ android:requestLegacyExternalStorage="true"
+ tools:ignore="UnusedAttribute">
+
+
+
+
+
+
.
+ */
+
+package xyz.quaver.pupil
+
+import android.app.DownloadManager
+import android.app.PendingIntent
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.net.Uri
+import android.webkit.MimeTypeMap
+import androidx.core.app.NotificationCompat
+import androidx.core.app.NotificationManagerCompat
+import androidx.core.content.FileProvider
+import androidx.preference.PreferenceManager
+import xyz.quaver.pupil.util.NOTIFICATION_ID_UPDATE
+import java.io.File
+
+class BroadcastReciever : BroadcastReceiver() {
+
+ override fun onReceive(context: Context?, intent: Intent?) {
+ context ?: return
+
+ when (intent?.action) {
+ DownloadManager.ACTION_DOWNLOAD_COMPLETE -> {
+
+ // Validate download
+
+ val preference = PreferenceManager.getDefaultSharedPreferences(context)
+ val downloadID = preference.getLong("update_download_id", -1)
+ val downloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
+
+ if (intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1) != downloadID)
+ return
+
+ // Get target uri
+
+ val query = DownloadManager.Query()
+ .setFilterById(downloadID)
+
+ val uri = downloadManager.query(query).use { cursor ->
+ cursor.moveToFirst()
+
+ cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI)).let {
+ val uri = Uri.parse(it)
+
+ when (uri.scheme) {
+ "file" ->
+ FileProvider.getUriForFile(context, context.applicationContext.packageName + ".provider", File(uri.path!!))
+ "content" -> uri
+ else -> return
+ }
+ }
+ }
+
+ // Build Notification
+
+ val notificationManager = NotificationManagerCompat.from(context)
+
+ val pendingIntent = PendingIntent.getActivity(context, 0, Intent(Intent.ACTION_VIEW).apply {
+ flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK
+ setDataAndType(uri, MimeTypeMap.getSingleton().getMimeTypeFromExtension("apk"))
+ }, 0)
+
+ val notification = NotificationCompat.Builder(context, "update")
+ .setSmallIcon(android.R.drawable.stat_sys_download_done)
+ .setContentTitle(context.getText(R.string.update_download_completed))
+ .setContentText(context.getText(R.string.update_download_completed_description))
+ .setContentIntent(pendingIntent)
+ .build()
+
+ notificationManager.notify(NOTIFICATION_ID_UPDATE, notification)
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/xyz/quaver/pupil/Pupil.kt b/app/src/main/java/xyz/quaver/pupil/Pupil.kt
index ff48c13e..9ec3d664 100644
--- a/app/src/main/java/xyz/quaver/pupil/Pupil.kt
+++ b/app/src/main/java/xyz/quaver/pupil/Pupil.kt
@@ -51,7 +51,10 @@ class Pupil : MultiDexApplication() {
proxy = getProxy(this)
try {
- preference.getString("dl_location", null)
+ preference.getString("dl_location", null).also {
+ if (!File(it!!).canWrite())
+ throw Exception()
+ }
} catch (e: Exception) {
preference.edit().remove("dl_location").apply()
}
@@ -72,13 +75,20 @@ class Pupil : MultiDexApplication() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
- val channel = NotificationChannel("download", getString(R.string.channel_download), NotificationManager.IMPORTANCE_MIN).apply {
+
+ manager.createNotificationChannel(NotificationChannel("download", getString(R.string.channel_download), NotificationManager.IMPORTANCE_LOW).apply {
description = getString(R.string.channel_download_description)
enableLights(false)
enableVibration(false)
lockscreenVisibility = Notification.VISIBILITY_SECRET
- }
- manager.createNotificationChannel(channel)
+ })
+
+ manager.createNotificationChannel(NotificationChannel("update", getString(R.string.channel_update), NotificationManager.IMPORTANCE_HIGH).apply {
+ description = getString(R.string.channel_update_description)
+ enableLights(true)
+ enableVibration(true)
+ lockscreenVisibility = Notification.VISIBILITY_SECRET
+ })
}
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
diff --git a/app/src/main/java/xyz/quaver/pupil/ui/MainActivity.kt b/app/src/main/java/xyz/quaver/pupil/ui/MainActivity.kt
index 679f83e4..bc9de08a 100644
--- a/app/src/main/java/xyz/quaver/pupil/ui/MainActivity.kt
+++ b/app/src/main/java/xyz/quaver/pupil/ui/MainActivity.kt
@@ -195,7 +195,7 @@ class MainActivity : AppCompatActivity() {
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
val preference = PreferenceManager.getDefaultSharedPreferences(this)
- val perPage = preference.getString("per_page", "25")!!.toInt()
+ val perPage = preference.getString("per_page", "25")!!.toIntOrNull() ?: 25
val maxPage = ceil(totalItems / perPage.toDouble()).roundToInt()
return when(keyCode) {
@@ -341,7 +341,7 @@ class MainActivity : AppCompatActivity() {
setImageResource(R.drawable.ic_jump)
setOnClickListener {
val preference = PreferenceManager.getDefaultSharedPreferences(context)
- val perPage = preference.getString("per_page", "25")!!.toInt()
+ val perPage = preference.getString("per_page", "25")!!.toIntOrNull() ?: 25
val editText = EditText(context)
AlertDialog.Builder(context).apply {
@@ -369,14 +369,16 @@ class MainActivity : AppCompatActivity() {
with(main_fab_id) {
setImageResource(R.drawable.numeric)
setOnClickListener {
- val editText = EditText(context)
+ val editText = EditText(context).apply {
+ inputType = InputType.TYPE_CLASS_NUMBER
+ }
AlertDialog.Builder(context).apply {
setView(editText)
setTitle(R.string.main_open_gallery_by_id)
setPositiveButton(android.R.string.ok) { _, _ ->
- val galleryID = editText.text.toString().toInt()
+ val galleryID = editText.text.toString().toIntOrNull() ?: return@setPositiveButton
val intent = Intent(this@MainActivity, ReaderActivity::class.java).apply {
putExtra("galleryID", galleryID)
}
diff --git a/app/src/main/java/xyz/quaver/pupil/util/ConstValues.kt b/app/src/main/java/xyz/quaver/pupil/util/ConstValues.kt
index 38b24cf2..d70c8807 100644
--- a/app/src/main/java/xyz/quaver/pupil/util/ConstValues.kt
+++ b/app/src/main/java/xyz/quaver/pupil/util/ConstValues.kt
@@ -27,4 +27,6 @@ const val REQUEST_DOWNLOAD_FOLDER = 3874
const val REQUEST_DOWNLOAD_FOLDER_OLD = 3425
const val REQUEST_WRITE_PERMISSION_AND_SAF = 13900
+const val NOTIFICATION_ID_UPDATE = 2345
+
val json = Json(JsonConfiguration.Stable)
\ No newline at end of file
diff --git a/app/src/main/java/xyz/quaver/pupil/util/update.kt b/app/src/main/java/xyz/quaver/pupil/util/update.kt
index 94ae9ed1..7a687ba8 100644
--- a/app/src/main/java/xyz/quaver/pupil/util/update.kt
+++ b/app/src/main/java/xyz/quaver/pupil/util/update.kt
@@ -18,16 +18,10 @@
package xyz.quaver.pupil.util
-import android.app.PendingIntent
+import android.app.DownloadManager
import android.content.Context
-import android.content.Intent
-import android.webkit.MimeTypeMap
+import android.net.Uri
import androidx.appcompat.app.AlertDialog
-import androidx.appcompat.app.AppCompatActivity
-import androidx.core.app.NotificationCompat
-import androidx.core.app.NotificationManagerCompat
-import androidx.core.content.FileProvider
-import androidx.lifecycle.Lifecycle
import androidx.preference.PreferenceManager
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@@ -81,7 +75,7 @@ fun getApkUrl(releases: JsonObject) : String? {
}
const val UPDATE_NOTIFICATION_ID = 384823
-fun checkUpdate(context: AppCompatActivity, force: Boolean = false) {
+fun checkUpdate(context: Context, force: Boolean = false) {
val preferences = PreferenceManager.getDefaultSharedPreferences(context)
val ignoreUpdateUntil = preferences.getLong("ignore_update_until", 0)
@@ -143,56 +137,27 @@ fun checkUpdate(context: AppCompatActivity, force: Boolean = false) {
setMessage(Markwon.create(context).toMarkdown(msg))
setPositiveButton(android.R.string.yes) { _, _ ->
- val notificationManager = NotificationManagerCompat.from(context)
- val builder = NotificationCompat.Builder(context, "download").apply {
- setContentTitle(context.getString(R.string.update_notification_description))
- setSmallIcon(android.R.drawable.stat_sys_download)
- priority = NotificationCompat.PRIORITY_LOW
- setOngoing(true)
+ val preference = PreferenceManager.getDefaultSharedPreferences(context)
+
+ val downloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
+
+ //Cancel any download queued before
+
+ val id = preference.getLong("update_download_id", -1)
+
+ if (id != -1L)
+ downloadManager.remove(id)
+
+ val target = File(context.getExternalFilesDir(null), "Pupil.apk").also {
+ it.delete()
}
- CoroutineScope(Dispatchers.IO).launch io@{
- val target = File(getDownloadDirectory(context), "Pupil.apk")
+ val request = DownloadManager.Request(Uri.parse(url))
+ .setTitle(context.getText(R.string.update_notification_description))
+ .setDestinationUri(Uri.fromFile(target))
- try {
- URL(url).download(target) { progress, fileSize ->
- builder.setProgress(fileSize.toInt(), progress.toInt(), false)
- notificationManager.notify(UPDATE_NOTIFICATION_ID, builder.build())
- }
- } catch (e: Exception) {
- builder.apply {
- setContentText(context.getString(R.string.update_failed))
- setMessage(context.getString(R.string.update_failed_message))
- setSmallIcon(android.R.drawable.stat_sys_download_done)
- setOngoing(false)
- }
-
- notificationManager.cancel(UPDATE_NOTIFICATION_ID)
- notificationManager.notify(UPDATE_NOTIFICATION_ID, builder.build())
-
- return@io
- }
-
- val install = Intent(Intent.ACTION_VIEW).apply {
- flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_GRANT_READ_URI_PERMISSION
- setDataAndType(FileProvider.getUriForFile(context, context.applicationContext.packageName + ".provider", target), MimeTypeMap.getSingleton().getMimeTypeFromExtension("apk"))
- }
-
- builder.apply {
- setContentIntent(PendingIntent.getActivity(context, 0, install, 0))
- setProgress(0, 0, false)
- setSmallIcon(android.R.drawable.stat_sys_download_done)
- setContentTitle(context.getString(R.string.update_download_completed))
- setContentText(context.getString(R.string.update_download_completed_description))
- setOngoing(false)
- }
-
- notificationManager.cancel(UPDATE_NOTIFICATION_ID)
-
- if (context.lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED))
- context.startActivity(install)
- else
- notificationManager.notify(UPDATE_NOTIFICATION_ID, builder.build())
+ downloadManager.enqueue(request).also {
+ preference.edit().putLong("update_download_id", it).apply()
}
}
setNegativeButton(if (force) android.R.string.no else R.string.ignore_update) { _, _ ->
diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml
index f26ea3d7..9d764026 100644
--- a/app/src/main/res/values-ja/strings.xml
+++ b/app/src/main/res/values-ja/strings.xml
@@ -132,4 +132,6 @@
サーバー
簡単モード
すべてのダウンロードキャンセル
+ アップデート
+ アップデートの進行状態を表示
\ No newline at end of file
diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml
index 99ebfe1f..394dbff5 100644
--- a/app/src/main/res/values-ko/strings.xml
+++ b/app/src/main/res/values-ko/strings.xml
@@ -132,4 +132,6 @@
서버
간단히 보기 모드
다운로드 모두 취소
+ 업데이트
+ 업데이트 진행상황 표시
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index fd51625d..519bc5ae 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -35,6 +35,9 @@
Download
Shows download status
+ Update
+ Shows update progress
+
Unable to connect to hitomi.la
Lock file corrupted! Please re-install Pupil
diff --git a/libpupil/build.gradle b/libpupil/build.gradle
index 96abc57b..035a800e 100644
--- a/libpupil/build.gradle
+++ b/libpupil/build.gradle
@@ -11,8 +11,6 @@ dependencies {
testImplementation 'junit:junit:4.13'
}
-sourceCompatibility = "7"
-targetCompatibility = "7"
buildscript {
repositories {
mavenCentral()
diff --git a/libpupil/src/test/java/xyz/quaver/hitomi/UnitTest.kt b/libpupil/src/test/java/xyz/quaver/hitomi/UnitTest.kt
index 4d56ed56..bd3661a6 100644
--- a/libpupil/src/test/java/xyz/quaver/hitomi/UnitTest.kt
+++ b/libpupil/src/test/java/xyz/quaver/hitomi/UnitTest.kt
@@ -75,7 +75,7 @@ class UnitTest {
@Test
fun test_getReader() {
- val reader = getReader(1567569)
+ val reader = getReader(1574736)
print(reader)
}