From aabedf3fde0cde2b145f05a99032915f34a69a82 Mon Sep 17 00:00:00 2001 From: xj <1031082091@qq.com> Date: Fri, 25 Dec 2020 17:42:41 +0800 Subject: [PATCH] fix bug???? --- app/build.gradle | 9 +- .../main/java/com/hippo/ehviewer/EhDB.java | 2 +- .../java/com/hippo/ehviewer/Settings.java | 12 + .../java/com/hippo/ehviewer/client/EhDns.java | 1 + .../hippo/ehviewer/spider/SpiderQueen.java | 326 ++++++++++-------- .../ehviewer/ui/scene/GalleryDetailScene.java | 5 +- .../main/res/layout/scene_gallery_detail.xml | 4 +- .../ehviewer/daogenerator/Utilities.java | 33 ++ 8 files changed, 236 insertions(+), 156 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index b2dc1666a..c3017bf08 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -6,12 +6,14 @@ if (file('google-services.json').exists()) { } android { - compileSdkVersion 30 + compileSdkVersion 28 + buildToolsVersion "30.0.2" + ndkVersion '22.0.6917172 rc1' defaultConfig { applicationId "com.xjs.ehviewer" minSdkVersion 23 - targetSdkVersion 30 + targetSdkVersion 28 versionCode 107 versionName "1.7.7.0" vectorDrawables.useSupportLibrary = true @@ -51,8 +53,7 @@ android { java.srcDirs += 'src/main/java-gen' } } - ndkVersion '22.0.6917172 rc1' - buildToolsVersion '30.0.3' + } task copyNotice(type: Copy) { diff --git a/app/src/main/java/com/hippo/ehviewer/EhDB.java b/app/src/main/java/com/hippo/ehviewer/EhDB.java index d184b8702..ef8470d4e 100644 --- a/app/src/main/java/com/hippo/ehviewer/EhDB.java +++ b/app/src/main/java/com/hippo/ehviewer/EhDB.java @@ -140,7 +140,7 @@ private static void upgradeDB(SQLiteDatabase db, int oldVersion) { private static class OldDBHelper extends SQLiteOpenHelper { private static final String DB_NAME = "data"; - private static final int VERSION = 4; + private static final int VERSION = 5; private static final String TABLE_GALLERY = "gallery"; private static final String TABLE_LOCAL_FAVOURITE = "local_favourite"; diff --git a/app/src/main/java/com/hippo/ehviewer/Settings.java b/app/src/main/java/com/hippo/ehviewer/Settings.java index f6a311cc6..6516fc710 100644 --- a/app/src/main/java/com/hippo/ehviewer/Settings.java +++ b/app/src/main/java/com/hippo/ehviewer/Settings.java @@ -1186,4 +1186,16 @@ public static boolean getDF() { public static void putDF(boolean value) { putBoolean(KEY_DOMAIN_FRONTING, value); } + + + private static final String KEY_DOWNLOAD_DELAY = "download_delay"; + private static final int DEFAULT_DOWNLOAD_DELAY = 0; + + public static int getDownloadDelay() { + return getIntFromStr(KEY_DOWNLOAD_DELAY, DEFAULT_DOWNLOAD_DELAY); + } + public static void putDownloadDelay(int value) { + putIntToStr(KEY_DOWNLOAD_DELAY, value); + } + } diff --git a/app/src/main/java/com/hippo/ehviewer/client/EhDns.java b/app/src/main/java/com/hippo/ehviewer/client/EhDns.java index e34ca9b4a..69651554a 100644 --- a/app/src/main/java/com/hippo/ehviewer/client/EhDns.java +++ b/app/src/main/java/com/hippo/ehviewer/client/EhDns.java @@ -51,6 +51,7 @@ public class EhDns implements Dns { put(map, "repo.e-hentai.org", "94.100.28.57"); put(map, "forums.e-hentai.org", "94.100.18.243"); put(map, "ehgt.org", "37.48.89.44+178.162.139.24+178.162.140.212+81.171.10.48"); +// put(map, "ehgt.org", "178.162.139.24"); put(map, "ul.ehgt.org", "94.100.24.82+94.100.24.72"); builtInHosts = map; } diff --git a/app/src/main/java/com/hippo/ehviewer/spider/SpiderQueen.java b/app/src/main/java/com/hippo/ehviewer/spider/SpiderQueen.java index e53e79917..95b716336 100644 --- a/app/src/main/java/com/hippo/ehviewer/spider/SpiderQueen.java +++ b/app/src/main/java/com/hippo/ehviewer/spider/SpiderQueen.java @@ -24,10 +24,12 @@ import android.util.Log; import android.util.SparseArray; import android.webkit.MimeTypeMap; + import androidx.annotation.IntDef; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.UiThread; + import com.hippo.beerbelly.SimpleDiskCache; import com.hippo.ehviewer.EhApplication; import com.hippo.ehviewer.GetText; @@ -61,6 +63,7 @@ import com.hippo.yorozuya.collect.SparseJLArray; import com.hippo.yorozuya.thread.PriorityThread; import com.hippo.yorozuya.thread.PriorityThreadFactory; + import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; @@ -78,6 +81,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; + import okhttp3.Call; import okhttp3.MediaType; import okhttp3.OkHttpClient; @@ -87,38 +91,23 @@ public final class SpiderQueen implements Runnable { - private static final String TAG = SpiderQueen.class.getSimpleName(); - private static final AtomicInteger sIdGenerator = new AtomicInteger(); - private static final boolean DEBUG_LOG = false; - private static final boolean DEBUG_PTOKEN = true; - - @IntDef({MODE_READ, MODE_DOWNLOAD}) - @Retention(RetentionPolicy.SOURCE) - public @interface Mode {} - - @IntDef({STATE_NONE, STATE_DOWNLOADING, STATE_FINISHED, STATE_FAILED}) - @Retention(RetentionPolicy.SOURCE) - public @interface State {} - public static final int MODE_READ = 0; public static final int MODE_DOWNLOAD = 1; - public static final int STATE_NONE = 0; public static final int STATE_DOWNLOADING = 1; public static final int STATE_FINISHED = 2; public static final int STATE_FAILED = 3; - - public static final int DECODE_THREAD_NUM = 1; - + public static final int DECODE_THREAD_NUM = 2; public static final String SPIDER_INFO_FILENAME = ".ehviewer"; - + private static final String TAG = SpiderQueen.class.getSimpleName(); + private static final AtomicInteger sIdGenerator = new AtomicInteger(); + private static final boolean DEBUG_LOG = false; + private static final boolean DEBUG_PTOKEN = true; private static final String[] URL_509_SUFFIX_ARRAY = { "/509.gif", "/509s.gif" }; - private static final SparseJLArray sQueenMap = new SparseJLArray<>(); - @NonNull private final OkHttpClient mHttpClient; @NonNull @@ -127,54 +116,43 @@ public final class SpiderQueen implements Runnable { private final GalleryInfo mGalleryInfo; @NonNull private final SpiderDen mSpiderDen; - - private int mReadReference = 0; - private int mDownloadReference = 0; - - // It mQueenThread is null, failed or stopped - @Nullable - private volatile Thread mQueenThread; private final Object mQueenLock = new Object(); - private final Thread[] mDecodeThreadArray = new Thread[DECODE_THREAD_NUM]; private final int[] mDecodeIndexArray = new int[DECODE_THREAD_NUM]; private final Queue mDecodeRequestQueue = new LinkedList<>(); - private final Object mWorkerLock = new Object(); - private ThreadPoolExecutor mWorkerPoolExecutor; - private int mWorkerCount; - private final Object mPTokenLock = new Object(); private final AtomicReference mSpiderInfo = new AtomicReference<>(); private final Queue mRequestPTokenQueue = new ConcurrentLinkedQueue<>(); - private final Object mPageStateLock = new Object(); - private volatile int[] mPageStateArray; - // Store request page. The index may be invalid private final Queue mRequestPageQueue = new LinkedList<>(); // Store preload page. The index may be invalid private final Queue mRequestPageQueue2 = new LinkedList<>(); // Store force request page. The index may be invalid private final Queue mForceRequestPageQueue = new LinkedList<>(); - // For download, when it go to mPageStateArray.size(), done - private volatile int mDownloadPage = -1; - private final AtomicInteger mDownloadedPages = new AtomicInteger(0); private final AtomicInteger mFinishedPages = new AtomicInteger(0); - - private AtomicReference showKey = new AtomicReference<>(); private final Object showKeyLock = new Object(); - // Store page error private final ConcurrentHashMap mPageErrorMap = new ConcurrentHashMap<>(); // Store page download percent private final ConcurrentHashMap mPagePercentMap = new ConcurrentHashMap<>(); - private final List mSpiderListeners = new ArrayList<>(); - private final int mWorkerMaxCount; private final int mPreloadNumber; + private final int mDownloadDelay; + private int mReadReference = 0; + private int mDownloadReference = 0; + // It mQueenThread is null, failed or stopped + @Nullable + private volatile Thread mQueenThread; + private ThreadPoolExecutor mWorkerPoolExecutor; + private int mWorkerCount; + private volatile int[] mPageStateArray; + // For download, when it go to mPageStateArray.size(), done + private volatile int mDownloadPage = -1; + private AtomicReference showKey = new AtomicReference<>(); private SpiderQueen(EhApplication application, @NonNull GalleryInfo galleryInfo) { mHttpClient = EhApplication.getOkHttpClient(application); @@ -190,8 +168,52 @@ private SpiderQueen(EhApplication application, @NonNull GalleryInfo galleryInfo) } mWorkerPoolExecutor = new ThreadPoolExecutor(mWorkerMaxCount, mWorkerMaxCount, - 0, TimeUnit.SECONDS, new LinkedBlockingDeque(), + 0, TimeUnit.SECONDS, new LinkedBlockingDeque<>(), new PriorityThreadFactory(SpiderWorker.class.getSimpleName(), Process.THREAD_PRIORITY_BACKGROUND)); + mDownloadDelay = Settings.getDownloadDelay(); + } + + @UiThread + public static SpiderQueen obtainSpiderQueen(@NonNull Context context, + @NonNull GalleryInfo galleryInfo, @Mode int mode) { + OSUtils.checkMainLoop(); + + SpiderQueen queen = sQueenMap.get(galleryInfo.gid); + if (queen == null) { + EhApplication application = (EhApplication) context.getApplicationContext(); + queen = new SpiderQueen(application, galleryInfo); + sQueenMap.put(galleryInfo.gid, queen); + // Set mode + queen.setMode(mode); + queen.start(); + } else { + // Set mode + queen.setMode(mode); + } + return queen; + } + + @UiThread + public static void releaseSpiderQueen(@NonNull SpiderQueen queen, @Mode int mode) { + OSUtils.checkMainLoop(); + + // Clear mode + queen.clearMode(mode); + + if (queen.mReadReference == 0 && queen.mDownloadReference == 0) { + // Stop and remove if there is no reference + queen.stop(); + sQueenMap.remove(queen.mGalleryInfo.gid); + } + } + + public static boolean contain(int[] array, int value) { + for (int v : array) { + if (v == value) { + return true; + } + } + return false; } public void addOnSpiderListener(OnSpiderListener listener) { @@ -288,40 +310,6 @@ private void notifyGetImageFailure(int index, String error) { } } - @UiThread - public static SpiderQueen obtainSpiderQueen(@NonNull Context context, - @NonNull GalleryInfo galleryInfo, @Mode int mode) { - OSUtils.checkMainLoop(); - - SpiderQueen queen = sQueenMap.get(galleryInfo.gid); - if (queen == null) { - EhApplication application = (EhApplication) context.getApplicationContext(); - queen = new SpiderQueen(application, galleryInfo); - sQueenMap.put(galleryInfo.gid, queen); - // Set mode - queen.setMode(mode); - queen.start(); - } else { - // Set mode - queen.setMode(mode); - } - return queen; - } - - @UiThread - public static void releaseSpiderQueen(@NonNull SpiderQueen queen, @Mode int mode) { - OSUtils.checkMainLoop(); - - // Clear mode - queen.clearMode(mode); - - if (queen.mReadReference == 0 && queen.mDownloadReference == 0) { - // Stop and remove if there is no reference - queen.stop(); - sQueenMap.remove(queen.mGalleryInfo.gid); - } - } - private void updateMode() { int mode; if (mDownloadReference > 0) { @@ -481,8 +469,7 @@ public void cancelRequest(int index) { } /** - * @return - * String for error
+ * @return String for error
* Float for download percent
* null for wait */ @@ -496,7 +483,7 @@ private Object request(int index, boolean ignoreError, boolean force, boolean ad // Fix state for force if ((force && (state == STATE_FINISHED || state == STATE_FAILED)) || - (ignoreError && state == STATE_FAILED)) { + (ignoreError && state == STATE_FAILED)) { // Update state to none at once updatePageState(index, STATE_NONE); state = STATE_NONE; @@ -563,15 +550,6 @@ private Object request(int index, boolean ignoreError, boolean force, boolean ad return result; } - public static boolean contain(int[] array, int value) { - for (int v: array) { - if (v == value) { - return true; - } - } - return false; - } - private void ensureWorkers() { synchronized (mWorkerLock) { if (null == mWorkerPoolExecutor) { @@ -651,6 +629,39 @@ public UniFile save(int index, @NonNull UniFile dir, @NonNull String filename) { } } + + @Nullable + public String getExtension(int index) { + int state = getPageState(index); + if (STATE_FINISHED != state) { + return null; + } + + InputStreamPipe pipe = mSpiderDen.openInputStreamPipe(index); + if (null == pipe) { + return null; + } + + OutputStream os = null; + try { + pipe.obtain(); + + // Get dst file + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + BitmapFactory.decodeStream(pipe.open(), null, options); + pipe.close(); + + return MimeTypeMap.getSingleton().getExtensionFromMimeType(options.outMimeType); + } catch (IOException e) { + return null; + } finally { + pipe.close(); + pipe.release(); + IOUtils.closeQuietly(os); + } + } + public int getStartPage() { SpiderInfo spiderInfo = readSpiderInfoFromLocal(); if (spiderInfo != null) { @@ -780,7 +791,7 @@ private String getPTokenFromInternet(int index) { String referer = EhUrl.getReferer(); if (DEBUG_PTOKEN) { Log.d(TAG, "index " + index + ", previewIndex " + previewIndex + - ", previewPerPage " + spiderInfo.previewPerPage+ ", url " + url); + ", previewPerPage " + spiderInfo.previewPerPage + ", url " + url); } Request request = new EhRequestBuilder(url, referer).build(); Response response = mHttpClient.newCall(request).execute(); @@ -1008,6 +1019,68 @@ private void updatePageState(int index, @State int state, String error) { } } + @IntDef({MODE_READ, MODE_DOWNLOAD}) + @Retention(RetentionPolicy.SOURCE) + public @interface Mode { + } + + @IntDef({STATE_NONE, STATE_DOWNLOADING, STATE_FINISHED, STATE_FAILED}) + @Retention(RetentionPolicy.SOURCE) + public @interface State { + } + + public interface OnSpiderListener { + + void onGetPages(int pages); + + void onGet509(int index); + + /** + * @param contentLength -1 for unknown + */ + void onPageDownload(int index, long contentLength, long receivedSize, int bytesRead); + + void onPageSuccess(int index, int finished, int downloaded, int total); + + void onPageFailure(int index, String error, int finished, int downloaded, int total); + + /** + * All workers end + */ + void onFinish(int finished, int downloaded, int total); + + void onGetImageSuccess(int index, Image image); + + void onGetImageFailure(int index, String error); + } + + private static class AutoCloseInputStream extends InputStream { + + private final InputStreamPipe mPipe; + private final InputStream mIs; + + public AutoCloseInputStream(InputStreamPipe pipe, InputStream is) { + mPipe = pipe; + mIs = is; + } + + @Override + public int read() throws IOException { + return mIs.read(); + } + + @Override + public int read(@NonNull byte[] buffer, int byteOffset, int byteCount) throws IOException { + return mIs.read(buffer, byteOffset, byteCount); + } + + @Override + public void close() throws IOException { + mPipe.close(); + mPipe.release(); + } + } + private class SpiderWorker implements Runnable { private final long mGid; @@ -1017,7 +1090,7 @@ public SpiderWorker() { } private String getPageUrl(long gid, int index, String pToken, - String oldPageUrl, String skipHathKey) { + String oldPageUrl, String skipHathKey) { String pageUrl; if (oldPageUrl != null) { pageUrl = oldPageUrl; @@ -1179,7 +1252,10 @@ private boolean downloadImage(long gid, int index, String pToken, String previou Log.d(TAG, "Start download image " + index); } - Call call = mHttpClient.newCall(new EhRequestBuilder(targetImageUrl, referer).build()); + // disable Call Timeout for image-downloading requests + Call call = mHttpClient.newBuilder() + .callTimeout(0, TimeUnit.SECONDS).build() + .newCall(new EhRequestBuilder(targetImageUrl, referer).build()); Response response = call.execute(); ResponseBody responseBody = response.body(); @@ -1276,7 +1352,7 @@ private boolean downloadImage(long gid, int index, String pToken, String previou isPipe.obtain(); InputStream inputStream = new BufferedInputStream(isPipe.open()); boolean isPlainTxt = true; - for (;;) { + for (; ; ) { int b = inputStream.read(); if (b == -1) { break; @@ -1311,6 +1387,11 @@ private boolean downloadImage(long gid, int index, String pToken, String previou // Download finished updatePageState(index, STATE_FINISHED); + try { + Thread.sleep(mDownloadDelay); + } catch (InterruptedException e) { + e.printStackTrace(); + } return true; } catch (IOException e) { e.printStackTrace(); @@ -1381,7 +1462,7 @@ private boolean runInternal() { // Check exist for not force request if (!force && mSpiderDen.contain(index)) { - updatePageState(index , STATE_FINISHED); + updatePageState(index, STATE_FINISHED); return true; } @@ -1481,7 +1562,8 @@ public void run() { Log.i(TAG, Thread.currentThread().getName() + ": start"); } - while (mSpiderDen.isReady() && !Thread.currentThread().isInterrupted() && runInternal()); + while (mSpiderDen.isReady() && !Thread.currentThread().isInterrupted() && runInternal()) + ; boolean finish; // Clear in spider worker array @@ -1594,56 +1676,4 @@ public void run() { } } } - - private class AutoCloseInputStream extends InputStream { - - private final InputStreamPipe mPipe; - private final InputStream mIs; - - public AutoCloseInputStream(InputStreamPipe pipe, InputStream is) { - mPipe = pipe; - mIs = is; - } - - @Override - public int read() throws IOException { - return mIs.read(); - } - - @Override - public int read(@NonNull byte[] buffer, int byteOffset, int byteCount) throws IOException { - return mIs.read(buffer, byteOffset, byteCount); - } - - @Override - public void close() throws IOException { - mPipe.close(); - mPipe.release(); - } - } - - public interface OnSpiderListener { - - void onGetPages(int pages); - - void onGet509(int index); - - /** - * @param contentLength -1 for unknown - */ - void onPageDownload(int index, long contentLength, long receivedSize, int bytesRead); - - void onPageSuccess(int index, int finished, int downloaded, int total); - - void onPageFailure(int index, String error, int finished, int downloaded, int total); - - /** - * All workers end - */ - void onFinish(int finished, int downloaded, int total); - - void onGetImageSuccess(int index, Image image); - - void onGetImageFailure(int index, String error); - } } diff --git a/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryDetailScene.java b/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryDetailScene.java index d9873aed4..2f8d84a19 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryDetailScene.java +++ b/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryDetailScene.java @@ -834,10 +834,13 @@ private void bindViewSecond() { return; } +// if (mThumb == null || mTitle == null || mUploader == null || mCategory == null) { +// return; +// } Resources resources = getResources2(); AssertUtils.assertNotNull(resources); - mThumb.load(EhCacheKeyFactory.getThumbKey(gd.gid), gd.thumb); + mThumb.load(EhCacheKeyFactory.getThumbKey(gd.gid), gd.thumb,false); mTitle.setText(EhUtils.getSuitableTitle(gd)); mUploader.setText(gd.uploader); mCategory.setText(EhUtils.getCategory(gd.category)); diff --git a/app/src/main/res/layout/scene_gallery_detail.xml b/app/src/main/res/layout/scene_gallery_detail.xml index 324959f5c..c24722b6f 100644 --- a/app/src/main/res/layout/scene_gallery_detail.xml +++ b/app/src/main/res/layout/scene_gallery_detail.xml @@ -21,7 +21,7 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - - +