diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 7f9ce9ad9..00da616d5 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
-<manifest package="eu.kanade.tachiyomi"
-          xmlns:android="http://schemas.android.com/apk/res/android">
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="eu.kanade.tachiyomi">
 
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
@@ -68,7 +68,19 @@
         </receiver>
 
         <receiver
-            android:name=".data.library.LibraryUpdateService$LibraryUpdateReceiver">
+            android:name=".data.library.LibraryUpdateService$SyncOnPowerConnected"
+            android:enabled="false">
+            <intent-filter>
+                <action android:name="android.intent.action.ACTION_POWER_CONNECTED" />
+            </intent-filter>
+        </receiver>
+
+        <receiver
+            android:name=".data.library.LibraryUpdateService$CancelUpdateReceiver">
+        </receiver>
+
+        <receiver
+            android:name=".data.updater.UpdateDownloader$InstallOnReceived">
         </receiver>
 
         <receiver
@@ -79,6 +91,15 @@
             </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.cache.CoverGlideModule"
             android:value="GlideModule" />
diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt
index 3aaaf00ce..f85e5a48c 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt
@@ -9,6 +9,8 @@ import android.os.IBinder
 import android.os.PowerManager
 import android.support.v4.app.NotificationCompat
 import android.util.Pair
+import com.github.pwittchen.reactivenetwork.library.ConnectivityStatus
+import com.github.pwittchen.reactivenetwork.library.ReactiveNetwork
 import eu.kanade.tachiyomi.App
 import eu.kanade.tachiyomi.R
 import eu.kanade.tachiyomi.data.database.DatabaseHelper
@@ -16,42 +18,14 @@ import eu.kanade.tachiyomi.data.database.models.Manga
 import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.data.source.SourceManager
 import eu.kanade.tachiyomi.ui.main.MainActivity
-import eu.kanade.tachiyomi.util.AndroidComponentUtil
-import eu.kanade.tachiyomi.util.DeviceUtil
-import eu.kanade.tachiyomi.util.notification
-import eu.kanade.tachiyomi.util.notificationManager
+import eu.kanade.tachiyomi.util.*
 import rx.Observable
 import rx.Subscription
 import rx.schedulers.Schedulers
-import timber.log.Timber
 import java.util.*
 import java.util.concurrent.atomic.AtomicInteger
 import javax.inject.Inject
 
-// Intent key for forced library update
-val UPDATE_IS_FORCED = "is_forced"
-
-/**
- * Get the start intent for [LibraryUpdateService].
- * @param context the application context.
- * @param isForced true when forcing library update
- * @return the intent of the service.
- */
-fun getIntent(context: Context, isForced: Boolean = false): Intent {
-    return Intent(context, LibraryUpdateService::class.java).apply {
-        putExtra(UPDATE_IS_FORCED, isForced)
-    }
-}
-
-/**
- * Returns the status of the service.
- * @param context the application context.
- * @return true if the service is running, false otherwise.
- */
-fun isRunning(context: Context): Boolean {
-    return AndroidComponentUtil.isServiceRunning(context, LibraryUpdateService::class.java)
-}
-
 /**
  * This class will take care of updating the chapters of the manga from the library. It can be
  * started calling the [start] method. If it's already running, it won't do anything.
@@ -77,6 +51,30 @@ class LibraryUpdateService : Service() {
     companion object {
         val UPDATE_NOTIFICATION_ID = 1
 
+        // Intent key for manual library update
+        val UPDATE_IS_MANUAL = "is_manual"
+
+        /**
+         * Get the start intent for [LibraryUpdateService].
+         * @param context the application context.
+         * @param isManual true when user triggers library update.
+         * @return the intent of the service.
+         */
+        fun getIntent(context: Context, isManual: Boolean = false): Intent {
+            return Intent(context, LibraryUpdateService::class.java).apply {
+                putExtra(UPDATE_IS_MANUAL, isManual)
+            }
+        }
+
+        /**
+         * Returns the status of the service.
+         * @param context the application context.
+         * @return true if the service is running, false otherwise.
+         */
+        fun isRunning(context: Context): Boolean {
+            return AndroidComponentUtil.isServiceRunning(context, LibraryUpdateService::class.java)
+        }
+
         /**
          * Static method to start the service. It will be started only if there isn't another
          * instance already running.
@@ -125,36 +123,52 @@ class LibraryUpdateService : Service() {
 
 
     /**
-     * Method called when the service receives an intent. In this case, the content of the intent
-     * is irrelevant, because everything required is fetched in [updateLibrary].
-     * @param intent the intent from [start].
+     * Method called when the service receives an intent.
+     * @param intent the start intent from.
      * @param flags the flags of the command.
      * @param startId the start id of this command.
      * @return the start value of the command.
      */
     override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
