Skip to content

Commit

Permalink
Check if in-app update allowed
Browse files Browse the repository at this point in the history
  • Loading branch information
Koitharu committed Apr 19, 2020
1 parent ef4dd82 commit 0d0982b
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 14 deletions.
2 changes: 1 addition & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ android {
minSdkVersion 21
targetSdkVersion 29
versionCode gitCommits
versionName '0.2-b1'
versionName '0.3'

buildConfigField 'String', 'GIT_BRANCH', "\"${gitBranch}\""

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package org.koitharu.kotatsu.ui.settings

import android.annotation.SuppressLint
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Build
Expand All @@ -22,8 +24,18 @@ import org.koitharu.kotatsu.core.github.VersionId
import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.ui.common.BaseService
import org.koitharu.kotatsu.utils.FileSizeUtils
import org.koitharu.kotatsu.utils.ext.byte2HexFormatted
import java.io.ByteArrayInputStream
import java.io.InputStream
import java.security.MessageDigest
import java.security.NoSuchAlgorithmException
import java.security.cert.CertificateEncodingException
import java.security.cert.CertificateException
import java.security.cert.CertificateFactory
import java.security.cert.X509Certificate
import java.util.concurrent.TimeUnit


class AppUpdateService : BaseService() {

override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
Expand Down Expand Up @@ -92,25 +104,26 @@ class AppUpdateService : BaseService() {
)
builder.setSmallIcon(R.drawable.ic_stat_update)
builder.setAutoCancel(true)
builder.setColor(ContextCompat.getColor(this, R.color.blue_primary_dark))
builder.color = ContextCompat.getColor(this, R.color.blue_primary_dark)
builder.setLargeIcon(BitmapFactory.decodeResource(resources, R.mipmap.ic_launcher))
manager.notify(NOTIFICATION_ID, builder.build())
}

companion object {

private const val CERT_SHA1 = "2C:19:C7:E8:07:61:2B:8E:94:51:1B:FD:72:67:07:64:5D:C2:58:AE"
private const val NOTIFICATION_ID = 202
private const val CHANNEL_ID = "update"
private val PERIOD = TimeUnit.HOURS.toMillis(6)

fun start(context: Context) {
try {
context.startService(Intent(context, AppUpdateService::class.java))
} catch (_: IllegalStateException) {
}
fun isUpdateSupported(context: Context): Boolean {
return getCertificateSHA1Fingerprint(context) == CERT_SHA1
}

fun startIfRequired(context: Context) {
if (!isUpdateSupported(context)) {
return
}
val settings = AppSettings(context)
if (settings.appUpdateAuto) {
val lastUpdate = settings.appUpdate
Expand All @@ -119,5 +132,47 @@ class AppUpdateService : BaseService() {
}
}
}

private fun start(context: Context) {
try {
context.startService(Intent(context, AppUpdateService::class.java))
} catch (_: IllegalStateException) {
}
}

@Suppress("DEPRECATION")
@SuppressLint("PackageManagerGetSignatures")
private fun getCertificateSHA1Fingerprint(context: Context): String? {
val packageInfo = try {
context.packageManager.getPackageInfo(
context.packageName,
PackageManager.GET_SIGNATURES
)
} catch (e: PackageManager.NameNotFoundException) {
e.printStackTrace()
return null
}
val signatures = packageInfo?.signatures
val cert: ByteArray = signatures?.firstOrNull()?.toByteArray() ?: return null
val input: InputStream = ByteArrayInputStream(cert)
val c = try {
val cf = CertificateFactory.getInstance("X509")
cf.generateCertificate(input) as X509Certificate
} catch (e: CertificateException) {
e.printStackTrace()
return null
}
return try {
val md: MessageDigest = MessageDigest.getInstance("SHA1")
val publicKey: ByteArray = md.digest(c.getEncoded())
publicKey.byte2HexFormatted()
} catch (e: NoSuchAlgorithmException) {
e.printStackTrace()
null
} catch (e: CertificateEncodingException) {
e.printStackTrace()
null
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ class MainSettingsFragment : BasePreferenceFragment(R.string.settings),
}
findPreference<MultiSelectListPreference>(R.string.key_reader_switchers)?.summaryProvider =
MultiSummaryProvider(R.string.gestures_only)
findPreference<Preference>(R.string.key_app_update_auto)?.run {
isVisible = AppUpdateService.isUpdateSupported(context)
}
}

override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
Expand Down
20 changes: 20 additions & 0 deletions app/src/main/java/org/koitharu/kotatsu/utils/ext/StringExt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package org.koitharu.kotatsu.utils.ext

import android.net.Uri
import java.net.URLEncoder
import java.util.*

fun String.longHashCode(): Long {
var h = 1125899906842597L
Expand Down Expand Up @@ -72,4 +73,23 @@ fun String.toUriOrNull(): Uri? = if (isEmpty()) {
null
} else {
Uri.parse(this)
}

fun ByteArray.byte2HexFormatted(): String? {
val str = StringBuilder(size * 2)
for (i in indices) {
var h = Integer.toHexString(this[i].toInt())
val l = h.length
if (l == 1) {
h = "0$h"
}
if (l > 2) {
h = h.substring(l - 2, l)
}
str.append(h.toUpperCase(Locale.ROOT))
if (i < size - 1) {
str.append(':')
}
}
return str.toString()
}
17 changes: 10 additions & 7 deletions app/src/main/res/xml/pref_main.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">

<ListPreference
android:defaultValue="-1"
Expand Down Expand Up @@ -32,9 +33,9 @@

<PreferenceScreen
android:fragment="org.koitharu.kotatsu.ui.settings.sources.SourcesSettingsFragment"
android:key="@string/key_remote_sources"
android:title="@string/remote_sources"
app:allowDividerAbove="true"
android:key="@string/key_remote_sources"
app:iconSpaceReserved="false" />

<PreferenceScreen
Expand All @@ -53,8 +54,8 @@

<SwitchPreferenceCompat
android:defaultValue="false"
android:title="@string/pages_animation"
android:key="@string/key_reader_animation"
android:title="@string/pages_animation"
app:iconSpaceReserved="false" />

<PreferenceCategory
Expand All @@ -67,7 +68,9 @@
android:key="@string/key_app_update_auto"
android:summary="@string/show_notification_app_update"
android:title="@string/application_update"
app:iconSpaceReserved="false" />
app:iconSpaceReserved="false"
app:isPreferenceVisible="false"
tools:isPreferenceVisible="true" />

<SwitchPreference
android:defaultValue="true"
Expand All @@ -77,10 +80,10 @@
app:iconSpaceReserved="false" />

<Preference
android:title="@string/notifications_settings"
app:iconSpaceReserved="false"
android:dependency="@string/key_tracker_notifications"
android:key="@string/key_notifications_settings" />
android:key="@string/key_notifications_settings"
android:title="@string/notifications_settings"
app:iconSpaceReserved="false" />

</PreferenceCategory>

Expand Down

0 comments on commit 0d0982b

Please sign in to comment.