diff --git a/app/src/main/java/com/hippo/ehviewer/preference/CleanRedundancyPreference.java b/app/src/main/java/com/hippo/ehviewer/preference/CleanRedundancyPreference.java
new file mode 100644
index 000000000..99665277f
--- /dev/null
+++ b/app/src/main/java/com/hippo/ehviewer/preference/CleanRedundancyPreference.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2016 Hippo Seven
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.hippo.ehviewer.preference;
+
+import android.content.Context;
+import android.support.annotation.NonNull;
+import android.util.AttributeSet;
+import android.widget.Toast;
+
+import com.hippo.ehviewer.EhApplication;
+import com.hippo.ehviewer.R;
+import com.hippo.ehviewer.Settings;
+import com.hippo.ehviewer.download.DownloadManager;
+import com.hippo.unifile.UniFile;
+import com.hippo.yorozuya.NumberUtils;
+
+public class CleanRedundancyPreference extends TaskPreference {
+
+ public CleanRedundancyPreference(Context context) {
+ super(context);
+ }
+
+ public CleanRedundancyPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public CleanRedundancyPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ @NonNull
+ @Override
+ protected Task onCreateTask() {
+ return new ClearTask(getContext());
+ }
+
+ private static class ClearTask extends Task {
+
+ private final EhApplication mApplication;
+ private final DownloadManager mManager;
+
+ public ClearTask(@NonNull Context context) {
+ super(context);
+ mApplication = (EhApplication) context.getApplicationContext();
+ mManager = EhApplication.getDownloadManager(mApplication);
+ }
+
+ // True for cleared
+ private boolean clearFile(UniFile file) {
+ String name = file.getName();
+ int index = name.indexOf('-');
+ if (index >= 0) {
+ name = name.substring(0, index);
+ }
+ long gid = NumberUtils.parseLongSafely(name, -1L);
+ if (-1L == gid) {
+ return false;
+ }
+ if (mManager.containDownloadInfo(gid)) {
+ return false;
+ }
+ file.delete();
+ return true;
+ }
+
+ @Override
+ protected Object doInBackground(Void... params) {
+ UniFile dir = Settings.getDownloadLocation();
+ if (null == dir) {
+ return 0;
+ }
+ UniFile[] files = dir.listFiles();
+ if (null == files) {
+ return 0;
+ }
+
+ int count = 0;
+ for (UniFile f: files) {
+ if (clearFile(f)) {
+ ++count;
+ }
+ }
+
+ return count;
+ }
+
+ @Override
+ protected void onPostExecute(Object o) {
+ int count;
+ if (o instanceof Integer) {
+ count = (Integer) o;
+ } else {
+ count = 0;
+ }
+
+ Toast.makeText(mApplication, 0 == count ?
+ mApplication.getString(R.string.settings_download_clean_redundancy_no_redundancy):
+ mApplication.getString(R.string.settings_download_clean_redundancy_done, count), Toast.LENGTH_SHORT).show();
+ super.onPostExecute(o);
+ }
+ }
+}
diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml
index bf6bc318a..45e4e9dce 100644
--- a/app/src/main/res/values-zh-rCN/strings.xml
+++ b/app/src/main/res/values-zh-rCN/strings.xml
@@ -425,6 +425,10 @@
未找到可恢复下载项
恢复失败
成功恢复 %s 项
+ 清理下载冗余
+ 清理下载目录中不在下载列表里的图片文件
+ 未发现冗余
+ 完成冗余清理,共清理 %d 项
高级
解析失败时保存页面内容
diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml
index 127d1fc65..9822903c7 100644
--- a/app/src/main/res/values-zh-rHK/strings.xml
+++ b/app/src/main/res/values-zh-rHK/strings.xml
@@ -425,6 +425,10 @@
未找到可恢復下載項
恢復失敗
成功恢復 %s 項
+ 清理下載宂餘
+ 清理下載目錄中不在下載列表裏的圖片文件
+ 未發現宂餘
+ 完成宂餘清理,共清理 %d 項
高級
解析失敗時保存頁面內容
diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml
index 6cbd2401d..1612dd516 100644
--- a/app/src/main/res/values-zh-rTW/strings.xml
+++ b/app/src/main/res/values-zh-rTW/strings.xml
@@ -425,6 +425,10 @@
未找到可恢復下載項
恢復失敗
成功恢復 %s 項
+ 清理下載冗餘
+ 清理下載目錄中不在下載列表裡的圖片檔案
+ 未發現冗餘
+ 完成冗餘清理,共清理 %d 項
高階
解析失敗時儲存頁面內容
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index f396d30ba..869af72c5 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -467,6 +467,10 @@
Not found download items to restore
Restore failed
Restore %d items successfully
+ Clear download redundancy
+ Remove gallery images which are not in download list but in download location
+ No redundancy
+ Redundancy cleaning completed, clean-up %d items totally
Advanced
Save html content when parsing error
diff --git a/app/src/main/res/xml/download_settings.xml b/app/src/main/res/xml/download_settings.xml
index c231bc3c4..f09cf2243 100644
--- a/app/src/main/res/xml/download_settings.xml
+++ b/app/src/main/res/xml/download_settings.xml
@@ -50,4 +50,9 @@
android:title="@string/settings_download_restore_download_items"
android:summary="@string/settings_download_restore_download_items_summary"/>
+
+