-        // If there's no network available, set a component to start this service again when
-        // a connection is available.
-        if (!DeviceUtil.isNetworkConnected(this)) {
-            Timber.i("Sync canceled, connection not available")
-            showWarningNotification(getString(R.string.notification_no_connection_title),
-                    getString(R.string.notification_no_connection_body))
+
+        // Get connectivity status
+        val connection = ReactiveNetwork().getConnectivityStatus(this, true)
+
+        // Get library update restrictions
+        val restrictions = preferences.libraryUpdateRestriction()
+
+        // Check if users updates library manual
+        val isManualUpdate = intent?.getBooleanExtra(UPDATE_IS_MANUAL, false) ?: false
+
+        // Whether to cancel the update.
+        var cancelUpdate = false
+
+        // Check if device has internet connection
+        // Check if device has wifi connection if only wifi is enabled
+        if (connection == ConnectivityStatus.OFFLINE || ("wifi" in restrictions
+                && connection != ConnectivityStatus.WIFI_CONNECTED_HAS_INTERNET)) {
+
+            if (isManualUpdate) {
+                toast(R.string.notification_no_connection_title)
+            }
+
+            // Enable library update when connection available
             AndroidComponentUtil.toggleComponent(this, SyncOnConnectionAvailable::class.java, true)
+            cancelUpdate = true
+        }
+        if (!isManualUpdate && "ac" in restrictions && !DeviceUtil.isPowerConnected(this)) {
+            AndroidComponentUtil.toggleComponent(this, SyncOnPowerConnected::class.java, true)
+            cancelUpdate = true
+        }
+
+        if (cancelUpdate) {
             stopSelf(startId)
             return Service.START_NOT_STICKY
         }
 
-        // If user doesn't want to update while phone is not charging, cancel sync
-        else if (preferences.updateOnlyWhenCharging() && !(intent?.getBooleanExtra(UPDATE_IS_FORCED, false) ?: false) && !DeviceUtil.isPowerConnected(this)) {
-            Timber.i("Sync canceled, not connected to ac power")
-            // Create force library update intent
-            val forceIntent = getLibraryUpdateReceiverIntent(LibraryUpdateReceiver.FORCE_LIBRARY_UPDATE)
-            // Show warning
-            showWarningNotification(getString(R.string.notification_not_connected_to_ac_title),
-                    getString(R.string.notification_not_connected_to_ac_body), forceIntent)
-            stopSelf(startId)
-            return Service.START_NOT_STICKY
-        }
+        // Stop enabled components.
+        AndroidComponentUtil.toggleComponent(this, SyncOnConnectionAvailable::class.java, false)
+        AndroidComponentUtil.toggleComponent(this, SyncOnPowerConnected::class.java, false)
 
         // Unsubscribe from any previous subscription if needed.
         subscription?.unsubscribe()
@@ -168,20 +182,11 @@ class LibraryUpdateService : Service() {
                             stopSelf(startId)
                         }, {
                             stopSelf(startId)
-                })
+                        })
 
         return Service.START_STICKY
     }
 
-    /**
-     * Creates a PendingIntent for LibraryUpdate broadcast class
-     * @param action id of action
-     */
-    fun getLibraryUpdateReceiverIntent(action: String): PendingIntent {
-        return PendingIntent.getBroadcast(this, 0,
-                Intent(this, LibraryUpdateReceiver::class.java).apply { this.action = action }, 0)
-    }
-
     /**
      * Method that updates the library. It's called in a background thread, so it's safe to do
      * heavy operations or network calls here.
@@ -195,7 +200,8 @@ class LibraryUpdateService : Service() {
         val newUpdates = ArrayList<Manga>()
         val failedUpdates = ArrayList<Manga>()
 
-        val cancelIntent = getLibraryUpdateReceiverIntent(LibraryUpdateReceiver.CANCEL_LIBRARY_UPDATE)
+        val cancelIntent = PendingIntent.getBroadcast(this, 0,
+                Intent(this, CancelUpdateReceiver::class.java), 0)
 
         // Get the manga list that is going to be updated.
         val allLibraryMangas = db.getFavoriteMangas().executeAsBlocking()
@@ -299,12 +305,11 @@ class LibraryUpdateService : Service() {
      * @param body the body of the notification.
      */
     private fun showNotification(title: String, body: String) {
-        val n = notification() {
+        notificationManager.notify(UPDATE_NOTIFICATION_ID, notification() {
             setSmallIcon(R.drawable.ic_refresh_white_24dp_img)
             setContentTitle(title)
             setContentText(body)
-        }
-        notificationManager.notify(UPDATE_NOTIFICATION_ID, n)
+        })
     }
 
     /**
@@ -314,35 +319,15 @@ class LibraryUpdateService : Service() {
      * @param total the total progress.
      */
     private fun showProgressNotification(manga: Manga, current: Int, total: Int, cancelIntent: PendingIntent) {
-        val n = notification() {
+        notificationManager.notify(UPDATE_NOTIFICATION_ID, notification() {
             setSmallIcon(R.drawable.ic_refresh_white_24dp_img)
             setContentTitle(manga.title)
             setProgress(total, current, false)
             setOngoing(true)
             addAction(R.drawable.ic_clear_grey_24dp_img, getString(android.R.string.cancel), cancelIntent)
-        }
-        notificationManager.notify(UPDATE_NOTIFICATION_ID, n)
+        })
     }
 
