mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-11-04 08:08:55 +01:00 
			
		
		
		
	Complete auto updates checker (#449)
* Complete auto updates checker * Use GcmTaskService for the periodical updates checker * Persist task across reinstalls * Hide setting instead of disabling * Minor refactor
This commit is contained in:
		@@ -96,6 +96,8 @@ dependencies {
 | 
			
		||||
    compile "com.android.support:support-annotations:$support_library_version"
 | 
			
		||||
    compile "com.android.support:customtabs:$support_library_version"
 | 
			
		||||
 | 
			
		||||
    compile 'com.google.android.gms:play-services-gcm:9.4.0'
 | 
			
		||||
 | 
			
		||||
    // ReactiveX
 | 
			
		||||
    compile 'io.reactivex:rxandroid:1.2.1'
 | 
			
		||||
    compile 'io.reactivex:rxjava:1.1.8'
 | 
			
		||||
 
 | 
			
		||||
@@ -59,6 +59,20 @@
 | 
			
		||||
        <service android:name=".data.mangasync.UpdateMangaSyncService"
 | 
			
		||||
            android:exported="false"/>
 | 
			
		||||
 | 
			
		||||
        <service
 | 
			
		||||
            android:name=".data.updater.UpdateCheckerService"
 | 
			
		||||
            android:exported="true"
 | 
			
		||||
            android:permission="com.google.android.gms.permission.BIND_NETWORK_TASK_SERVICE">
 | 
			
		||||
            <intent-filter>
 | 
			
		||||
                <action android:name="com.google.android.gms.gcm.ACTION_TASK_READY" />
 | 
			
		||||
            </intent-filter>
 | 
			
		||||
        </service>
 | 
			
		||||
 | 
			
		||||
        <service android:name=".data.updater.UpdateDownloaderService"
 | 
			
		||||
            android:exported="false"/>
 | 
			
		||||
 | 
			
		||||
        <receiver android:name=".data.updater.UpdateNotificationReceiver"/>
 | 
			
		||||
 | 
			
		||||
        <receiver
 | 
			
		||||
            android:name=".data.library.LibraryUpdateService$SyncOnConnectionAvailable"
 | 
			
		||||
            android:enabled="false">
 | 
			
		||||
@@ -79,10 +93,6 @@
 | 
			
		||||
            android:name=".data.library.LibraryUpdateService$CancelUpdateReceiver">
 | 
			
		||||
        </receiver>
 | 
			
		||||
 | 
			
		||||
        <receiver
 | 
			
		||||
            android:name=".data.updater.UpdateDownloader$InstallOnReceived">
 | 
			
		||||
        </receiver>
 | 
			
		||||
 | 
			
		||||
        <receiver
 | 
			
		||||
            android:name=".data.library.LibraryUpdateAlarm">
 | 
			
		||||
            <intent-filter>
 | 
			
		||||
@@ -91,15 +101,6 @@
 | 
			
		||||
            </intent-filter>
 | 
			
		||||
        </receiver>
 | 
			
		||||
 | 
			
		||||
        <receiver
 | 
			
		||||
            android:name=".data.updater.UpdateDownloaderAlarm">
 | 
			
		||||
            <intent-filter>
 | 
			
		||||
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
 | 
			
		||||
                <action android:name="eu.kanade.CHECK_UPDATE"/>
 | 
			
		||||
            </intent-filter>
 | 
			
		||||
        </receiver>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        <meta-data
 | 
			
		||||
            android:name="eu.kanade.tachiyomi.data.glide.AppGlideModule"
 | 
			
		||||
            android:value="GlideModule" />
 | 
			
		||||
 
 | 
			
		||||
@@ -78,7 +78,7 @@ class PreferenceKeys(context: Context) {
 | 
			
		||||
 | 
			
		||||
    val filterUnread = context.getString(R.string.pref_filter_unread_key)
 | 
			
		||||
 | 
			
		||||
    val automaticUpdateStatus = context.getString(R.string.pref_enable_automatic_updates_key)
 | 
			
		||||
    val automaticUpdates = context.getString(R.string.pref_enable_automatic_updates_key)
 | 
			
		||||
 | 
			
		||||
    val startScreen = context.getString(R.string.pref_start_screen_key)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -130,6 +130,6 @@ class PreferencesHelper(context: Context) {
 | 
			
		||||
 | 
			
		||||
    fun filterUnread() = rxPrefs.getBoolean(keys.filterUnread, false)
 | 
			
		||||
 | 
			
		||||
    fun automaticUpdateStatus() = prefs.getBoolean(keys.automaticUpdateStatus, false)
 | 
			
		||||
    fun automaticUpdates() = prefs.getBoolean(keys.automaticUpdates, false)
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,6 @@ import retrofit2.converter.gson.GsonConverterFactory
 | 
			
		||||
import retrofit2.http.GET
 | 
			
		||||
import rx.Observable
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Used to connect with the Github API.
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
@@ -1,20 +1,25 @@
 | 
			
		||||
package eu.kanade.tachiyomi.data.updater
 | 
			
		||||
 | 
			
		||||
import android.content.Context
 | 
			
		||||
import eu.kanade.tachiyomi.R
 | 
			
		||||
import eu.kanade.tachiyomi.util.toast
 | 
			
		||||
import eu.kanade.tachiyomi.BuildConfig
 | 
			
		||||
import rx.Observable
 | 
			
		||||
 | 
			
		||||
class GithubUpdateChecker() {
 | 
			
		||||
 | 
			
		||||
class GithubUpdateChecker(private val context: Context) {
 | 
			
		||||
 | 
			
		||||
    val service: GithubService = GithubService.create()
 | 
			
		||||
    private val service: GithubService = GithubService.create()
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns observable containing release information
 | 
			
		||||
     */
 | 
			
		||||
    fun checkForApplicationUpdate(): Observable<GithubRelease> {
 | 
			
		||||
        context.toast(R.string.update_check_look_for_updates)
 | 
			
		||||
        return service.getLatestVersion()
 | 
			
		||||
    fun checkForUpdate(): Observable<GithubUpdateResult> {
 | 
			
		||||
        return service.getLatestVersion().map { release ->
 | 
			
		||||
            val newVersion = release.version.replace("[^\\d.]".toRegex(), "")
 | 
			
		||||
 | 
			
		||||
            // Check if latest version is different from current version
 | 
			
		||||
            if (newVersion != BuildConfig.VERSION_NAME) {
 | 
			
		||||
                GithubUpdateResult.NewUpdate(release)
 | 
			
		||||
            } else {
 | 
			
		||||
                GithubUpdateResult.NoNewUpdate()
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,7 @@
 | 
			
		||||
package eu.kanade.tachiyomi.data.updater
 | 
			
		||||
 | 
			
		||||
sealed class GithubUpdateResult {
 | 
			
		||||
 | 
			
		||||
    class NewUpdate(val release: GithubRelease): GithubUpdateResult()
 | 
			
		||||
    class NoNewUpdate(): GithubUpdateResult()
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,80 @@
 | 
			
		||||
package eu.kanade.tachiyomi.data.updater
 | 
			
		||||
 | 
			
		||||
import android.content.Context
 | 
			
		||||
import android.support.v4.app.NotificationCompat
 | 
			
		||||
import com.google.android.gms.gcm.*
 | 
			
		||||
import eu.kanade.tachiyomi.Constants.NOTIFICATION_UPDATER_ID
 | 
			
		||||
import eu.kanade.tachiyomi.R
 | 
			
		||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 | 
			
		||||
import eu.kanade.tachiyomi.util.notificationManager
 | 
			
		||||
import uy.kohesive.injekt.Injekt
 | 
			
		||||
import uy.kohesive.injekt.api.get
 | 
			
		||||
 | 
			
		||||
class UpdateCheckerService : GcmTaskService() {
 | 
			
		||||
 | 
			
		||||
    override fun onInitializeTasks() {
 | 
			
		||||
        val preferences: PreferencesHelper = Injekt.get()
 | 
			
		||||
        if (preferences.automaticUpdates()) {
 | 
			
		||||
            setupTask(this)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun onRunTask(params: TaskParams): Int {
 | 
			
		||||
        return checkVersion()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun checkVersion(): Int {
 | 
			
		||||
        return GithubUpdateChecker()
 | 
			
		||||
                .checkForUpdate()
 | 
			
		||||
                .map { result ->
 | 
			
		||||
                    if (result is GithubUpdateResult.NewUpdate) {
 | 
			
		||||
                        val url = result.release.downloadLink
 | 
			
		||||
 | 
			
		||||
                        NotificationCompat.Builder(this).update {
 | 
			
		||||
                            setContentTitle(getString(R.string.app_name))
 | 
			
		||||
                            setContentText(getString(R.string.update_check_notification_update_available))
 | 
			
		||||
                            setSmallIcon(android.R.drawable.stat_sys_download_done)
 | 
			
		||||
                            // Download action
 | 
			
		||||
                            addAction(android.R.drawable.stat_sys_download_done,
 | 
			
		||||
                                    getString(R.string.action_download),
 | 
			
		||||
                                    UpdateNotificationReceiver.downloadApkIntent(
 | 
			
		||||
                                            this@UpdateCheckerService, url))
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    GcmNetworkManager.RESULT_SUCCESS
 | 
			
		||||
                }
 | 
			
		||||
                .onErrorReturn { GcmNetworkManager.RESULT_FAILURE }
 | 
			
		||||
                // Sadly, the task needs to be synchronous.
 | 
			
		||||
                .toBlocking()
 | 
			
		||||
                .single()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun NotificationCompat.Builder.update(block: NotificationCompat.Builder.() -> Unit) {
 | 
			
		||||
        block()
 | 
			
		||||
        notificationManager.notify(NOTIFICATION_UPDATER_ID, build())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
        fun setupTask(context: Context) {
 | 
			
		||||
            val task = PeriodicTask.Builder()
 | 
			
		||||
                    .setService(UpdateCheckerService::class.java)
 | 
			
		||||
                    .setTag("Updater")
 | 
			
		||||
                    // 24 hours
 | 
			
		||||
                    .setPeriod(24 * 60 * 60)
 | 
			
		||||
                    // Run between the last two hours
 | 
			
		||||
                    .setFlex(2 * 60 * 60)
 | 
			
		||||
                    .setRequiredNetwork(Task.NETWORK_STATE_CONNECTED)
 | 
			
		||||
                    .setPersisted(true)
 | 
			
		||||
                    .setUpdateCurrent(true)
 | 
			
		||||
                    .build()
 | 
			
		||||
 | 
			
		||||
            GcmNetworkManager.getInstance(context).schedule(task)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        fun cancelTask(context: Context) {
 | 
			
		||||
            GcmNetworkManager.getInstance(context).cancelAllTasks(UpdateCheckerService::class.java)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -1,202 +0,0 @@
 | 
			
		||||
package eu.kanade.tachiyomi.data.updater
 | 
			
		||||
 | 
			
		||||
import android.app.Notification
 | 
			
		||||
import android.app.PendingIntent
 | 
			
		||||
import android.content.BroadcastReceiver
 | 
			
		||||
import android.content.Context
 | 
			
		||||
import android.content.Intent
 | 
			
		||||
import android.net.Uri
 | 
			
		||||
import android.os.AsyncTask
 | 
			
		||||
import android.support.v4.app.NotificationCompat
 | 
			
		||||
import eu.kanade.tachiyomi.Constants
 | 
			
		||||
import eu.kanade.tachiyomi.R
 | 
			
		||||
import eu.kanade.tachiyomi.data.network.GET
 | 
			
		||||
import eu.kanade.tachiyomi.data.network.NetworkHelper
 | 
			
		||||
import eu.kanade.tachiyomi.data.network.ProgressListener
 | 
			
		||||
import eu.kanade.tachiyomi.data.network.newCallWithProgress
 | 
			
		||||
import eu.kanade.tachiyomi.util.notificationManager
 | 
			
		||||
import eu.kanade.tachiyomi.util.saveTo
 | 
			
		||||
import timber.log.Timber
 | 
			
		||||
import uy.kohesive.injekt.injectLazy
 | 
			
		||||
import java.io.File
 | 
			
		||||
 | 
			
		||||
class UpdateDownloader(private val context: Context) :
 | 
			
		||||
        AsyncTask<String, Int, UpdateDownloader.DownloadResult>() {
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
        /**
 | 
			
		||||
         * Prompt user with apk install intent
 | 
			
		||||
         * @param context context
 | 
			
		||||
         * @param file file of apk that is installed
 | 
			
		||||
         */
 | 
			
		||||
        fun installAPK(context: Context, file: File) {
 | 
			
		||||
            // Prompt install interface
 | 
			
		||||
            val intent = Intent(Intent.ACTION_VIEW)
 | 
			
		||||
            intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive")
 | 
			
		||||
            // Without this flag android returned a intent error!
 | 
			
		||||
            intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
 | 
			
		||||
            context.startActivity(intent)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    val network: NetworkHelper by injectLazy()
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Default download dir
 | 
			
		||||
     */
 | 
			
		||||
    private val apkFile = File(context.externalCacheDir, "update.apk")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Notification builder
 | 
			
		||||
     */
 | 
			
		||||
    private val notificationBuilder = NotificationCompat.Builder(context)
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Id of the notification
 | 
			
		||||
     */
 | 
			
		||||
    private val notificationId: Int
 | 
			
		||||
        get() = Constants.NOTIFICATION_UPDATER_ID
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Class containing download result
 | 
			
		||||
     * @param url url of file
 | 
			
		||||
     * @param successful status of download
 | 
			
		||||
     */
 | 
			
		||||
    class DownloadResult(var url: String, var successful: Boolean)
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Called before downloading
 | 
			
		||||
     */
 | 
			
		||||
    override fun onPreExecute() {
 | 
			
		||||
        // Create download notification
 | 
			
		||||
        with(notificationBuilder) {
 | 
			
		||||
            setContentTitle(context.getString(R.string.update_check_notification_file_download))
 | 
			
		||||
            setContentText(context.getString(R.string.update_check_notification_download_in_progress))
 | 
			
		||||
            setSmallIcon(android.R.drawable.stat_sys_download)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun doInBackground(vararg params: String?): DownloadResult {
 | 
			
		||||
        // Initialize information array containing path and url to file.
 | 
			
		||||
        val result = DownloadResult(params[0]!!, false)
 | 
			
		||||
 | 
			
		||||
        // Progress of the download
 | 
			
		||||
        var savedProgress = 0
 | 
			
		||||
 | 
			
		||||
        val progressListener = object : ProgressListener {
 | 
			
		||||
            override fun update(bytesRead: Long, contentLength: Long, done: Boolean) {
 | 
			
		||||
                val progress = (100 * bytesRead / contentLength).toInt()
 | 
			
		||||
                if (progress > savedProgress) {
 | 
			
		||||
                    savedProgress = progress
 | 
			
		||||
                    publishProgress(progress)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            // Make the request and download the file
 | 
			
		||||
            val response = network.client.newCallWithProgress(GET(result.url), progressListener).execute()
 | 
			
		||||
 | 
			
		||||
            if (response.isSuccessful) {
 | 
			
		||||
                response.body().source().saveTo(apkFile)
 | 
			
		||||
                // Set download successful
 | 
			
		||||
                result.successful = true
 | 
			
		||||
            } else {
 | 
			
		||||
                response.close()
 | 
			
		||||
            }
 | 
			
		||||
        } catch (e: Exception) {
 | 
			
		||||
            Timber.e(e, e.message)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return result
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Called when progress is updated
 | 
			
		||||
     * @param values values containing progress
 | 
			
		||||
     */
 | 
			
		||||
    override fun onProgressUpdate(vararg values: Int?) {
 | 
			
		||||
        // Notify notification manager to update notification
 | 
			
		||||
        values.getOrNull(0)?.let {
 | 
			
		||||
            notificationBuilder.setProgress(100, it, false)
 | 
			
		||||
            // Displays the progress bar on notification
 | 
			
		||||
            context.notificationManager.notify(notificationId, notificationBuilder.build())
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Called when download done
 | 
			
		||||
     * @param result string containing download information
 | 
			
		||||
     */
 | 
			
		||||
    override fun onPostExecute(result: DownloadResult) {
 | 
			
		||||
        with(notificationBuilder) {
 | 
			
		||||
            if (result.successful) {
 | 
			
		||||
                setContentTitle(context.getString(R.string.app_name))
 | 
			
		||||
                setContentText(context.getString(R.string.update_check_notification_download_complete))
 | 
			
		||||
                addAction(R.drawable.ic_system_update_grey_24dp_img, context.getString(R.string.action_install),
 | 
			
		||||
                        getInstallOnReceivedIntent(InstallOnReceived.INSTALL_APK, apkFile.absolutePath))
 | 
			
		||||
                addAction(R.drawable.ic_clear_grey_24dp_img, context.getString(R.string.action_cancel),
 | 
			
		||||
                        getInstallOnReceivedIntent(InstallOnReceived.CANCEL_NOTIFICATION))
 | 
			
		||||
            } else {
 | 
			
		||||
                setContentText(context.getString(R.string.update_check_notification_download_error))
 | 
			
		||||
                addAction(R.drawable.ic_refresh_grey_24dp_img, context.getString(R.string.action_retry),
 | 
			
		||||
                        getInstallOnReceivedIntent(InstallOnReceived.RETRY_DOWNLOAD, result.url))
 | 
			
		||||
                addAction(R.drawable.ic_clear_grey_24dp_img, context.getString(R.string.action_cancel),
 | 
			
		||||
                        getInstallOnReceivedIntent(InstallOnReceived.CANCEL_NOTIFICATION))
 | 
			
		||||
            }
 | 
			
		||||
            setSmallIcon(android.R.drawable.stat_sys_download_done)
 | 
			
		||||
            setProgress(0, 0, false)
 | 
			
		||||
        }
 | 
			
		||||
        val notification = notificationBuilder.build()
 | 
			
		||||
        notification.flags = Notification.FLAG_NO_CLEAR
 | 
			
		||||
        context.notificationManager.notify(notificationId, notification)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns broadcast intent
 | 
			
		||||
     * @param action action name of broadcast intent
 | 
			
		||||
     * @param path path of file | url of file
 | 
			
		||||
     * @return broadcast intent
 | 
			
		||||
     */
 | 
			
		||||
    fun getInstallOnReceivedIntent(action: String, path: String = ""): PendingIntent {
 | 
			
		||||
        val intent = Intent(context, InstallOnReceived::class.java).apply {
 | 
			
		||||
            this.action = action
 | 
			
		||||
            putExtra(InstallOnReceived.FILE_LOCATION, path)
 | 
			
		||||
        }
 | 
			
		||||
        return PendingIntent.getBroadcast(context, 0, intent, 0)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * BroadcastEvent used to install apk or retry download
 | 
			
		||||
     */
 | 
			
		||||
    class InstallOnReceived : BroadcastReceiver() {
 | 
			
		||||
        companion object {
 | 
			
		||||
            // Install apk action
 | 
			
		||||
            const val INSTALL_APK = "eu.kanade.INSTALL_APK"
 | 
			
		||||
 | 
			
		||||
            // Retry download action
 | 
			
		||||
            const val RETRY_DOWNLOAD = "eu.kanade.RETRY_DOWNLOAD"
 | 
			
		||||
 | 
			
		||||
            // Retry download action
 | 
			
		||||
            const val CANCEL_NOTIFICATION = "eu.kanade.CANCEL_NOTIFICATION"
 | 
			
		||||
 | 
			
		||||
            // Absolute path of file || URL of file
 | 
			
		||||
            const val FILE_LOCATION = "file_location"
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        override fun onReceive(context: Context, intent: Intent) {
 | 
			
		||||
            when (intent.action) {
 | 
			
		||||
                // Install apk.
 | 
			
		||||
                INSTALL_APK -> UpdateDownloader.installAPK(context, File(intent.getStringExtra(FILE_LOCATION)))
 | 
			
		||||
                // Retry download.
 | 
			
		||||
                RETRY_DOWNLOAD -> UpdateDownloader(context).execute(intent.getStringExtra(FILE_LOCATION))
 | 
			
		||||
 | 
			
		||||
                CANCEL_NOTIFICATION -> context.notificationManager.cancel(Constants.NOTIFICATION_UPDATER_ID)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,110 +0,0 @@
 | 
			
		||||
package eu.kanade.tachiyomi.data.updater
 | 
			
		||||
 | 
			
		||||
import android.app.AlarmManager
 | 
			
		||||
import android.app.PendingIntent
 | 
			
		||||
import android.content.BroadcastReceiver
 | 
			
		||||
import android.content.Context
 | 
			
		||||
import android.content.Intent
 | 
			
		||||
import android.os.SystemClock
 | 
			
		||||
import eu.kanade.tachiyomi.BuildConfig
 | 
			
		||||
import eu.kanade.tachiyomi.R
 | 
			
		||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 | 
			
		||||
import eu.kanade.tachiyomi.util.DeviceUtil
 | 
			
		||||
import eu.kanade.tachiyomi.util.alarmManager
 | 
			
		||||
import eu.kanade.tachiyomi.util.notification
 | 
			
		||||
import eu.kanade.tachiyomi.util.notificationManager
 | 
			
		||||
import rx.android.schedulers.AndroidSchedulers
 | 
			
		||||
import rx.schedulers.Schedulers
 | 
			
		||||
import uy.kohesive.injekt.Injekt
 | 
			
		||||
import uy.kohesive.injekt.api.get
 | 
			
		||||
 | 
			
		||||
class UpdateDownloaderAlarm : BroadcastReceiver() {
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
        const val CHECK_UPDATE_ACTION = "eu.kanade.CHECK_UPDATE"
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Sets the alarm to run the intent that checks for update
 | 
			
		||||
         * @param context the application context.
 | 
			
		||||
         * @param intervalInHours the time in hours when it will be executed.
 | 
			
		||||
         */
 | 
			
		||||
        fun startAlarm(context: Context, intervalInHours: Int = 12,
 | 
			
		||||
                       isEnabled: Boolean = Injekt.get<PreferencesHelper>().automaticUpdateStatus()) {
 | 
			
		||||
            // Stop previous running alarms if needed, and do not restart it if the interval is 0.
 | 
			
		||||
            UpdateDownloaderAlarm.stopAlarm(context)
 | 
			
		||||
            if (intervalInHours == 0 || !isEnabled)
 | 
			
		||||
                return
 | 
			
		||||
 | 
			
		||||
            // Get the time the alarm should fire the event to update.
 | 
			
		||||
            val intervalInMillis = intervalInHours * 60 * 60 * 1000
 | 
			
		||||
            val nextRun = SystemClock.elapsedRealtime() + intervalInMillis
 | 
			
		||||
 | 
			
		||||
            // Start the alarm.
 | 
			
		||||
            val pendingIntent = getPendingIntent(context)
 | 
			
		||||
            context.alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
 | 
			
		||||
                    nextRun, intervalInMillis.toLong(), pendingIntent)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Stops the alarm if it's running.
 | 
			
		||||
         * @param context the application context.
 | 
			
		||||
         */
 | 
			
		||||
        fun stopAlarm(context: Context) {
 | 
			
		||||
            val pendingIntent = getPendingIntent(context)
 | 
			
		||||
            context.alarmManager.cancel(pendingIntent)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Returns broadcast intent
 | 
			
		||||
         * @param context the application context.
 | 
			
		||||
         * @return broadcast intent
 | 
			
		||||
         */
 | 
			
		||||
        fun getPendingIntent(context: Context): PendingIntent {
 | 
			
		||||
            return PendingIntent.getBroadcast(context, 0,
 | 
			
		||||
                    Intent(context, UpdateDownloaderAlarm::class.java).apply {
 | 
			
		||||
                        this.action = CHECK_UPDATE_ACTION
 | 
			
		||||
                    }, PendingIntent.FLAG_UPDATE_CURRENT)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    override fun onReceive(context: Context, intent: Intent) {
 | 
			
		||||
        when (intent.action) {
 | 
			
		||||
        // Start the alarm when the system is booted.
 | 
			
		||||
            Intent.ACTION_BOOT_COMPLETED -> startAlarm(context)
 | 
			
		||||
        // Update the library when the alarm fires an event.
 | 
			
		||||
            CHECK_UPDATE_ACTION -> checkVersion(context)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun checkVersion(context: Context) {
 | 
			
		||||
        if (DeviceUtil.isNetworkConnected(context)) {
 | 
			
		||||
            val updateChecker = GithubUpdateChecker(context)
 | 
			
		||||
            updateChecker.checkForApplicationUpdate()
 | 
			
		||||
                    .subscribeOn(Schedulers.io())
 | 
			
		||||
                    .observeOn(AndroidSchedulers.mainThread())
 | 
			
		||||
                    .subscribe({ release ->
 | 
			
		||||
                        //Get version of latest release
 | 
			
		||||
                        var newVersion = release.version
 | 
			
		||||
                        newVersion = newVersion.replace("[^\\d.]".toRegex(), "")
 | 
			
		||||
 | 
			
		||||
                        //Check if latest version is different from current version
 | 
			
		||||
                        if (newVersion != BuildConfig.VERSION_NAME) {
 | 
			
		||||
                            val downloadLink = release.downloadLink
 | 
			
		||||
 | 
			
		||||
                            val n = context.notification() {
 | 
			
		||||
                                setContentTitle(context.getString(R.string.update_check_notification_update_available))
 | 
			
		||||
                                addAction(android.R.drawable.stat_sys_download_done, context.getString(eu.kanade.tachiyomi.R.string.action_download),
 | 
			
		||||
                                        UpdateDownloader(context).getInstallOnReceivedIntent(UpdateDownloader.InstallOnReceived.RETRY_DOWNLOAD, downloadLink))
 | 
			
		||||
                                setSmallIcon(android.R.drawable.stat_sys_download_done)
 | 
			
		||||
                            }
 | 
			
		||||
                            // Displays the progress bar on notification
 | 
			
		||||
                            context.notificationManager.notify(0, n);
 | 
			
		||||
                        }
 | 
			
		||||
                    }, {
 | 
			
		||||
                        it.printStackTrace()
 | 
			
		||||
                    })
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,149 @@
 | 
			
		||||
package eu.kanade.tachiyomi.data.updater
 | 
			
		||||
 | 
			
		||||
import android.app.IntentService
 | 
			
		||||
import android.content.Context
 | 
			
		||||
import android.content.Intent
 | 
			
		||||
import android.net.Uri
 | 
			
		||||
import android.support.v4.app.NotificationCompat
 | 
			
		||||
import eu.kanade.tachiyomi.Constants.NOTIFICATION_UPDATER_ID
 | 
			
		||||
import eu.kanade.tachiyomi.R
 | 
			
		||||
import eu.kanade.tachiyomi.data.network.GET
 | 
			
		||||
import eu.kanade.tachiyomi.data.network.NetworkHelper
 | 
			
		||||
import eu.kanade.tachiyomi.data.network.ProgressListener
 | 
			
		||||
import eu.kanade.tachiyomi.data.network.newCallWithProgress
 | 
			
		||||
import eu.kanade.tachiyomi.util.notificationManager
 | 
			
		||||
import eu.kanade.tachiyomi.util.saveTo
 | 
			
		||||
import timber.log.Timber
 | 
			
		||||
import uy.kohesive.injekt.injectLazy
 | 
			
		||||
import java.io.File
 | 
			
		||||
 | 
			
		||||
class UpdateDownloaderService : IntentService(UpdateDownloaderService::class.java.name) {
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
        /**
 | 
			
		||||
         * Download url.
 | 
			
		||||
         */
 | 
			
		||||
        const val EXTRA_DOWNLOAD_URL = "eu.kanade.APP_DOWNLOAD_URL"
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Downloads a new update and let the user install the new version from a notification.
 | 
			
		||||
         * @param context the application context.
 | 
			
		||||
         * @param url the url to the new update.
 | 
			
		||||
         */
 | 
			
		||||
        fun downloadUpdate(context: Context, url: String) {
 | 
			
		||||
            val intent = Intent(context, UpdateDownloaderService::class.java).apply {
 | 
			
		||||
                putExtra(EXTRA_DOWNLOAD_URL, url)
 | 
			
		||||
            }
 | 
			
		||||
            context.startService(intent)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Prompt user with apk install intent
 | 
			
		||||
         * @param context context
 | 
			
		||||
         * @param file file of apk that is installed
 | 
			
		||||
         */
 | 
			
		||||
        fun installAPK(context: Context, file: File) {
 | 
			
		||||
            // Prompt install interface
 | 
			
		||||
            val intent = Intent(Intent.ACTION_VIEW).apply {
 | 
			
		||||
                setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive")
 | 
			
		||||
                // Without this flag android returned a intent error!
 | 
			
		||||
                flags = Intent.FLAG_ACTIVITY_NEW_TASK
 | 
			
		||||
            }
 | 
			
		||||
            context.startActivity(intent)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Network helper
 | 
			
		||||
     */
 | 
			
		||||
    private val network: NetworkHelper by injectLazy()
 | 
			
		||||
 | 
			
		||||
    override fun onHandleIntent(intent: Intent?) {
 | 
			
		||||
        if (intent == null) return
 | 
			
		||||
 | 
			
		||||
        val url = intent.getStringExtra(EXTRA_DOWNLOAD_URL) ?: return
 | 
			
		||||
        downloadApk(url)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun downloadApk(url: String) {
 | 
			
		||||
        val progressNotification = NotificationCompat.Builder(this)
 | 
			
		||||
 | 
			
		||||
        progressNotification.update {
 | 
			
		||||
            setContentTitle(getString(R.string.app_name))
 | 
			
		||||
            setContentText(getString(R.string.update_check_notification_download_in_progress))
 | 
			
		||||
            setSmallIcon(android.R.drawable.stat_sys_download)
 | 
			
		||||
            setOngoing(true)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Progress of the download
 | 
			
		||||
        var savedProgress = 0
 | 
			
		||||
 | 
			
		||||
        val progressListener = object : ProgressListener {
 | 
			
		||||
            override fun update(bytesRead: Long, contentLength: Long, done: Boolean) {
 | 
			
		||||
                val progress = (100 * bytesRead / contentLength).toInt()
 | 
			
		||||
                if (progress > savedProgress) {
 | 
			
		||||
                    savedProgress = progress
 | 
			
		||||
 | 
			
		||||
                    progressNotification.update { setProgress(100, progress, false) }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Reference the context for later usage inside apply blocks.
 | 
			
		||||
        val ctx = this
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            // Download the new update.
 | 
			
		||||
            val response = network.client.newCallWithProgress(GET(url), progressListener).execute()
 | 
			
		||||
 | 
			
		||||
            // File where the apk will be saved
 | 
			
		||||
            val apkFile = File(externalCacheDir, "update.apk")
 | 
			
		||||
 | 
			
		||||
            if (response.isSuccessful) {
 | 
			
		||||
                response.body().source().saveTo(apkFile)
 | 
			
		||||
            } else {
 | 
			
		||||
                response.close()
 | 
			
		||||
                throw Exception("Unsuccessful response")
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Prompt the user to install the new update.
 | 
			
		||||
            NotificationCompat.Builder(this).update {
 | 
			
		||||
                setContentTitle(getString(R.string.app_name))
 | 
			
		||||
                setContentText(getString(R.string.update_check_notification_download_complete))
 | 
			
		||||
                setSmallIcon(android.R.drawable.stat_sys_download_done)
 | 
			
		||||
                // Install action
 | 
			
		||||
                addAction(R.drawable.ic_system_update_grey_24dp_img,
 | 
			
		||||
                        getString(R.string.action_install),
 | 
			
		||||
                        UpdateNotificationReceiver.installApkIntent(ctx, apkFile.absolutePath))
 | 
			
		||||
                // Cancel action
 | 
			
		||||
                addAction(R.drawable.ic_clear_grey_24dp_img,
 | 
			
		||||
                        getString(R.string.action_cancel),
 | 
			
		||||
                        UpdateNotificationReceiver.cancelNotificationIntent(ctx))
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        } catch (e: Exception) {
 | 
			
		||||
            Timber.e(e, e.message)
 | 
			
		||||
 | 
			
		||||
            // Prompt the user to retry the download.
 | 
			
		||||
            NotificationCompat.Builder(this).update {
 | 
			
		||||
                setContentTitle(getString(R.string.app_name))
 | 
			
		||||
                setContentText(getString(R.string.update_check_notification_download_error))
 | 
			
		||||
                setSmallIcon(android.R.drawable.stat_sys_download_done)
 | 
			
		||||
                // Retry action
 | 
			
		||||
                addAction(R.drawable.ic_refresh_grey_24dp_img,
 | 
			
		||||
                        getString(R.string.action_retry),
 | 
			
		||||
                        UpdateNotificationReceiver.downloadApkIntent(ctx, url))
 | 
			
		||||
                // Cancel action
 | 
			
		||||
                addAction(R.drawable.ic_clear_grey_24dp_img,
 | 
			
		||||
                        getString(R.string.action_cancel),
 | 
			
		||||
                        UpdateNotificationReceiver.cancelNotificationIntent(ctx))
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun NotificationCompat.Builder.update(block: NotificationCompat.Builder.() -> Unit) {
 | 
			
		||||
        block()
 | 
			
		||||
        notificationManager.notify(NOTIFICATION_UPDATER_ID, build())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,67 @@
 | 
			
		||||
package eu.kanade.tachiyomi.data.updater
 | 
			
		||||
 | 
			
		||||
import android.app.PendingIntent
 | 
			
		||||
import android.content.BroadcastReceiver
 | 
			
		||||
import android.content.Context
 | 
			
		||||
import android.content.Intent
 | 
			
		||||
import eu.kanade.tachiyomi.Constants.NOTIFICATION_UPDATER_ID
 | 
			
		||||
import eu.kanade.tachiyomi.util.notificationManager
 | 
			
		||||
import java.io.File
 | 
			
		||||
 | 
			
		||||
class UpdateNotificationReceiver : BroadcastReceiver() {
 | 
			
		||||
 | 
			
		||||
    override fun onReceive(context: Context, intent: Intent) {
 | 
			
		||||
        when (intent.action) {
 | 
			
		||||
            ACTION_INSTALL_APK -> {
 | 
			
		||||
                UpdateDownloaderService.installAPK(context,
 | 
			
		||||
                        File(intent.getStringExtra(EXTRA_FILE_LOCATION)))
 | 
			
		||||
                cancelNotification(context)
 | 
			
		||||
            }
 | 
			
		||||
            ACTION_DOWNLOAD_UPDATE -> UpdateDownloaderService.downloadUpdate(context,
 | 
			
		||||
                    intent.getStringExtra(UpdateDownloaderService.EXTRA_DOWNLOAD_URL))
 | 
			
		||||
            ACTION_CANCEL_NOTIFICATION -> cancelNotification(context)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun cancelNotification(context: Context) {
 | 
			
		||||
        context.notificationManager.cancel(NOTIFICATION_UPDATER_ID)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
        // Install apk action
 | 
			
		||||
        const val ACTION_INSTALL_APK = "eu.kanade.INSTALL_APK"
 | 
			
		||||
 | 
			
		||||
        // Download apk action
 | 
			
		||||
        const val ACTION_DOWNLOAD_UPDATE = "eu.kanade.RETRY_DOWNLOAD"
 | 
			
		||||
 | 
			
		||||
        // Cancel notification action
 | 
			
		||||
        const val ACTION_CANCEL_NOTIFICATION = "eu.kanade.CANCEL_NOTIFICATION"
 | 
			
		||||
 | 
			
		||||
        // Absolute path of apk file
 | 
			
		||||
        const val EXTRA_FILE_LOCATION = "file_location"
 | 
			
		||||
 | 
			
		||||
        fun cancelNotificationIntent(context: Context): PendingIntent {
 | 
			
		||||
            val intent = Intent(context, UpdateNotificationReceiver::class.java).apply {
 | 
			
		||||
                action = ACTION_CANCEL_NOTIFICATION
 | 
			
		||||
            }
 | 
			
		||||
            return PendingIntent.getBroadcast(context, 0, intent, 0)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        fun installApkIntent(context: Context, path: String): PendingIntent {
 | 
			
		||||
            val intent = Intent(context, UpdateNotificationReceiver::class.java).apply {
 | 
			
		||||
                action = ACTION_INSTALL_APK
 | 
			
		||||
                putExtra(EXTRA_FILE_LOCATION, path)
 | 
			
		||||
            }
 | 
			
		||||
            return PendingIntent.getBroadcast(context, 0, intent, 0)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        fun downloadApkIntent(context: Context, url: String): PendingIntent {
 | 
			
		||||
            val intent = Intent(context, UpdateNotificationReceiver::class.java).apply {
 | 
			
		||||
                action = ACTION_DOWNLOAD_UPDATE
 | 
			
		||||
                putExtra(UpdateDownloaderService.EXTRA_DOWNLOAD_URL, url)
 | 
			
		||||
            }
 | 
			
		||||
            return PendingIntent.getBroadcast(context, 0, intent, 0)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -1,18 +1,21 @@
 | 
			
		||||
package eu.kanade.tachiyomi.ui.setting
 | 
			
		||||
 | 
			
		||||
import android.os.Bundle
 | 
			
		||||
import android.support.v7.preference.SwitchPreferenceCompat
 | 
			
		||||
import android.support.v7.preference.XpPreferenceFragment
 | 
			
		||||
import android.view.View
 | 
			
		||||
import com.afollestad.materialdialogs.MaterialDialog
 | 
			
		||||
import eu.kanade.tachiyomi.BuildConfig
 | 
			
		||||
import eu.kanade.tachiyomi.R
 | 
			
		||||
import eu.kanade.tachiyomi.data.updater.GithubUpdateChecker
 | 
			
		||||
import eu.kanade.tachiyomi.data.updater.UpdateDownloader
 | 
			
		||||
import eu.kanade.tachiyomi.data.updater.GithubUpdateResult
 | 
			
		||||
import eu.kanade.tachiyomi.data.updater.UpdateCheckerService
 | 
			
		||||
import eu.kanade.tachiyomi.data.updater.UpdateDownloaderService
 | 
			
		||||
import eu.kanade.tachiyomi.util.toast
 | 
			
		||||
import net.xpece.android.support.preference.SwitchPreference
 | 
			
		||||
import rx.Subscription
 | 
			
		||||
import rx.android.schedulers.AndroidSchedulers
 | 
			
		||||
import rx.schedulers.Schedulers
 | 
			
		||||
import timber.log.Timber
 | 
			
		||||
import java.text.DateFormat
 | 
			
		||||
import java.text.ParseException
 | 
			
		||||
import java.text.SimpleDateFormat
 | 
			
		||||
@@ -22,15 +25,15 @@ class SettingsAboutFragment : SettingsFragment() {
 | 
			
		||||
    /**
 | 
			
		||||
     * Checks for new releases
 | 
			
		||||
     */
 | 
			
		||||
    private val updateChecker by lazy { GithubUpdateChecker(activity) }
 | 
			
		||||
    private val updateChecker by lazy { GithubUpdateChecker() }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The subscribtion service of the obtained release object
 | 
			
		||||
     */
 | 
			
		||||
    private var releaseSubscription: Subscription? = null
 | 
			
		||||
 | 
			
		||||
    val automaticUpdateToggle by lazy {
 | 
			
		||||
        findPreference(getString(R.string.pref_enable_automatic_updates_key)) as SwitchPreferenceCompat
 | 
			
		||||
    val automaticUpdates by lazy {
 | 
			
		||||
        findPreference(getString(R.string.pref_enable_automatic_updates_key)) as SwitchPreference
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
@@ -59,13 +62,17 @@ class SettingsAboutFragment : SettingsFragment() {
 | 
			
		||||
                true
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            //TODO One glorious day enable this and add the magnificent option for auto update checking.
 | 
			
		||||
            // automaticUpdateToggle.isEnabled = true
 | 
			
		||||
            //            automaticUpdateToggle.setOnPreferenceChangeListener { preference, any ->
 | 
			
		||||
            //                val status = any as Boolean
 | 
			
		||||
            //                UpdateDownloaderAlarm.startAlarm(activity, 12, status)
 | 
			
		||||
            //                true
 | 
			
		||||
            //            }
 | 
			
		||||
            automaticUpdates.setOnPreferenceChangeListener { preference, any ->
 | 
			
		||||
                val checked = any as Boolean
 | 
			
		||||
                if (checked) {
 | 
			
		||||
                    UpdateCheckerService.setupTask(context)
 | 
			
		||||
                } else {
 | 
			
		||||
                    UpdateCheckerService.cancelTask(context)
 | 
			
		||||
                }
 | 
			
		||||
                true
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            automaticUpdates.isVisible = false
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        buildTime.summary = getFormattedBuildTime()
 | 
			
		||||
@@ -98,36 +105,35 @@ class SettingsAboutFragment : SettingsFragment() {
 | 
			
		||||
    private fun checkVersion() {
 | 
			
		||||
        releaseSubscription?.unsubscribe()
 | 
			
		||||
 | 
			
		||||
        releaseSubscription = updateChecker.checkForApplicationUpdate()
 | 
			
		||||
        context.toast(R.string.update_check_look_for_updates)
 | 
			
		||||
 | 
			
		||||
        releaseSubscription = updateChecker.checkForUpdate()
 | 
			
		||||
                .subscribeOn(Schedulers.io())
 | 
			
		||||
                .observeOn(AndroidSchedulers.mainThread())
 | 
			
		||||
                .subscribe({ release ->
 | 
			
		||||
                    //Get version of latest release
 | 
			
		||||
                    var newVersion = release.version
 | 
			
		||||
                    newVersion = newVersion.replace("[^\\d.]".toRegex(), "")
 | 
			
		||||
                .subscribe({ result ->
 | 
			
		||||
                    when (result) {
 | 
			
		||||
                        is GithubUpdateResult.NewUpdate -> {
 | 
			
		||||
                            val body = result.release.changeLog
 | 
			
		||||
                            val url = result.release.downloadLink
 | 
			
		||||
 | 
			
		||||
                    //Check if latest version is different from current version
 | 
			
		||||
                    if (newVersion != BuildConfig.VERSION_NAME) {
 | 
			
		||||
                        val downloadLink = release.downloadLink
 | 
			
		||||
                        val body = release.changeLog
 | 
			
		||||
 | 
			
		||||
                        //Create confirmation window
 | 
			
		||||
                        MaterialDialog.Builder(activity)
 | 
			
		||||
                                .title(R.string.update_check_title)
 | 
			
		||||
                                .content(body)
 | 
			
		||||
                                .positiveText(getString(R.string.update_check_confirm))
 | 
			
		||||
                                .negativeText(getString(R.string.update_check_ignore))
 | 
			
		||||
                                .onPositive { dialog, which ->
 | 
			
		||||
                                    // User output that download has started
 | 
			
		||||
                                    activity.toast(R.string.update_check_download_started)
 | 
			
		||||
                                    // Start download
 | 
			
		||||
                                    UpdateDownloader(activity.applicationContext).execute(downloadLink)
 | 
			
		||||
                                }.show()
 | 
			
		||||
                    } else {
 | 
			
		||||
                        activity.toast(R.string.update_check_no_new_updates)
 | 
			
		||||
                            // Create confirmation window
 | 
			
		||||
                            MaterialDialog.Builder(context)
 | 
			
		||||
                                    .title(R.string.update_check_title)
 | 
			
		||||
                                    .content(body)
 | 
			
		||||
                                    .positiveText(getString(R.string.update_check_confirm))
 | 
			
		||||
                                    .negativeText(getString(R.string.update_check_ignore))
 | 
			
		||||
                                    .onPositive { dialog, which ->
 | 
			
		||||
                                        // Start download
 | 
			
		||||
                                        UpdateDownloaderService.downloadUpdate(context, url)
 | 
			
		||||
                                    }
 | 
			
		||||
                                    .show()
 | 
			
		||||
                        }
 | 
			
		||||
                        is GithubUpdateResult.NoNewUpdate -> {
 | 
			
		||||
                            context.toast(R.string.update_check_no_new_updates)
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }, {
 | 
			
		||||
                    it.printStackTrace()
 | 
			
		||||
                }, { error ->
 | 
			
		||||
                    Timber.e(error, error.message)
 | 
			
		||||
                })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -12,12 +12,11 @@
 | 
			
		||||
            android:summary="@string/pref_acra_summary"
 | 
			
		||||
            android:title="@string/pref_enable_acra"/>
 | 
			
		||||
 | 
			
		||||
        <!--<SwitchPreferenceCompat-->
 | 
			
		||||
        <!--android:defaultValue="false"-->
 | 
			
		||||
        <!--android:enabled="false"-->
 | 
			
		||||
        <!--android:key="@string/pref_enable_automatic_updates_key"-->
 | 
			
		||||
        <!--android:summary="@string/pref_enable_automatic_updates_summary"-->
 | 
			
		||||
        <!--android:title="@string/pref_enable_automatic_updates"/>-->
 | 
			
		||||
        <SwitchPreference
 | 
			
		||||
            android:defaultValue="false"
 | 
			
		||||
            android:key="@string/pref_enable_automatic_updates_key"
 | 
			
		||||
            android:summary="@string/pref_enable_automatic_updates_summary"
 | 
			
		||||
            android:title="@string/pref_enable_automatic_updates"/>
 | 
			
		||||
 | 
			
		||||
        <Preference
 | 
			
		||||
            android:key="@string/pref_version"
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user