-    /**
-     * Show warning message when library can't be updated
-     * @param warningTitle title of warning
-     * @param warningBody warning information
-     * @param pendingIntent Intent called when action clicked
-     */
-    private fun showWarningNotification(warningTitle: String, warningBody: String, pendingIntent: PendingIntent? = null) {
-        val n = notification() {
-            setSmallIcon(R.drawable.ic_warning_white_24dp_img)
-            setContentTitle(warningTitle)
-            setStyle(NotificationCompat.BigTextStyle().bigText(warningBody))
-            setContentIntent(notificationIntent)
-            if (pendingIntent != null) {
-                addAction(R.drawable.ic_refresh_grey_24dp_img, getString(R.string.action_force), pendingIntent)
-            }
-            setAutoCancel(true)
-        }
-        notificationManager.notify(UPDATE_NOTIFICATION_ID, n)
-    }
 
     /**
      * Shows the notification containing the result of the update done by the service.
@@ -353,14 +338,13 @@ class LibraryUpdateService : Service() {
         val title = getString(R.string.notification_update_completed)
         val body = getUpdatedMangasBody(updates, failed)
 
-        val n = notification() {
+        notificationManager.notify(UPDATE_NOTIFICATION_ID, notification() {
             setSmallIcon(R.drawable.ic_refresh_white_24dp_img)
             setContentTitle(title)
             setStyle(NotificationCompat.BigTextStyle().bigText(body))
             setContentIntent(notificationIntent)
             setAutoCancel(true)
-        }
-        notificationManager.notify(UPDATE_NOTIFICATION_ID, n)
+        })
     }
 
     /**
@@ -385,7 +369,6 @@ class LibraryUpdateService : Service() {
      * network changes.
      */
     class SyncOnConnectionAvailable : BroadcastReceiver() {
-
         /**
          * Method called when a network change occurs.
          * @param context the application context.
@@ -394,35 +377,38 @@ class LibraryUpdateService : Service() {
         override fun onReceive(context: Context, intent: Intent) {
             if (DeviceUtil.isNetworkConnected(context)) {
                 AndroidComponentUtil.toggleComponent(context, this.javaClass, false)
-                context.startService(getIntent(context))
+                start(context)
             }
         }
     }
 
     /**
-     * Class that triggers the library to update.
+     * Class that triggers the library to update when connected to power.
      */
-    class LibraryUpdateReceiver : BroadcastReceiver() {
-        companion object {
-            // Cancel library update action
-            val CANCEL_LIBRARY_UPDATE = "eu.kanade.CANCEL_LIBRARY_UPDATE"
-            // Force library update
-            val FORCE_LIBRARY_UPDATE = "eu.kanade.FORCE_LIBRARY_UPDATE"
+    class SyncOnPowerConnected: BroadcastReceiver() {
+        /**
+         * Method called when AC is connected.
+         * @param context the application context.
+         * @param intent the intent received.
+         */
+        override fun onReceive(context: Context, intent: Intent) {
+            AndroidComponentUtil.toggleComponent(context, this.javaClass, false)
+            start(context)
         }
+    }
 
+    /**
+     * Class that stops updating the library.
+     */
+    class CancelUpdateReceiver : BroadcastReceiver() {
         /**
          * Method called when user wants a library update.
          * @param context the application context.
          * @param intent the intent received.
          */
         override fun onReceive(context: Context, intent: Intent) {
-            when (intent.action) {
-                CANCEL_LIBRARY_UPDATE -> {
-                    LibraryUpdateService.stop(context)
-                    context.notificationManager.cancel(UPDATE_NOTIFICATION_ID)
-                }
-                FORCE_LIBRARY_UPDATE -> LibraryUpdateService.start(context, true)
-            }
+            LibraryUpdateService.stop(context)
+            context.notificationManager.cancel(UPDATE_NOTIFICATION_ID)
         }
     }
 
diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt
index 1a6ae9ade..f17b15d26 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt
@@ -70,16 +70,17 @@ class PreferenceKeys(context: Context) {
 
     val removeAfterMarkedAsRead = context.getString(R.string.pref_remove_after_marked_as_read_key)
 
-    val updateOnlyWhenCharging = context.getString(R.string.pref_update_only_when_charging_key)
-
     val libraryUpdateInterval = context.getString(R.string.pref_library_update_interval_key)
 
+    val libraryUpdateRestriction = context.getString(R.string.pref_library_update_restriction_key)
+
     val filterDownloaded = context.getString(R.string.pref_filter_downloaded_key)
 
     val filterUnread = context.getString(R.string.pref_filter_unread_key)
 
     fun sourceUsername(sourceId: Int) = "pref_source_username_$sourceId"
 
+
     fun sourcePassword(sourceId: Int) = "pref_source_password_$sourceId"
 
     fun syncUsername(syncId: Int) = "pref_mangasync_username_$syncId"
diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt
index 01e91736e..335302de9 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt
@@ -39,6 +39,11 @@ class PreferencesHelper(private val context: Context) {
                     context.getString(R.string.pref_library_update_interval_key), 0)
         }
 
+        fun getAutomaticUpdateStatus(context: Context): Boolean {
+            return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(
+                    context.getString(R.string.pref_enable_automatic_updates), false)
+        }
+
         @JvmStatic
         fun getTheme(context: Context): Int {
             return PreferenceManager.getDefaultSharedPreferences(context).getInt(
@@ -132,10 +137,10 @@ class PreferencesHelper(private val context: Context) {
 
     fun removeAfterMarkedAsRead() = prefs.getBoolean(keys.removeAfterMarkedAsRead, false)
 
-    fun updateOnlyWhenCharging() = prefs.getBoolean(keys.updateOnlyWhenCharging, false)
-
     fun libraryUpdateInterval() = rxPrefs.getInteger(keys.libraryUpdateInterval, 0)
 
+    fun libraryUpdateRestriction() = prefs.getStringSet(keys.libraryUpdateRestriction, emptySet())
+
     fun filterDownloaded() = rxPrefs.getBoolean(keys.filterDownloaded, false)
 
     fun filterUnread() = rxPrefs.getBoolean(keys.filterUnread, false)
diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/updater/UpdateDownloader.java b/app/src/main/java/eu/kanade/tachiyomi/data/updater/UpdateDownloader.java
deleted file mode 100644
index e86098e07..000000000
--- a/app/src/main/java/eu/kanade/tachiyomi/data/updater/UpdateDownloader.java
+++ /dev/null
@@ -1,99 +0,0 @@
-package eu.kanade.tachiyomi.data.updater;
-
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.AsyncTask;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.InputStream;
-import java.net.HttpURLConnection;
-import java.net.URL;
-
-import javax.inject.Inject;
-
-import eu.kanade.tachiyomi.App;
-import eu.kanade.tachiyomi.data.preference.PreferencesHelper;
-
-public class UpdateDownloader extends AsyncTask<String, Void, Void> {
-    /**
-     * Name of cache directory.
-     */
-    private static final String PARAMETER_CACHE_DIRECTORY = "apk_downloads";
-    /**
-     * Interface to global information about an application environment.
-     */
-    private final Context context;
-    /**
-     * Cache directory used for cache management.
-     */
-    private final File cacheDir;
-    @Inject PreferencesHelper preferencesHelper;
-
-    /**
-     * Constructor of UpdaterCache.
-     *
-     * @param context application environment interface.
-     */
-    public UpdateDownloader(Context context) {
-        App.get(context).getComponent().inject(this);
-        this.context = context;
-
-        // Get cache directory from parameter.
-        cacheDir = new File(preferencesHelper.downloadsDirectory().get(), PARAMETER_CACHE_DIRECTORY);
-
-        // Create cache directory.
-        createCacheDir();
-    }
-
-    /**
-     * Create cache directory if it doesn't exist
-     *
-     * @return true if cache dir is created otherwise false.
-     */
-    @SuppressWarnings("UnusedReturnValue")
-    private boolean createCacheDir() {
-        return !cacheDir.exists() && cacheDir.mkdirs();
-    }
-
-
-    @Override
-    protected Void doInBackground(String... args) {
-        try {
-            createCacheDir();
-
-            URL url = new URL(args[0]);
-            HttpURLConnection c = (HttpURLConnection) url.openConnection();
-            c.connect();
-
-            File outputFile = new File(cacheDir, "update.apk");
-            if (outputFile.exists()) {
-                //noinspection ResultOfMethodCallIgnored
-                outputFile.delete();
-            }
-            FileOutputStream fos = new FileOutputStream(outputFile);
-
-            InputStream is = c.getInputStream();
-
-            byte[] buffer = new byte[1024];
-            int len1;
-            while ((len1 = is.read(buffer)) != -1) {
-                fos.write(buffer, 0, len1);
-            }
-            fos.close();
-            is.close();
-
-            // Prompt install interface
-            Intent intent = new Intent(Intent.ACTION_VIEW);
-            intent.setDataAndType(Uri.fromFile(outputFile), "application/vnd.android.package-archive");
-            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // without this flag android returned a intent error!
-            context.startActivity(intent);
-
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-        return null;
-    }
-}
-
diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/updater/UpdateDownloader.kt b/app/src/main/java/eu/kanade/tachiyomi/data/updater/UpdateDownloader.kt
new file mode 100644
index 000000000..145c3bdee
--- /dev/null
+++ b/app/src/main/java/eu/kanade/tachiyomi/data/updater/UpdateDownloader.kt
@@ -0,0 +1,199 @@
+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.App
+import eu.kanade.tachiyomi.R
+import eu.kanade.tachiyomi.data.network.NetworkHelper
+import eu.kanade.tachiyomi.data.network.ProgressListener
+import eu.kanade.tachiyomi.data.network.get
+import eu.kanade.tachiyomi.util.notificationManager
+import eu.kanade.tachiyomi.util.saveTo
+import timber.log.Timber
+import java.io.File
+import javax.inject.Inject
+
+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)
+        }
+    }
+
+    @Inject lateinit var network: NetworkHelper
+
+    /**
+     * Default download dir
+     */
+    val apkFile = File(context.externalCacheDir, "update.apk")
+
+
+    /**
+     * Notification builder
+     */
+    val notificationBuilder = NotificationCompat.Builder(context)
+
+    init {
+        App.get(context).component.inject(this)
+    }
+
+    /**
+     * 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.requestBodyProgressBlocking(get(result.url), progressListener)
+
+            if (response.isSuccessful) {
+                response.body().source().saveTo(apkFile)
+                // Set download successful
+                result.successful = true
+            }
+        } 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(InstallOnReceived.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(InstallOnReceived.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
+            val INSTALL_APK = "eu.kanade.INSTALL_APK"
+
+            // Retry download action
+            val RETRY_DOWNLOAD = "eu.kanade.RETRY_DOWNLOAD"
+
+            // Retry download action
+            val CANCEL_NOTIFICATION = "eu.kanade.CANCEL_NOTIFICATION"
+
+            // Absolute path of file || URL of file
+            val FILE_LOCATION = "file_location"
+
+            // Id of the notification
+            val notificationId = 2
+        }
+
+        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(notificationId)
+            }
+        }
+
+    }
+}
diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/updater/UpdateDownloaderAlarm.kt b/app/src/main/java/eu/kanade/tachiyomi/data/updater/UpdateDownloaderAlarm.kt
new file mode 100644
index 000000000..b0258fd07
--- /dev/null
+++ b/app/src/main/java/eu/kanade/tachiyomi/data/updater/UpdateDownloaderAlarm.kt
@@ -0,0 +1,109 @@
+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
+
+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.
+         */
+        @JvmStatic
+        @JvmOverloads
+        fun startAlarm(context: Context, intervalInHours: Int = 12, isEnabled: Boolean = PreferencesHelper.getAutomaticUpdateStatus(context)) {
+            // 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()
+                    })
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseActivity.kt
index 06bf3a714..efe2218df 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseActivity.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseActivity.kt
@@ -73,5 +73,4 @@ open class BaseActivity : AppCompatActivity() {
         snack.f()
         snack.show()
     }
-
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAboutFragment.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAboutFragment.kt
index e094d5624..7c98fa71d 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAboutFragment.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAboutFragment.kt
@@ -1,6 +1,7 @@
 package eu.kanade.tachiyomi.ui.setting
 
 import android.os.Bundle
+import android.support.v7.preference.SwitchPreferenceCompat
 import android.view.View
 import com.afollestad.materialdialogs.MaterialDialog
 import eu.kanade.tachiyomi.BuildConfig
@@ -27,6 +28,10 @@ class SettingsAboutFragment : SettingsNestedFragment() {
      */
     private var releaseSubscription: Subscription? = null
 
+    val automaticUpdateToggle by lazy {
+        findPreference(getString(R.string.pref_enable_automatic_updates_key)) as SwitchPreferenceCompat
+    }
+
     companion object {
 
         fun newInstance(resourcePreference: Int, resourceTitle: Int): SettingsNestedFragment {
@@ -45,11 +50,19 @@ class SettingsAboutFragment : SettingsNestedFragment() {
         else
             BuildConfig.VERSION_NAME
 
-        //Set onClickListener to check for new version
-        version.setOnPreferenceClickListener {
-            if (!BuildConfig.DEBUG && BuildConfig.INCLUDE_UPDATER)
-                checkVersion()
-            true
+        if (!BuildConfig.DEBUG && BuildConfig.INCLUDE_UPDATER) {
+            //Set onClickListener to check for new version
+            version.setOnPreferenceClickListener {
+                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
+            //            }
         }
 
         buildTime.summary = getFormattedBuildTime()
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsGeneralFragment.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsGeneralFragment.kt
index d99741fc8..2e81d577b 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsGeneralFragment.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsGeneralFragment.kt
@@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.ui.setting
 
 import android.content.Intent
 import android.os.Bundle
+import android.support.v14.preference.MultiSelectListPreference
 import android.support.v4.app.TaskStackBuilder
 import android.support.v7.preference.Preference
 import android.view.View
@@ -33,13 +34,28 @@ class SettingsGeneralFragment : SettingsNestedFragment() {
         findPreference(getString(R.string.pref_library_update_interval_key)) as IntListPreference
     }
 
+    val updateRestriction by lazy {
+        findPreference(getString(R.string.pref_library_update_restriction_key)) as MultiSelectListPreference
+    }
+
     val themePreference by lazy {
         findPreference(getString(R.string.pref_theme_key)) as IntListPreference
     }
 
+    var updateIntervalSubscription: Subscription? = null
+
     var columnsSubscription: Subscription? = null
 
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+        updateIntervalSubscription = preferences.libraryUpdateInterval().asObservable()
+                .subscribe { updateRestriction.isVisible = it > 0 }
+
+        columnsSubscription = Observable.combineLatest(
+                preferences.portraitColumns().asObservable(),
+                preferences.landscapeColumns().asObservable())
+                { portraitColumns, landscapeColumns -> Pair(portraitColumns, landscapeColumns) }
+                .subscribe { updateColumnsSummary(it.first, it.second) }
+
         updateInterval.setOnPreferenceChangeListener { preference, newValue ->
             LibraryUpdateAlarm.startAlarm(activity, (newValue as String).toInt())
             true
@@ -57,17 +73,11 @@ class SettingsGeneralFragment : SettingsNestedFragment() {
         }
     }
 
-    override fun onResume() {
-        super.onResume()
-        columnsSubscription = Observable.combineLatest(preferences.portraitColumns().asObservable(),
-                preferences.landscapeColumns().asObservable(),
-                { portraitColumns, landscapeColumns -> Pair(portraitColumns, landscapeColumns) })
-                .subscribe { updateColumnsSummary(it.first, it.second) }
-    }
-
-    override fun onPause() {
+    override fun onDestroyView() {
+        updateIntervalSubscription?.unsubscribe()
         columnsSubscription?.unsubscribe()
-        super.onPause()
+        super.onDestroyView()
+
     }
 
     override fun onDisplayPreferenceDialog(preference: Preference) {
diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/DeviceUtil.kt b/app/src/main/java/eu/kanade/tachiyomi/util/DeviceUtil.kt
index beab475dd..e7dc9e559 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/util/DeviceUtil.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/util/DeviceUtil.kt
@@ -11,7 +11,7 @@ object DeviceUtil {
         val intent = context.registerReceiver(null, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
         intent?.let {
             val plugged = it.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1)
-            return plugged == BatteryManager.BATTERY_PLUGGED_AC || plugged == BatteryManager.BATTERY_PLUGGED_USB
+            return plugged == BatteryManager.BATTERY_PLUGGED_AC || plugged == BatteryManager.BATTERY_PLUGGED_USB || plugged == BatteryManager.BATTERY_PLUGGED_WIRELESS
         }
         return false
     }
diff --git a/app/src/main/res/drawable-hdpi/ic_system_update_grey_24dp_img.png b/app/src/main/res/drawable-hdpi/ic_system_update_grey_24dp_img.png
new file mode 100644
index 000000000..51cf94d80
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_system_update_grey_24dp_img.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_system_update_grey_24dp_img.png b/app/src/main/res/drawable-mdpi/ic_system_update_grey_24dp_img.png
new file mode 100644
index 000000000..33cca7074
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_system_update_grey_24dp_img.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_system_update_grey_24dp_img.png b/app/src/main/res/drawable-xhdpi/ic_system_update_grey_24dp_img.png
new file mode 100644
index 000000000..37db7d1d4
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_system_update_grey_24dp_img.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_system_update_grey_24dp_img.png b/app/src/main/res/drawable-xxhdpi/ic_system_update_grey_24dp_img.png
new file mode 100644
index 000000000..d24aba7b2
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_system_update_grey_24dp_img.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_system_update_grey_24dp_img.png b/app/src/main/res/drawable-xxxhdpi/ic_system_update_grey_24dp_img.png
new file mode 100644
index 000000000..8fa116da7
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_system_update_grey_24dp_img.png differ
diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml
index ce38a3eba..40b2c301c 100644
--- a/app/src/main/res/values/arrays.xml
+++ b/app/src/main/res/values/arrays.xml
@@ -126,4 +126,14 @@
         <item>48</item>
     </string-array>
 
+    <string-array name="library_update_restrictions">
+        <item>@string/wifi</item>
+        <item>@string/charging</item>
+    </string-array>
+
+    <string-array name="library_update_restrictions_values">
+        <item>wifi</item>
+        <item>ac</item>
+    </string-array>
+
 </resources>
\ No newline at end of file
diff --git a/app/src/main/res/values/keys.xml b/app/src/main/res/values/keys.xml
index d7cb6da96..c0f8b2ecc 100644
--- a/app/src/main/res/values/keys.xml
+++ b/app/src/main/res/values/keys.xml
@@ -13,10 +13,10 @@
     <string name="pref_library_columns_landscape_key">pref_library_columns_landscape_key</string>
     <string name="pref_library_update_interval_key">pref_library_update_interval_key</string>
     <string name="pref_update_only_non_completed_key">pref_update_only_non_completed_key</string>
-    <string name="pref_update_only_when_charging_key">pref_update_only_when_charging_key</string>
     <string name="pref_auto_update_manga_sync_key">pref_auto_update_manga_sync_key</string>
     <string name="pref_ask_update_manga_sync_key">pref_ask_update_manga_sync_key</string>
     <string name="pref_theme_key">pref_theme_key</string>
+    <string name="pref_library_update_restriction_key">library_update_restriction</string>
 
     <string name="pref_default_viewer_key">pref_default_viewer_key</string>
     <string name="pref_image_scale_type_key">pref_image_scale_type_key</string>
@@ -52,8 +52,10 @@
     <string name="pref_clear_chapter_cache_key">pref_clear_chapter_cache_key</string>
     <string name="pref_clear_database_key">pref_clear_database_key</string>
 
+
     <string name="pref_version">pref_version</string>
     <string name="pref_build_time">pref_build_time</string>
+    <string name="pref_enable_automatic_updates_key">pref_enable_automatic_updates_key</string>
 
     <string name="pref_display_catalogue_as_list">pref_display_catalogue_as_list</string>
     <string name="pref_last_catalogue_source_key">pref_last_catalogue_source_key</string>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index b57a2edab..fec7a6ee5 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -51,6 +51,7 @@
     <string name="action_cancel">Cancel</string>
     <string name="action_sort">Sort</string>
     <string name="action_force">Force refresh</string>
+    <string name="action_install">Install</string>
 
     <!-- Operations -->
     <string name="deleting">Deleting…</string>
@@ -72,8 +73,6 @@
     <string name="landscape">Landscape</string>
     <string name="default_columns">Default</string>
     <string name="pref_library_update_interval">Library update frequency</string>
-    <string name="pref_update_only_non_completed">Only update incomplete manga</string>
-    <string name="pref_update_only_when_charging">Only update when charging</string>
     <string name="update_never">Manual</string>
     <string name="update_1hour">Hourly</string>
     <string name="update_2hour">Every 2 hours</string>
@@ -82,13 +81,17 @@
     <string name="update_12hour">Every 12 hours</string>
     <string name="update_24hour">Daily</string>
     <string name="update_48hour">Every 2 days</string>
+    <string name="pref_library_update_restriction">Library update restrictions</string>
+    <string name="pref_library_update_restriction_summary">Update only when the conditions are met</string>
+    <string name="wifi">Wi-Fi</string>
+    <string name="charging">Charging</string>
+    <string name="pref_update_only_non_completed">Only update incomplete manga</string>
     <string name="pref_auto_update_manga_sync">Sync chapters after reading</string>
     <string name="pref_ask_update_manga_sync">Confirm before updating</string>
     <string name="pref_theme">Application theme</string>
     <string name="light_theme">Main theme</string>
     <string name="dark_theme">Dark theme</string>
 
-
       <!-- Reader section -->
     <string name="pref_hide_status_bar">Hide status bar</string>
     <string name="pref_lock_orientation">Lock orientation</string>
@@ -166,7 +169,8 @@
       <!-- About section -->
     <string name="version">Version</string>
     <string name="build_time">Build time</string>
-
+    <string name="pref_enable_automatic_updates">Check for updates</string>
+    <string name="pref_enable_automatic_updates_summary">Automatically check for application updates</string>
     <!-- ACRA -->
     <string name="pref_enable_acra">Send crash reports</string>
     <string name="pref_acra_summary">Helps fix any bugs. No sensitive data will be sent</string>
@@ -282,6 +286,13 @@
     <string name="update_check_download_started">Download started</string>
     <string name="update_check_look_for_updates">Looking for updates</string>
 
+    <!--UpdateCheck Notifications-->
+    <string name="update_check_notification_file_download">Download update</string>
+    <string name="update_check_notification_download_in_progress">Download in progress</string>
+    <string name="update_check_notification_download_complete">Download complete</string>
+    <string name="update_check_notification_download_error">Download error</string>
+    <string name="update_check_notification_update_available">Update available</string>
+
     <!--Content Description-->
     <string name="description_backdrop">Backdrop image of selected manga</string>
     <string name="description_cover">Cover of selected manga</string>
diff --git a/app/src/main/res/xml/pref_about.xml b/app/src/main/res/xml/pref_about.xml
index d15d58c35..e4df24e83 100644
--- a/app/src/main/res/xml/pref_about.xml
+++ b/app/src/main/res/xml/pref_about.xml
@@ -3,19 +3,26 @@
     xmlns:android="http://schemas.android.com/apk/res/android">
 
     <SwitchPreferenceCompat
+        android:defaultValue="true"
         android:key="acra.enable"
-        android:title="@string/pref_enable_acra"
         android:summary="@string/pref_acra_summary"
-        android:defaultValue="true"/>
+        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"/>-->
 
     <Preference
         android:key="@string/pref_version"
-        android:title="@string/version"
-        android:persistent="false" />
+        android:persistent="false"
+        android:title="@string/version"/>
 
     <Preference
         android:key="@string/pref_build_time"
-        android:title="@string/build_time"
-        android:persistent="false" />
+        android:persistent="false"
+        android:title="@string/build_time"/>
 
 </android.support.v7.preference.PreferenceScreen>
\ No newline at end of file
diff --git a/app/src/main/res/xml/pref_advanced.xml b/app/src/main/res/xml/pref_advanced.xml
index 035a98d8c..ae20a4843 100644
--- a/app/src/main/res/xml/pref_advanced.xml
+++ b/app/src/main/res/xml/pref_advanced.xml
@@ -3,13 +3,13 @@
     xmlns:android="http://schemas.android.com/apk/res/android">
 
     <Preference
-        android:title="@string/pref_clear_chapter_cache"
-        android:key="@string/pref_clear_chapter_cache_key" />
+        android:key="@string/pref_clear_chapter_cache_key"
+        android:title="@string/pref_clear_chapter_cache"/>
 
     <Preference
-        android:title="@string/pref_clear_database"
         android:key="@string/pref_clear_database_key"
-        android:summary="@string/pref_clear_database_summary"/>
+        android:summary="@string/pref_clear_database_summary"
+        android:title="@string/pref_clear_database"/>
 
     <SwitchPreferenceCompat
         android:defaultValue="false"
diff --git a/app/src/main/res/xml/pref_general.xml b/app/src/main/res/xml/pref_general.xml
index 9b2d7251c..8d96330d3 100644
--- a/app/src/main/res/xml/pref_general.xml
+++ b/app/src/main/res/xml/pref_general.xml
@@ -24,14 +24,16 @@
         android:summary="%s"
         android:title="@string/pref_library_update_interval"/>
 
+    <MultiSelectListPreference
+        android:entries="@array/library_update_restrictions"
+        android:entryValues="@array/library_update_restrictions_values"
+        android:key="@string/pref_library_update_restriction_key"
+        android:summary="@string/pref_library_update_restriction_summary"
+        android:title="@string/pref_library_update_restriction" />
+
     <SwitchPreferenceCompat
         android:defaultValue="false"
         android:key="@string/pref_update_only_non_completed_key"
         android:title="@string/pref_update_only_non_completed"/>
 
-    <SwitchPreferenceCompat
-        android:defaultValue="false"
-        android:key="@string/pref_update_only_when_charging_key"
-        android:title="@string/pref_update_only_when_charging"/>
-
 </android.support.v7.preference.PreferenceScreen>
\ No newline at end of file
diff --git a/app/src/test/java/eu/kanade/tachiyomi/data/library/LibraryUpdateAlarmTest.java b/app/src/test/java/eu/kanade/tachiyomi/data/library/LibraryUpdateAlarmTest.java
index d6f7115fe..bee54844a 100644
--- a/app/src/test/java/eu/kanade/tachiyomi/data/library/LibraryUpdateAlarmTest.java
+++ b/app/src/test/java/eu/kanade/tachiyomi/data/library/LibraryUpdateAlarmTest.java
@@ -101,7 +101,7 @@ public class LibraryUpdateAlarmTest {
     @Test
     public void testLibraryUpdateServiceIsStartedWhenUpdateIntentIsReceived() {
         Intent intent = new Intent(context, LibraryUpdateService.class);
-        intent.putExtra("is_forced", false);
+        intent.putExtra("is_manual", false);
         assertThat(app.getNextStartedService()).isNotEqualTo(intent);
 
         LibraryUpdateAlarm alarm = new LibraryUpdateAlarm();