Add gallery spider
This commit is contained in:
1 parent
ce68c32cf2
commit
440898fba5
43 files changed
+1980
-203
No files matched your search
@@ -22,10 +22,14 @@ import android.content.Context;
|
||||
import com.hippo.beerbelly.SimpleDiskCache;
|
||||
import com.hippo.conaco.Conaco;
|
||||
import com.hippo.ehviewer.client.EhClient;
|
||||
import com.hippo.ehviewer.gallery.GallerySpider;
|
||||
import com.hippo.ehviewer.gallery.ImageHandler;
|
||||
import com.hippo.ehviewer.network.EhHttpClient;
|
||||
import com.hippo.ehviewer.util.DBUtils;
|
||||
import com.hippo.ehviewer.util.Settings;
|
||||
import com.hippo.scene.SceneApplication;
|
||||
import com.hippo.vectorold.content.VectorContext;
|
||||
import com.hippo.yorozuya.FileUtils;
|
||||
import com.hippo.yorozuya.Say;
|
||||
|
||||
import java.io.File;
|
||||
@@ -38,13 +42,13 @@ public class EhApplication extends SceneApplication {
|
||||
private EhHttpClient mEhHttpClient;
|
||||
private EhClient mEhClient;
|
||||
private Conaco mConaco;
|
||||
private SimpleDiskCache mReadcache;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
Settings.initialize(this);
|
||||
DBUtils.initialize(this);
|
||||
|
||||
File sayFile = AppConfig.getFileInAppDir("EhViewer.log");
|
||||
if (sayFile != null) {
|
||||
@@ -63,11 +67,20 @@ public class EhApplication extends SceneApplication {
|
||||
conacoBuilder.httpClient = mEhHttpClient;
|
||||
mConaco = conacoBuilder.build();
|
||||
|
||||
SimpleDiskCache readcache = null;
|
||||
try {
|
||||
mReadcache = new SimpleDiskCache(new File(getCacheDir(), "readCache"), 200 * 1024 * 1024);
|
||||
readcache = new SimpleDiskCache(new File(getCacheDir(), "read"), 200 * 1024 * 1024);
|
||||
} catch (IOException e) {
|
||||
// TODO need a better idea
|
||||
e.printStackTrace();
|
||||
}
|
||||
ImageHandler.init(readcache);
|
||||
|
||||
File spiderInfoDir = getDir("spiderInfo", Context.MODE_PRIVATE);
|
||||
if (!FileUtils.ensureDirectory(spiderInfoDir)) {
|
||||
// TODO Can't create spider info dir
|
||||
}
|
||||
GallerySpider.init(mEhHttpClient, spiderInfoDir);
|
||||
}
|
||||
|
||||
private int getMemoryCacheMaxSize() {
|
||||
@@ -105,9 +118,4 @@ public class EhApplication extends SceneApplication {
|
||||
EhApplication application = (EhApplication) context.getApplicationContext();
|
||||
return application.mConaco;
|
||||
}
|
||||
|
||||
public static SimpleDiskCache getReadCache(Context context) {
|
||||
EhApplication application = (EhApplication) context.getApplicationContext();
|
||||
return application.mReadcache;
|
||||
}
|
||||
}
|
||||
+5
-1
@@ -1,6 +1,6 @@
|
||||
package com.hippo.ehviewer;
|
||||
|
||||
public class EhImageKeyFactory {
|
||||
public class EhCacheKeyFactory {
|
||||
|
||||
public static String getThumbKey(int gid) {
|
||||
return "thumb:" + gid;
|
||||
@@ -19,4 +19,8 @@ public class EhImageKeyFactory {
|
||||
public static String getLargePreviewKey(int gid, int index) {
|
||||
return "preview:large:" + gid + ":" + index;
|
||||
}
|
||||
|
||||
public static String getImageKey(int gid, int index) {
|
||||
return "image:" + gid + ":" + index;
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@ import android.os.AsyncTask;
|
||||
import android.os.Process;
|
||||
|
||||
import com.hippo.ehviewer.client.data.GalleryApiDetail;
|
||||
import com.hippo.ehviewer.client.data.GalleryWithJpnTitle;
|
||||
import com.hippo.ehviewer.client.data.GalleryBase;
|
||||
import com.hippo.ehviewer.network.EhHttpRequest;
|
||||
import com.hippo.httpclient.HttpClient;
|
||||
import com.hippo.httpclient.HttpRequest;
|
||||
@@ -262,12 +262,12 @@ public final class EhClient {
|
||||
}
|
||||
}
|
||||
|
||||
private void fillJpnTitle(HttpRequest httpRequest, List<GalleryWithJpnTitle> list, int source) throws Exception {
|
||||
private void fillJpnTitle(HttpRequest httpRequest, List<GalleryBase> list, int source) throws Exception {
|
||||
int length = list.size();
|
||||
int[] gids = new int[length];
|
||||
String[] tokens = new String[length];
|
||||
for (int i = 0; i < length; i++) {
|
||||
GalleryWithJpnTitle gi = list.get(i);
|
||||
GalleryBase gi = list.get(i);
|
||||
gids[i] = gi.gid;
|
||||
tokens[i] = gi.token;
|
||||
}
|
||||
@@ -276,7 +276,7 @@ public final class EhClient {
|
||||
mHttpClient, httpRequest, gids, tokens, source);
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
GalleryWithJpnTitle gi = list.get(i);
|
||||
GalleryBase gi = list.get(i);
|
||||
GalleryApiDetail gad = galleryApiDetails.get(i);
|
||||
if (gi.gid == gad.gid) {
|
||||
gi.titleJpn = gad.titleJpn;
|
||||
|
||||
@@ -611,6 +611,15 @@ public class EhConfig implements Cloneable {
|
||||
|
||||
private boolean mDirty = true;
|
||||
|
||||
@Override
|
||||
public EhConfig clone() {
|
||||
try {
|
||||
return (EhConfig) super.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setDirty() {
|
||||
mDirty = true;
|
||||
}
|
||||
|
||||
@@ -35,21 +35,9 @@ class EhEngine {
|
||||
private static final String SIGN_IN_URL = "http://forums.e-hentai.org/index.php?act=Login&CODE=01";
|
||||
public static final String API_EHVIEWER = "http://www.ehviewer.com/API";
|
||||
|
||||
public static final String API_G = "http://g.e-hentai.org/api.php";
|
||||
public static final String API_EX = "http://exhentai.org/api.php";
|
||||
public static final long APIUID = 1363542;
|
||||
public static final String APIKEY = "f4b5407ab1727b9d08d7";
|
||||
|
||||
private static String getApiUrl(int source) {
|
||||
switch (source) {
|
||||
default:
|
||||
case EhUrl.SOURCE_G:
|
||||
return API_G;
|
||||
case EhUrl.SOURCE_EX:
|
||||
return API_EX;
|
||||
}
|
||||
}
|
||||
|
||||
public static String signIn(HttpClient httpClient, HttpRequest httpRequest,
|
||||
String username, String password) throws Exception {
|
||||
try {
|
||||
@@ -124,7 +112,7 @@ class EhEngine {
|
||||
return GalleryDetailParser.parse(body, source,
|
||||
GalleryDetailParser.REQUEST_DETAIL |
|
||||
GalleryDetailParser.REQUEST_TAG |
|
||||
GalleryDetailParser.REQUEST_PREVIEW_INFO |
|
||||
GalleryDetailParser.REQUEST_PREVIEW_PAGES |
|
||||
GalleryDetailParser.REQUEST_PREVIEW |
|
||||
GalleryDetailParser.REQUEST_COMMENT);
|
||||
} catch (Exception e) {
|
||||
@@ -174,7 +162,7 @@ class EhEngine {
|
||||
ja.put(g);
|
||||
}
|
||||
json.put("gidlist", ja);
|
||||
httpRequest.setUrl(getApiUrl(source));
|
||||
httpRequest.setUrl(EhUrl.getApiUrl(source));
|
||||
httpRequest.setHttpImpl(new JsonPoster(json));
|
||||
HttpResponse response = httpClient.execute(httpRequest);
|
||||
String body = response.getString();
|
||||
|
||||
@@ -30,6 +30,9 @@ public class EhUrl {
|
||||
public static final String HEADER_EX = "http://exhentai.org/";
|
||||
public static final String HEADER_LOFI = "http://lofi.e-hentai.org/";
|
||||
|
||||
public static final String API_G = "http://g.e-hentai.org/api.php";
|
||||
public static final String API_EX = "http://exhentai.org/api.php";
|
||||
|
||||
public static String getReadableHost(int source) {
|
||||
switch (source) {
|
||||
default:
|
||||
@@ -42,6 +45,16 @@ public class EhUrl {
|
||||
}
|
||||
}
|
||||
|
||||
public static String getApiUrl(int source) {
|
||||
switch (source) {
|
||||
default:
|
||||
case EhUrl.SOURCE_G:
|
||||
return API_G;
|
||||
case EhUrl.SOURCE_EX:
|
||||
return API_EX;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getUrlHeader(int source) {
|
||||
switch (source) {
|
||||
default:
|
||||
@@ -67,4 +80,7 @@ public class EhUrl {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static String getPageUrl(int source, int gid, String token, int pageIndex) {
|
||||
return getUrlHeader(source) + "s/" + token + '/' + gid + '-' + (pageIndex + 1);
|
||||
}
|
||||
}
|
||||
@@ -28,8 +28,6 @@ import com.hippo.yorozuya.NumberUtils;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Locale;
|
||||
@@ -53,15 +51,10 @@ public class GalleryDetailParser {
|
||||
|
||||
public static final int REQUEST_DETAIL = 0x1;
|
||||
public static final int REQUEST_TAG = 0x2;
|
||||
public static final int REQUEST_PREVIEW_INFO = 0x4;
|
||||
public static final int REQUEST_PREVIEW_PAGES = 0x4;
|
||||
public static final int REQUEST_PREVIEW = 0x8;
|
||||
public static final int REQUEST_COMMENT = 0x10;
|
||||
|
||||
// TODO Can't Sort comment it like this,
|
||||
// If the comment is modified, this time is modifing time.
|
||||
// Leave it to cookie
|
||||
private static final CommentSort COMMENT_SORTER = new CommentSort();
|
||||
|
||||
public static GalleryDetail parse(String body, int source, int request) throws Exception {
|
||||
switch (source) {
|
||||
default:
|
||||
@@ -93,7 +86,7 @@ public class GalleryDetailParser {
|
||||
Pattern p;
|
||||
Matcher m;
|
||||
|
||||
// TODO I can't remember what's this for
|
||||
// Error info
|
||||
p = Pattern.compile("<div class=\"d\">\n<p>([^<]+)</p>");
|
||||
m = p.matcher(body);
|
||||
if (m.find()) {
|
||||
@@ -202,17 +195,8 @@ public class GalleryDetailParser {
|
||||
}
|
||||
|
||||
// Get preview info
|
||||
if ((request & REQUEST_PREVIEW_INFO) != 0) {
|
||||
p = Pattern.compile("<td[^>]+><a[^>]+>([\\d,]+)</a></td><td[^>]+>(?:<a[^>]+>)?>(?:</a>)?</td>");
|
||||
m = p.matcher(body);
|
||||
if (m.find()) {
|
||||
galleryDetail.previewPageCount = ParserUtils.parseInt(m.group(1));
|
||||
} else {
|
||||
galleryDetail.previewPageCount = 0;
|
||||
}
|
||||
if (galleryDetail.previewPageCount <= 0) {
|
||||
throw new ParseException("Parse preview page count error", body);
|
||||
}
|
||||
if ((request & REQUEST_PREVIEW_PAGES) != 0) {
|
||||
galleryDetail.previewPageCount = parsePreviewPages(body);
|
||||
}
|
||||
|
||||
// Get preview
|
||||
@@ -237,9 +221,8 @@ public class GalleryDetailParser {
|
||||
date = new Date(0l);
|
||||
}
|
||||
String outDateString = OUT_COMMENT_DATE_FORMAT.format(date);
|
||||
galleryDetail.comments.add(new Comment(outDateString, date, ParserUtils.trim(m.group(2)), m.group(3)));
|
||||
galleryDetail.comments.add(new Comment(outDateString, ParserUtils.trim(m.group(2)), m.group(3)));
|
||||
}
|
||||
Collections.sort(galleryDetail.comments, COMMENT_SORTER);
|
||||
}
|
||||
|
||||
return galleryDetail;
|
||||
@@ -253,6 +236,31 @@ public class GalleryDetailParser {
|
||||
}
|
||||
}
|
||||
|
||||
public static int parsePreviewPages(String body) throws ParseException {
|
||||
Pattern p = Pattern.compile("<td[^>]+><a[^>]+>([\\d,]+)</a></td><td[^>]+>(?:<a[^>]+>)?>(?:</a>)?</td>");
|
||||
Matcher m = p.matcher(body);
|
||||
int previewPages = -1;
|
||||
if (m.find()) {
|
||||
previewPages = ParserUtils.parseInt(m.group(1));
|
||||
}
|
||||
|
||||
if (previewPages <= 0) {
|
||||
throw new ParseException("Parse preview page count error", body);
|
||||
}
|
||||
|
||||
return previewPages;
|
||||
}
|
||||
|
||||
public static int parsePages(String body) throws ParseException {
|
||||
Pattern p = Pattern.compile("<tr><td[^<>]*>Length:</td><td[^<>]*>([\\d,]+) pages</td></tr>");
|
||||
Matcher m = p.matcher(body);
|
||||
if (m.find()) {
|
||||
return ParserUtils.parseInt(m.group(1));
|
||||
} else {
|
||||
throw new ParseException("Parse pages error", body);
|
||||
}
|
||||
}
|
||||
|
||||
public static PreviewSet parsePreview(String body, int source) throws EhException {
|
||||
switch (source) {
|
||||
default:
|
||||
@@ -297,12 +305,4 @@ public class GalleryDetailParser {
|
||||
}
|
||||
return largePreviewSet;
|
||||
}
|
||||
|
||||
static class CommentSort implements Comparator<Comment> {
|
||||
|
||||
@Override
|
||||
public int compare(Comment c1, Comment c2) {
|
||||
return c1.date.compareTo(c2.date);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2015 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.client;
|
||||
|
||||
import com.hippo.yorozuya.Say;
|
||||
import com.hippo.yorozuya.StringUtils;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class GalleryPageParser {
|
||||
|
||||
public static String parse(String body) throws ParseException {
|
||||
Pattern p = Pattern.compile("<div id=\"i3\"><a[^>]+><img id=\"img\" src=\"([^\"]+)\"");
|
||||
Matcher m = p.matcher(body);
|
||||
if (m.find()) {
|
||||
return StringUtils.unescapeXml(m.group(1));
|
||||
} else {
|
||||
Say.f("s", body);
|
||||
throw new ParseException("Parse gallery page error", body);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,17 +16,13 @@
|
||||
|
||||
package com.hippo.ehviewer.client.data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class Comment {
|
||||
public String time;
|
||||
public Date date;
|
||||
public String user;
|
||||
public String comment;
|
||||
|
||||
public Comment (String time, Date date, String user, String comment) {
|
||||
public Comment (String time, String user, String comment) {
|
||||
this.time = time;
|
||||
this.date = date;
|
||||
this.user = user;
|
||||
this.comment = comment;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ package com.hippo.ehviewer.client.data;
|
||||
public class GalleryApiDetail extends GalleryBase {
|
||||
|
||||
public String archiverKey;
|
||||
public String titleJpn;
|
||||
public int pageCount;
|
||||
public String size;
|
||||
public boolean expunged;
|
||||
|
||||
@@ -20,8 +20,9 @@ import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public abstract class GalleryBase {
|
||||
public class GalleryBase {
|
||||
|
||||
public static final DateFormat DEFAULT_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.US);
|
||||
|
||||
@@ -29,12 +30,82 @@ public abstract class GalleryBase {
|
||||
DEFAULT_DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||
}
|
||||
|
||||
/**
|
||||
* ISO 639-1
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public static final String S_LANG_JA = "JA";
|
||||
public static final String S_LANG_EN = "EN";
|
||||
public static final String S_LANG_ZH = "ZH";
|
||||
public static final String S_LANG_NL = "NL";
|
||||
public static final String S_LANG_FR = "FR";
|
||||
public static final String S_LANG_DE = "DE";
|
||||
public static final String S_LANG_HU = "HU";
|
||||
public static final String S_LANG_IT = "IT";
|
||||
public static final String S_LANG_KO = "KO";
|
||||
public static final String S_LANG_PL = "PL";
|
||||
public static final String S_LANG_PT = "PT";
|
||||
public static final String S_LANG_RU = "RU";
|
||||
public static final String S_LANG_ES = "ES";
|
||||
public static final String S_LANG_TH = "TH";
|
||||
public static final String S_LANG_VI = "VI";
|
||||
|
||||
public static final String[] S_LANGS = {
|
||||
S_LANG_EN,
|
||||
S_LANG_ZH,
|
||||
S_LANG_ES,
|
||||
S_LANG_KO,
|
||||
S_LANG_RU,
|
||||
S_LANG_FR,
|
||||
S_LANG_PT,
|
||||
S_LANG_TH,
|
||||
S_LANG_DE,
|
||||
S_LANG_IT,
|
||||
S_LANG_VI,
|
||||
S_LANG_PL,
|
||||
S_LANG_HU,
|
||||
S_LANG_NL,
|
||||
};
|
||||
|
||||
public static final String[] S_LANG_PATTERNS = {
|
||||
"[(\\[]eng(?:lish)?[)\\]]",
|
||||
"[((\\[]chinese[))\\]]|[汉漢]化|中[国國][语語]|中文|[(\\[]CN[)\\]]",
|
||||
"[(\\[]spanish[)\\]]|[(\\[]Español[)\\]]",
|
||||
"[(\\[]korean?[)\\]]",
|
||||
"[(\\[]rus(?:sian)?[)\\]]",
|
||||
"[(\\[]fr(?:ench)?[)\\]]",
|
||||
"[(\\[]portuguese",
|
||||
"[(\\[]thai(?: ภาษาไทย)?[)\\]]",
|
||||
"[(\\[]german[)\\]]",
|
||||
"[(\\[]italiano?[)\\]]",
|
||||
"[(\\[]vietnamese(?: Tiếng Việt)?[)\\]]",
|
||||
"[(\\[]polish[)\\]]",
|
||||
"[(\\[]hun(?:garian)?[)\\]]",
|
||||
"[(\\[]dutch[)\\]]",
|
||||
};
|
||||
|
||||
public int gid;
|
||||
public String token;
|
||||
public String title;
|
||||
public String titleJpn;
|
||||
public String thumb;
|
||||
public int category;
|
||||
public String posted;
|
||||
public String uploader;
|
||||
public float rating;
|
||||
|
||||
/**
|
||||
* language from title
|
||||
*/
|
||||
public String simpleLanguage;
|
||||
|
||||
public final void generateSLang() {
|
||||
for (int i = 0; i < S_LANGS.length; i++) {
|
||||
if (Pattern.compile(S_LANG_PATTERNS[i], Pattern.CASE_INSENSITIVE).matcher(title).find()) {
|
||||
simpleLanguage = S_LANGS[i];
|
||||
return;
|
||||
}
|
||||
}
|
||||
simpleLanguage = null;
|
||||
}
|
||||
}
|
||||
@@ -20,8 +20,6 @@ import java.util.List;
|
||||
|
||||
public class GalleryDetail extends GalleryBase {
|
||||
|
||||
public String titleJpn;
|
||||
|
||||
public int torrentCount;
|
||||
public String torrentUrl;
|
||||
|
||||
|
||||
@@ -16,93 +16,8 @@
|
||||
|
||||
package com.hippo.ehviewer.client.data;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
public class GalleryInfo extends GalleryBase {
|
||||
|
||||
public class GalleryInfo extends GalleryWithJpnTitle {
|
||||
|
||||
/**
|
||||
* ISO 639-1
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public static final String S_LANG_JA = "JA";
|
||||
public static final String S_LANG_EN = "EN";
|
||||
public static final String S_LANG_ZH = "ZH";
|
||||
public static final String S_LANG_NL = "NL";
|
||||
public static final String S_LANG_FR = "FR";
|
||||
public static final String S_LANG_DE = "DE";
|
||||
public static final String S_LANG_HU = "HU";
|
||||
public static final String S_LANG_IT = "IT";
|
||||
public static final String S_LANG_KO = "KO";
|
||||
public static final String S_LANG_PL = "PL";
|
||||
public static final String S_LANG_PT = "PT";
|
||||
public static final String S_LANG_RU = "RU";
|
||||
public static final String S_LANG_ES = "ES";
|
||||
public static final String S_LANG_TH = "TH";
|
||||
public static final String S_LANG_VI = "VI";
|
||||
|
||||
public static final String[] S_LANGS = {
|
||||
S_LANG_EN,
|
||||
S_LANG_ZH,
|
||||
S_LANG_ES,
|
||||
S_LANG_KO,
|
||||
S_LANG_RU,
|
||||
S_LANG_FR,
|
||||
S_LANG_PT,
|
||||
S_LANG_TH,
|
||||
S_LANG_DE,
|
||||
S_LANG_IT,
|
||||
S_LANG_VI,
|
||||
S_LANG_PL,
|
||||
S_LANG_HU,
|
||||
S_LANG_NL,
|
||||
};
|
||||
|
||||
public static final String[] S_LANG_PATTERNS = {
|
||||
"[(\\[]eng(?:lish)?[)\\]]",
|
||||
"[((\\[]chinese[))\\]]|[汉漢]化|中[国國][语語]|中文|[(\\[]CN[)\\]]",
|
||||
"[(\\[]spanish[)\\]]|[(\\[]Español[)\\]]",
|
||||
"[(\\[]korean?[)\\]]",
|
||||
"[(\\[]rus(?:sian)?[)\\]]",
|
||||
"[(\\[]fr(?:ench)?[)\\]]",
|
||||
"[(\\[]portuguese",
|
||||
"[(\\[]thai(?: ภาษาไทย)?[)\\]]",
|
||||
"[(\\[]german[)\\]]",
|
||||
"[(\\[]italiano?[)\\]]",
|
||||
"[(\\[]vietnamese(?: Tiếng Việt)?[)\\]]",
|
||||
"[(\\[]polish[)\\]]",
|
||||
"[(\\[]hun(?:garian)?[)\\]]",
|
||||
"[(\\[]dutch[)\\]]",
|
||||
};
|
||||
|
||||
/**
|
||||
* Will not be recond
|
||||
*/
|
||||
public int thumbWidth;
|
||||
/**
|
||||
* Will not be recond
|
||||
*/
|
||||
public int thumbHeight;
|
||||
/**
|
||||
* language get from title
|
||||
*/
|
||||
public String simpleLanguage;
|
||||
|
||||
public GalleryInfo() {
|
||||
// Empty
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return o instanceof GalleryInfo && ((GalleryInfo) o).gid == gid;
|
||||
}
|
||||
|
||||
public final void generateSLang() {
|
||||
for (int i = 0; i < S_LANGS.length; i++) {
|
||||
if (Pattern.compile(S_LANG_PATTERNS[i], Pattern.CASE_INSENSITIVE).matcher(title).find()) {
|
||||
simpleLanguage = S_LANGS[i];
|
||||
return;
|
||||
}
|
||||
}
|
||||
simpleLanguage = null;
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,7 @@ import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.hippo.conaco.Conaco;
|
||||
import com.hippo.ehviewer.EhImageKeyFactory;
|
||||
import com.hippo.ehviewer.EhCacheKeyFactory;
|
||||
import com.hippo.ehviewer.widget.LoadImageView;
|
||||
import com.hippo.widget.SimpleGridLayout;
|
||||
|
||||
@@ -53,7 +53,7 @@ public class LargePreviewSet extends PreviewSet {
|
||||
|
||||
LoadImageView imageView = ((LoadImageView) viewGroup.getChildAt(0));
|
||||
imageView.setRetryType(LoadImageView.RetryType.LONG_CLICK);
|
||||
imageView.load(conaco, EhImageKeyFactory.getLargePreviewKey(getGid(), index), item.imageUrl);
|
||||
imageView.load(conaco, EhCacheKeyFactory.getLargePreviewKey(getGid(), index), item.imageUrl);
|
||||
|
||||
((TextView) viewGroup.getChildAt(1)).setText(Integer.toString(index + 1));
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ import android.widget.TextView;
|
||||
import com.hippo.conaco.BitmapHolder;
|
||||
import com.hippo.conaco.Conaco;
|
||||
import com.hippo.conaco.Unikery;
|
||||
import com.hippo.ehviewer.EhImageKeyFactory;
|
||||
import com.hippo.ehviewer.EhCacheKeyFactory;
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.widget.SimpleGridLayout;
|
||||
import com.hippo.yorozuya.Say;
|
||||
@@ -92,7 +92,7 @@ public class NormalPreviewSet extends PreviewSet {
|
||||
|
||||
String key;
|
||||
if (row.imageIndex != -1) {
|
||||
key = EhImageKeyFactory.getNormalPreviewKey(getGid(), row.imageIndex);
|
||||
key = EhCacheKeyFactory.getNormalPreviewKey(getGid(), row.imageIndex);
|
||||
} else {
|
||||
key = row.imageUrl;
|
||||
}
|
||||
@@ -235,7 +235,7 @@ public class NormalPreviewSet extends PreviewSet {
|
||||
|
||||
String key;
|
||||
if (mRow.imageIndex != -1) {
|
||||
key = EhImageKeyFactory.getNormalPreviewKey(getGid(), mRow.imageIndex);
|
||||
key = EhCacheKeyFactory.getNormalPreviewKey(getGid(), mRow.imageIndex);
|
||||
} else {
|
||||
key = mRow.imageUrl;
|
||||
}
|
||||
|
||||
+5
-3
@@ -14,9 +14,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.client.data;
|
||||
package com.hippo.ehviewer.gallery;
|
||||
|
||||
public abstract class GalleryWithJpnTitle extends GalleryBase {
|
||||
public interface GalleryLoaderImpl {
|
||||
|
||||
public String titleJpn;
|
||||
void request(int index);
|
||||
|
||||
int size();
|
||||
}
|
||||
+4
-22
@@ -14,29 +14,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.client;
|
||||
package com.hippo.ehviewer.gallery;
|
||||
|
||||
public class GalleryDownloader {
|
||||
import android.graphics.Bitmap;
|
||||
|
||||
public enum MODE {
|
||||
READ,
|
||||
DOWNLOAD
|
||||
}
|
||||
public interface GalleryRequesterImpl {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public interface GallerySavers {
|
||||
|
||||
}
|
||||
void onGetImage(Bitmap bitmap);
|
||||
}
|
||||
@@ -0,0 +1,265 @@
|
||||
/*
|
||||
* Copyright 2015 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.gallery;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.Process;
|
||||
|
||||
import com.hippo.ehviewer.client.data.GalleryBase;
|
||||
import com.hippo.ehviewer.network.EhHttpClient;
|
||||
import com.hippo.yorozuya.OSUtils;
|
||||
import com.hippo.yorozuya.PriorityThreadFactory;
|
||||
import com.hippo.yorozuya.SafeSparseArray;
|
||||
import com.hippo.yorozuya.SimpleHandler;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
|
||||
public class GallerySpider implements GalleryLoaderImpl, SpiderQueen.SpiderListener {
|
||||
|
||||
private static SafeSparseArray<GallerySpider> mMap = new SafeSparseArray<>();
|
||||
|
||||
private static EhHttpClient sHttpClient;
|
||||
private static File sSpiderInfoDir;
|
||||
|
||||
private ImageHandler.Mode mMode;
|
||||
private GalleryBase mGalleryBase;
|
||||
private ThreadFactory mThreadFactory = new PriorityThreadFactory("SpiderQueen",
|
||||
Process.THREAD_PRIORITY_BACKGROUND);
|
||||
private SpiderQueen mSpiderQueen;
|
||||
|
||||
private List<GallerySpiderListener> mGallerySpiderListeners = new ArrayList<>();
|
||||
|
||||
private int mReference = 0;
|
||||
|
||||
public static void init(EhHttpClient httpClient, File spiderInfoDir) {
|
||||
sHttpClient = httpClient;
|
||||
sSpiderInfoDir = spiderInfoDir;
|
||||
}
|
||||
|
||||
public static GallerySpider obtain(GalleryBase galleryBase, ImageHandler.Mode mode) {
|
||||
int key = galleryBase.gid;
|
||||
GallerySpider gs = mMap.get(key);
|
||||
if (gs == null) {
|
||||
gs = new GallerySpider(galleryBase, mode);
|
||||
gs.start();
|
||||
mMap.put(key, gs);
|
||||
} else if (mode == ImageHandler.Mode.DOWNLOAD && gs.mMode == ImageHandler.Mode.READ) {
|
||||
gs.setMode(ImageHandler.Mode.DOWNLOAD);
|
||||
}
|
||||
gs.mReference++;
|
||||
return gs;
|
||||
}
|
||||
|
||||
public static void release(GallerySpider gallerySpider) {
|
||||
gallerySpider.mReference--;
|
||||
if (gallerySpider.mReference == 0) {
|
||||
gallerySpider.stop();
|
||||
mMap.remove(gallerySpider.mGalleryBase.gid);
|
||||
}
|
||||
}
|
||||
|
||||
private GallerySpider(GalleryBase galleryBase, ImageHandler.Mode mode) {
|
||||
mGalleryBase = galleryBase;
|
||||
mMode = mode;
|
||||
}
|
||||
|
||||
public void addSpiderListener(GallerySpiderListener listener) {
|
||||
mGallerySpiderListeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeSpiderListener(GallerySpiderListener listener) {
|
||||
mGallerySpiderListeners.remove(listener);
|
||||
}
|
||||
|
||||
public void setMode(ImageHandler.Mode mode) {
|
||||
mMode = mode;
|
||||
if (mSpiderQueen != null) {
|
||||
mSpiderQueen.setMode(mode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start downloading
|
||||
*/
|
||||
private void start() {
|
||||
OSUtils.checkMainLoop();
|
||||
|
||||
if (mSpiderQueen == null) {
|
||||
mSpiderQueen = new SpiderQueen(sHttpClient, sSpiderInfoDir,
|
||||
mGalleryBase, mMode, this);
|
||||
mThreadFactory.newThread(mSpiderQueen).start();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop downloading
|
||||
*/
|
||||
private void stop() {
|
||||
OSUtils.checkMainLoop();
|
||||
|
||||
if (mSpiderQueen != null) {
|
||||
mSpiderQueen.stop();
|
||||
mSpiderQueen = null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isRunning() {
|
||||
OSUtils.checkMainLoop();
|
||||
|
||||
return mSpiderQueen != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void request(int index) {
|
||||
if (mSpiderQueen != null) {
|
||||
mSpiderQueen.request(index);
|
||||
}
|
||||
}
|
||||
|
||||
public void releaseBitmap(Bitmap bitmap) {
|
||||
if (mSpiderQueen != null) {
|
||||
mSpiderQueen.releaseBitmap(bitmap);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
if (mSpiderQueen != null) {
|
||||
return mSpiderQueen.pages();
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGetPages(final int pages) {
|
||||
SimpleHandler.getInstance().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (GallerySpiderListener l : mGallerySpiderListeners) {
|
||||
l.onGetPages(pages);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSpiderPage(final int index, final float percent) {
|
||||
SimpleHandler.getInstance().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (GallerySpiderListener l : mGallerySpiderListeners) {
|
||||
l.onSpiderPage(index, percent);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSpiderSucceed(final int index) {
|
||||
SimpleHandler.getInstance().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (GallerySpiderListener l : mGallerySpiderListeners) {
|
||||
l.onSpiderSucceed(index);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSpiderFailed(final int index) {
|
||||
SimpleHandler.getInstance().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (GallerySpiderListener l : mGallerySpiderListeners) {
|
||||
l.onSpiderFailed(index);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGetNone(final int index) {
|
||||
SimpleHandler.getInstance().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (GallerySpiderListener l : mGallerySpiderListeners) {
|
||||
l.onGetNone(index);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGetBitmap(final int index, final Bitmap bitmap) {
|
||||
SimpleHandler.getInstance().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (GallerySpiderListener l : mGallerySpiderListeners) {
|
||||
l.onGetBitmap(index, bitmap);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGetSpider(final int index, final float percent) {
|
||||
SimpleHandler.getInstance().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (GallerySpiderListener l : mGallerySpiderListeners) {
|
||||
l.onGetSpider(index, percent);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGetFailed(final int index) {
|
||||
SimpleHandler.getInstance().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (GallerySpiderListener l : mGallerySpiderListeners) {
|
||||
l.onGetFailed(index);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public interface GallerySpiderListener {
|
||||
|
||||
void onGetPages(int pages);
|
||||
|
||||
void onSpiderPage(int index, float percent);
|
||||
|
||||
void onSpiderSucceed(int index);
|
||||
|
||||
void onSpiderFailed(int index);
|
||||
|
||||
void onGetNone(int index);
|
||||
|
||||
void onGetBitmap(int index, Bitmap bitmap);
|
||||
|
||||
void onGetSpider(int index, float percent);
|
||||
|
||||
void onGetFailed(int index);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2015 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.gallery;
|
||||
|
||||
import com.hippo.ehviewer.client.EhException;
|
||||
|
||||
public class Image509Expection extends EhException {
|
||||
|
||||
public Image509Expection() {
|
||||
super("509 image");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,305 @@
|
||||
/*
|
||||
* Copyright 2015 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.gallery;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.webkit.MimeTypeMap;
|
||||
|
||||
import com.hippo.beerbelly.SimpleDiskCache;
|
||||
import com.hippo.conaco.BitmapPool;
|
||||
import com.hippo.ehviewer.EhCacheKeyFactory;
|
||||
import com.hippo.ehviewer.client.data.GalleryBase;
|
||||
import com.hippo.ehviewer.dao.SpiderObj;
|
||||
import com.hippo.ehviewer.util.DBUtils;
|
||||
import com.hippo.ehviewer.util.Settings;
|
||||
import com.hippo.httpclient.HttpResponse;
|
||||
import com.hippo.io.UniFileInputStreamPipe;
|
||||
import com.hippo.io.UniFileOutputStreamPipe;
|
||||
import com.hippo.unifile.UniFile;
|
||||
import com.hippo.yorozuya.FileUtils;
|
||||
import com.hippo.yorozuya.IOUtils;
|
||||
import com.hippo.yorozuya.io.InputStreamPipe;
|
||||
import com.hippo.yorozuya.io.OutputStreamPipe;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class ImageHandler {
|
||||
|
||||
public static String[] POSSIBLE_IMAGE_EXTENSIONS = new String[] {
|
||||
"jpg", "jpeg", "png", "gif"
|
||||
};
|
||||
|
||||
private static SimpleDiskCache sDiskCache;
|
||||
|
||||
private GalleryBase mGalleryBase;
|
||||
private UniFile mDownloadDir;
|
||||
private Mode mMode;
|
||||
private String[] mFilenames;
|
||||
private BitmapPool mBitmapPool = new BitmapPool();
|
||||
|
||||
public enum Mode {
|
||||
READ,
|
||||
DOWNLOAD
|
||||
}
|
||||
|
||||
public static void init(SimpleDiskCache diskCache) {
|
||||
sDiskCache = diskCache;
|
||||
}
|
||||
|
||||
public ImageHandler(GalleryBase galleryBase, int pages, Mode mode) {
|
||||
mGalleryBase = galleryBase;
|
||||
mMode = mode;
|
||||
mFilenames = new String[pages];
|
||||
|
||||
// TODO Let GallerySpider to handle db, just pass dirname to ImageHandler
|
||||
String dirname;
|
||||
SpiderObj spiderObj = DBUtils.getSpiderObj(galleryBase.gid);
|
||||
if (spiderObj == null) {
|
||||
spiderObj = newSpiderObj();
|
||||
DBUtils.insertSpiderObj(spiderObj);
|
||||
}
|
||||
dirname = spiderObj.getDirname();
|
||||
mDownloadDir = Settings.getDownloadPath().createDirectory(dirname);
|
||||
}
|
||||
|
||||
public String downloadDirname() {
|
||||
return FileUtils.ensureFilename(mGalleryBase.gid + '-' + mGalleryBase.title);
|
||||
}
|
||||
|
||||
private SpiderObj newSpiderObj() {
|
||||
SpiderObj spiderObj = new SpiderObj();
|
||||
spiderObj.setGid((long) mGalleryBase.gid);
|
||||
spiderObj.setLastIndex(0);
|
||||
spiderObj.setDirname(downloadDirname());
|
||||
spiderObj.setDownload(mMode == Mode.DOWNLOAD);
|
||||
spiderObj.setTime(System.currentTimeMillis());
|
||||
return spiderObj;
|
||||
}
|
||||
|
||||
public void setMode(Mode mode) {
|
||||
mMode = mode;
|
||||
// Let DownloadManager to set spiderObj's download to true
|
||||
}
|
||||
|
||||
private static String getImageFilename(int index, String extension) {
|
||||
return String.format("%08d.%s", index + 1, extension);
|
||||
}
|
||||
|
||||
private String guessImageFilename(int index) {
|
||||
for (String extension : POSSIBLE_IMAGE_EXTENSIONS) {
|
||||
String filename = getImageFilename(index, extension);
|
||||
if (mDownloadDir.findFile(filename) != null) {
|
||||
return filename;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private InputStreamPipe getReadInputStreamPipe(int index) {
|
||||
String key = EhCacheKeyFactory.getImageKey(mGalleryBase.gid, index);
|
||||
return sDiskCache.getInputStreamPipe(key);
|
||||
}
|
||||
|
||||
private InputStreamPipe getDownloadInputStreamPipe(String filename) {
|
||||
UniFile uniFile = mDownloadDir.findFile(filename);
|
||||
if (uniFile != null) {
|
||||
return new UniFileInputStreamPipe(uniFile);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private OutputStreamPipe getReadOutputStreamPipe(int index) {
|
||||
String key = EhCacheKeyFactory.getImageKey(mGalleryBase.gid, index);
|
||||
return sDiskCache.getOutputStreamPipe(key);
|
||||
}
|
||||
|
||||
private OutputStreamPipe getDownloadOutputStreamPipe(String filename) {
|
||||
UniFile uniFile = mDownloadDir.createFile(filename);
|
||||
if (uniFile != null) {
|
||||
return new UniFileOutputStreamPipe(uniFile);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void releaseBitmap(Bitmap bitmap) {
|
||||
mBitmapPool.addReusableBitmap(bitmap);
|
||||
}
|
||||
|
||||
public boolean contain(int index) {
|
||||
if (mMode == Mode.READ) {
|
||||
String key = EhCacheKeyFactory.getImageKey(mGalleryBase.gid, index);
|
||||
return sDiskCache.contain(key);
|
||||
} else if (mMode == Mode.DOWNLOAD) {
|
||||
if (index >= mFilenames.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String filename;
|
||||
|
||||
filename = mFilenames[index];
|
||||
if (filename != null) {
|
||||
// Check it in dir
|
||||
if (mDownloadDir.findFile(filename) != null) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
filename = guessImageFilename(index);
|
||||
if (filename != null) {
|
||||
// Put filename into array
|
||||
mFilenames[index] = filename;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Try to find image in cache
|
||||
InputStreamPipe isPipe = getReadInputStreamPipe(index);
|
||||
if (isPipe == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
OutputStream os = null;
|
||||
try {
|
||||
isPipe.obtain();
|
||||
|
||||
if (filename == null) {
|
||||
// Try to get extension
|
||||
InputStream is = isPipe.open();
|
||||
final BitmapFactory.Options options = new BitmapFactory.Options();
|
||||
options.inJustDecodeBounds = true;
|
||||
BitmapFactory.decodeStream(is, null, options);
|
||||
isPipe.close();
|
||||
String extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(options.outMimeType);
|
||||
if (extension == null) {
|
||||
// Can't get extension;
|
||||
return false;
|
||||
}
|
||||
filename = getImageFilename(index, extension);
|
||||
// Put filename into array
|
||||
mFilenames[index] = filename;
|
||||
}
|
||||
|
||||
UniFile file = mDownloadDir.createFile(filename);
|
||||
if (file == null) {
|
||||
return false;
|
||||
}
|
||||
os = file.openOutputStream();
|
||||
IOUtils.copy(isPipe.open(), os);
|
||||
|
||||
} catch (IOException e) {
|
||||
// Ignore
|
||||
} finally {
|
||||
IOUtils.closeQuietly(os);
|
||||
isPipe.close();
|
||||
isPipe.release();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void save(int index, HttpResponse response) {
|
||||
OutputStreamPipe osPipe = null;
|
||||
|
||||
if (mMode == Mode.READ) {
|
||||
osPipe = getReadOutputStreamPipe(index);
|
||||
} else if (mMode == Mode.DOWNLOAD) {
|
||||
String extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(
|
||||
response.getHeaderField("Content-Type"));
|
||||
if (extension == null) {
|
||||
extension = MimeTypeMap.getFileExtensionFromUrl(response.getUrl().toString());
|
||||
if (extension == null) {
|
||||
extension = "jpg";
|
||||
}
|
||||
}
|
||||
String filename = getImageFilename(index, extension);
|
||||
// Put filename into array
|
||||
mFilenames[index] = filename;
|
||||
osPipe = getDownloadOutputStreamPipe(filename);
|
||||
}
|
||||
|
||||
if (osPipe == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
osPipe.obtain();
|
||||
IOUtils.copy(response.getInputStream(), osPipe.open());
|
||||
} catch (IOException e) {
|
||||
// Ignore
|
||||
} finally {
|
||||
osPipe.close();
|
||||
osPipe.release();
|
||||
}
|
||||
}
|
||||
|
||||
public Bitmap getBitmap(int index) {
|
||||
InputStreamPipe isPipe = null;
|
||||
if (mMode == Mode.READ) {
|
||||
isPipe = getReadInputStreamPipe(index);
|
||||
} else if (mMode == Mode.DOWNLOAD) {
|
||||
String filename = mFilenames[index];
|
||||
if (filename == null) {
|
||||
filename = guessImageFilename(index);
|
||||
if (filename != null) {
|
||||
// Put filename into array
|
||||
mFilenames[index] = filename;
|
||||
}
|
||||
}
|
||||
if (filename != null) {
|
||||
isPipe = getDownloadInputStreamPipe(filename);
|
||||
}
|
||||
}
|
||||
|
||||
if (isPipe == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
isPipe.obtain();
|
||||
|
||||
final BitmapFactory.Options options = new BitmapFactory.Options();
|
||||
options.inJustDecodeBounds = true;
|
||||
|
||||
InputStream is = isPipe.open();
|
||||
BitmapFactory.decodeStream(is, null, options);
|
||||
isPipe.close();
|
||||
|
||||
// Check out size
|
||||
if (options.outWidth <= 0 || options.outHeight <= 0) {
|
||||
isPipe.release();
|
||||
return null;
|
||||
}
|
||||
|
||||
options.inJustDecodeBounds = false;
|
||||
options.inMutable = true;
|
||||
options.inSampleSize = 1;
|
||||
options.inBitmap = mBitmapPool.getInBitmap(options);
|
||||
|
||||
is = isPipe.open();
|
||||
return BitmapFactory.decodeStream(is, null, options);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
} finally {
|
||||
isPipe.close();
|
||||
isPipe.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* Copyright 2015 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.gallery;
|
||||
|
||||
import com.hippo.ehviewer.client.EhConfig;
|
||||
import com.hippo.ehviewer.client.data.GalleryBase;
|
||||
import com.hippo.yorozuya.AssertUtils;
|
||||
import com.hippo.yorozuya.AutoExpandArray;
|
||||
import com.hippo.yorozuya.IOUtils;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
|
||||
public class SpiderInfo {
|
||||
|
||||
private static final int VERSION = 1;
|
||||
|
||||
public GalleryBase galleryBase;
|
||||
public int pages = -1;
|
||||
public String previewSize;
|
||||
public int previewPages;
|
||||
public int previewCountPerPage;
|
||||
public AutoExpandArray<String> tokens;
|
||||
|
||||
/**
|
||||
* version
|
||||
* galleryBase.gid
|
||||
* galleryBase.token
|
||||
* galleryBase.title
|
||||
* galleryBase.titleJpn
|
||||
* galleryBase.thumb
|
||||
* galleryBase.category
|
||||
* galleryBase.posted
|
||||
* galleryBase.uploader
|
||||
* galleryBase.rating
|
||||
* pages
|
||||
* previewSize
|
||||
* previewPages
|
||||
* previewCountPerPage
|
||||
* index token
|
||||
* index token
|
||||
* ...
|
||||
*
|
||||
* @param os the output stream
|
||||
*/
|
||||
public void write(OutputStream os) throws IOException {
|
||||
if (galleryBase == null || pages == -1 || previewSize == null) {
|
||||
// No need to write
|
||||
return;
|
||||
}
|
||||
|
||||
GalleryBase gb = galleryBase;
|
||||
OutputStreamWriter osWrite = new OutputStreamWriter(os, "UTF-8");
|
||||
osWrite.append(Integer.toString(VERSION)).append('\n')
|
||||
.append(Integer.toString(gb.gid)).append('\n')
|
||||
.append(gb.token).append('\n')
|
||||
.append(stringToHexString(gb.title)).append('\n')
|
||||
.append(stringToHexString(gb.titleJpn)).append('\n')
|
||||
.append(gb.thumb).append('\n')
|
||||
.append(Integer.toString(gb.category)).append('\n')
|
||||
.append(gb.posted).append('\n')
|
||||
.append(gb.uploader).append('\n')
|
||||
.append(Float.toString(gb.rating)).append('\n')
|
||||
.append(Integer.toString(pages)).append('\n')
|
||||
.append(previewSize).append('\n')
|
||||
.append(Integer.toString(previewPages)).append('\n')
|
||||
.append(Integer.toString(previewCountPerPage)).append('\n');
|
||||
|
||||
if (tokens != null) {
|
||||
int length = Math.min(tokens.maxValidIndex(), pages);
|
||||
for (int i = 0; i < length; i++) {
|
||||
String token = tokens.get(i);
|
||||
if (token != null) {
|
||||
osWrite.append(Integer.toString(i)).append(':')
|
||||
.append(token).append('\n');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
osWrite.flush();
|
||||
osWrite.close();
|
||||
}
|
||||
|
||||
|
||||
public static SpiderInfo read(InputStream is) throws Exception {
|
||||
BufferedInputStream bis = new BufferedInputStream(is);
|
||||
SpiderInfo spiderInfo = new SpiderInfo();
|
||||
|
||||
int version = Integer.parseInt(IOUtils.readAsciiLine(bis));
|
||||
if (VERSION != version){
|
||||
throw new IllegalStateException("Version should be " + VERSION +
|
||||
", but it is " + version);
|
||||
}
|
||||
|
||||
GalleryBase gb = new GalleryBase();
|
||||
gb.gid = Integer.parseInt(IOUtils.readAsciiLine(bis));
|
||||
gb.token = IOUtils.readAsciiLine(bis);
|
||||
gb.title = hexStringToString(IOUtils.readAsciiLine(bis));
|
||||
gb.titleJpn = hexStringToString(IOUtils.readAsciiLine(bis));
|
||||
gb.thumb = IOUtils.readAsciiLine(bis);
|
||||
gb.category = Integer.parseInt(IOUtils.readAsciiLine(bis));
|
||||
gb.posted = IOUtils.readAsciiLine(bis);
|
||||
gb.uploader = IOUtils.readAsciiLine(bis);
|
||||
gb.rating = Float.parseFloat(IOUtils.readAsciiLine(bis));
|
||||
spiderInfo.galleryBase = gb;
|
||||
|
||||
spiderInfo.pages = Integer.parseInt(IOUtils.readAsciiLine(bis));
|
||||
spiderInfo.previewSize = IOUtils.readAsciiLine(bis);
|
||||
if (!spiderInfo.previewSize.equals(EhConfig.PREVIEW_SIZE_NORMAL) &&
|
||||
!spiderInfo.previewSize.equals(EhConfig.PREVIEW_SIZE_LARGE)) {
|
||||
throw new IllegalStateException("Unknown preview size " + spiderInfo.previewSize);
|
||||
}
|
||||
spiderInfo.previewPages = Integer.parseInt(IOUtils.readAsciiLine(bis));
|
||||
spiderInfo.previewCountPerPage = Integer.parseInt(IOUtils.readAsciiLine(bis));
|
||||
|
||||
AutoExpandArray<String> tokens = new AutoExpandArray<>(spiderInfo.pages);
|
||||
try {
|
||||
//noinspection InfiniteLoopStatement
|
||||
for (;;) {
|
||||
String line = IOUtils.readAsciiLine(is);
|
||||
int pos = line.indexOf(":");
|
||||
if (pos == -1) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
int index = Integer.parseInt(line.substring(0, pos));
|
||||
String token = line.substring(pos + 1);
|
||||
tokens.set(index, token);
|
||||
} catch (NumberFormatException e) {
|
||||
// Empty
|
||||
}
|
||||
}
|
||||
} catch (EOFException e) {
|
||||
// Empty
|
||||
}
|
||||
spiderInfo.tokens = tokens;
|
||||
|
||||
return spiderInfo;
|
||||
}
|
||||
|
||||
public static String stringToHexString(String str) {
|
||||
StringBuilder sb = new StringBuilder(320);
|
||||
int length = str.length();
|
||||
for (int i = 0; i < length; i++) {
|
||||
char ch = str.charAt(i);
|
||||
String s = Integer.toString((int) ch, 16);
|
||||
int length2 = 4 - s.length();
|
||||
for (int j = 0; j < length2; j++) {
|
||||
sb.append('0');
|
||||
}
|
||||
sb.append(s);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static String hexStringToString(String str) {
|
||||
AssertUtils.assertEquals("Hex String's length must be a multiple of 4.", str.length() % 4, 0);
|
||||
|
||||
StringBuilder sb = new StringBuilder(80);
|
||||
int length = str.length();
|
||||
for (int i = 0; i < length; i += 4) {
|
||||
sb.append((char) Integer.parseInt(str.substring(i, i + 4), 16));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright 2015 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.gallery;
|
||||
|
||||
import com.hippo.ehviewer.client.EhConfig;
|
||||
import com.hippo.ehviewer.client.ParseException;
|
||||
import com.hippo.ehviewer.client.ParserUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class SpiderParser {
|
||||
|
||||
public static class Result {
|
||||
public int pages;
|
||||
public int previewPages;
|
||||
public String previewSize;
|
||||
public int startIndex;
|
||||
public List<String> tokens;
|
||||
}
|
||||
|
||||
public static final int REQUEST_PREVIEW = 0;
|
||||
public static final int REQUEST_ALL = 1;
|
||||
|
||||
public static Result parse(String body, int request) throws Exception {
|
||||
Result result = new Result();
|
||||
Pattern p;
|
||||
Matcher m;
|
||||
|
||||
if (request == REQUEST_ALL) {
|
||||
p = Pattern.compile("<tr><td[^<>]*>Length:</td><td[^<>]*>([\\d,]+) pages</td></tr>");
|
||||
m = p.matcher(body);
|
||||
if (m.find()) {
|
||||
result.pages = ParserUtils.parseInt(m.group(1));
|
||||
} else {
|
||||
throw new ParseException("Parse pages error", body);
|
||||
}
|
||||
|
||||
p = Pattern.compile("<td[^>]+><a[^>]+>([\\d,]+)</a></td><td[^>]+>(?:<a[^>]+>)?>(?:</a>)?</td>");
|
||||
m = p.matcher(body);
|
||||
if (m.find()) {
|
||||
result.previewPages = ParserUtils.parseInt(m.group(1));
|
||||
} else {
|
||||
throw new ParseException("Parse preview page count error", body);
|
||||
}
|
||||
}
|
||||
|
||||
List<String> list;
|
||||
if (body.contains("<div class=\"gdtm\"")) {
|
||||
result.previewSize = EhConfig.PREVIEW_SIZE_NORMAL;
|
||||
p = Pattern.compile("<div class=\"gdtm\"[^>]+><div[^>]+><a href=\"[^\"]+/(\\w+)/(\\d+)-(\\d+)\">");
|
||||
list = new ArrayList<>(40);
|
||||
} else {
|
||||
result.previewSize = EhConfig.PREVIEW_SIZE_LARGE;
|
||||
p = Pattern.compile("<div class=\"gdtl\"[^>]+><a href=\"[^\"]+/(\\w+)/(\\d+)-(\\d+)\">");
|
||||
list = new ArrayList<>(20);
|
||||
}
|
||||
result.tokens = list;
|
||||
m = p.matcher(body);
|
||||
|
||||
boolean first = true;
|
||||
while (m.find()) {
|
||||
if (first) {
|
||||
first = false;
|
||||
result.startIndex = Integer.parseInt(m.group(3)) - 1;
|
||||
}
|
||||
list.add(m.group(1));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,583 @@
|
||||
/*
|
||||
* Copyright 2015 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.gallery;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.Process;
|
||||
|
||||
import com.hippo.ehviewer.client.EhConfig;
|
||||
import com.hippo.ehviewer.client.EhUrl;
|
||||
import com.hippo.ehviewer.client.GalleryPageParser;
|
||||
import com.hippo.ehviewer.client.data.GalleryBase;
|
||||
import com.hippo.ehviewer.network.EhHttpClient;
|
||||
import com.hippo.ehviewer.network.EhHttpRequest;
|
||||
import com.hippo.ehviewer.util.Settings;
|
||||
import com.hippo.httpclient.HttpRequest;
|
||||
import com.hippo.httpclient.HttpResponse;
|
||||
import com.hippo.yorozuya.AutoExpandArray;
|
||||
import com.hippo.yorozuya.FileUtils;
|
||||
import com.hippo.yorozuya.PriorityThreadFactory;
|
||||
import com.hippo.yorozuya.Say;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public class SpiderQueen implements Runnable {
|
||||
|
||||
private static final String TAG = SpiderQueen.class.getSimpleName();
|
||||
|
||||
private static final String[] URL_509_SUFFIX_ARRAY = {
|
||||
"/509.gif",
|
||||
"/509s.gif"
|
||||
};
|
||||
|
||||
public static final int PAGE_STATE_NONE = 0;
|
||||
public static final int PAGE_STATE_DOWNLOADING = 1;
|
||||
public static final int PAGE_STATE_SUCCEED = 2;
|
||||
public static final int PAGE_STATE_FAILED = 3;
|
||||
|
||||
public EhHttpClient mHttpClient;
|
||||
public File mSpiderInfoDir;
|
||||
public GalleryBase mGalleryBase;
|
||||
public ImageHandler mImageHandler;
|
||||
public int mSource;
|
||||
private ImageHandler.Mode mMode;
|
||||
private SpiderListener mSpiderListener;
|
||||
|
||||
public SpiderInfo mSpiderInfo;
|
||||
public int mNextIndex;
|
||||
public int[] mPageStates;
|
||||
|
||||
public boolean mHasCheckIndexAgain = true;
|
||||
|
||||
private ThreadFactory mThreadFactory = new PriorityThreadFactory("SpiderWorker",
|
||||
Process.THREAD_PRIORITY_BACKGROUND);
|
||||
private SpiderWorker[] mSpiderWorkers;
|
||||
private LinkedList<Integer> mRequestTokens = new LinkedList<>();
|
||||
private Render mRender;
|
||||
|
||||
private final Object mQueenLock = new Object();
|
||||
private final Object mWorkerLock = new Object();
|
||||
private final Object mPageLock = new Object();
|
||||
private final ReentrantLock mWorkerArrayLock = new ReentrantLock();
|
||||
// Lock for mRequestTokens and mSpiderInfo.tokens
|
||||
private final Object mTokenLock = new Object();
|
||||
|
||||
private boolean mStop = false;
|
||||
|
||||
public SpiderQueen(EhHttpClient httpClient, File spiderInfoDir,
|
||||
GalleryBase galleryBase, ImageHandler.Mode mode, SpiderListener listener) {
|
||||
mHttpClient = httpClient;
|
||||
mSpiderInfoDir = spiderInfoDir;
|
||||
mGalleryBase = galleryBase;
|
||||
mSource = Settings.getEhSource();
|
||||
mMode = mode;
|
||||
mSpiderListener = listener;
|
||||
}
|
||||
|
||||
public void setMode(ImageHandler.Mode mode) {
|
||||
mMode = mode;
|
||||
if (mImageHandler != null) {
|
||||
mImageHandler.setMode(mode);
|
||||
}
|
||||
}
|
||||
|
||||
public void request(int index) {
|
||||
if (mRender == null) {
|
||||
mSpiderListener.onGetNone(index);
|
||||
} else {
|
||||
mRender.request(index);
|
||||
}
|
||||
}
|
||||
|
||||
public void releaseBitmap(Bitmap bitmap) {
|
||||
if (mImageHandler != null) {
|
||||
mImageHandler.releaseBitmap(bitmap);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Say.d(TAG, "Spider Queen starts");
|
||||
|
||||
EhConfig ehConfig = mHttpClient.getEhConfigClone();
|
||||
GalleryBase gb = mGalleryBase;
|
||||
SpiderInfo spiderInfo = null;
|
||||
|
||||
// 1. get spider info from dir
|
||||
File spiderInfoFile = new File(mSpiderInfoDir, Integer.toString(gb.gid));
|
||||
if (spiderInfoFile.exists()) {
|
||||
try {
|
||||
spiderInfo = SpiderInfo.read(new FileInputStream(spiderInfoFile));
|
||||
if (gb.gid != spiderInfo.galleryBase.gid) {
|
||||
spiderInfo = null;
|
||||
throw new IllegalStateException("Gid not match in SpiderInfo file");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileUtils.delete(spiderInfoFile);
|
||||
}
|
||||
}
|
||||
// Check stop
|
||||
if (mStop) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. if can't get spider info from dir, get it from internet
|
||||
if (spiderInfo == null) {
|
||||
// Use normal size to get more preview
|
||||
ehConfig.previewSize = EhConfig.PREVIEW_SIZE_NORMAL;
|
||||
ehConfig.setDirty();
|
||||
|
||||
EhHttpRequest request = new EhHttpRequest();
|
||||
request.setEhConfig(ehConfig);
|
||||
request.setUrl(EhUrl.getDetailUrl(mSource, gb.gid, gb.token, 0));
|
||||
try {
|
||||
HttpResponse response = mHttpClient.execute(request);
|
||||
String body = response.getString();
|
||||
SpiderParser.Result result = SpiderParser.parse(body, SpiderParser.REQUEST_ALL);
|
||||
spiderInfo = new SpiderInfo();
|
||||
spiderInfo.galleryBase = gb;
|
||||
spiderInfo.pages = result.pages;
|
||||
spiderInfo.previewSize = result.previewSize;
|
||||
spiderInfo.previewPages = result.previewPages;
|
||||
spiderInfo.previewCountPerPage = result.tokens.size();
|
||||
spiderInfo.tokens = new AutoExpandArray<>(spiderInfo.pages);
|
||||
} catch (Exception e) {
|
||||
// TODO Add a listener to tell spider error
|
||||
e.printStackTrace();
|
||||
return;
|
||||
} finally {
|
||||
request.disconnect();
|
||||
}
|
||||
}
|
||||
// Update EhConfig preview size
|
||||
ehConfig.previewSize = spiderInfo.previewSize;
|
||||
// Write to file
|
||||
try {
|
||||
spiderInfo.write(new FileOutputStream(spiderInfoFile));
|
||||
} catch (IOException e) {
|
||||
// Ignore
|
||||
}
|
||||
// Check stop
|
||||
if (mStop) {
|
||||
return;
|
||||
}
|
||||
// Listener
|
||||
mSpiderListener.onGetPages(spiderInfo.pages);
|
||||
|
||||
// 3. prepare
|
||||
mSpiderInfo = spiderInfo;
|
||||
mNextIndex = 0;
|
||||
mPageStates = new int[spiderInfo.pages];
|
||||
Arrays.fill(mPageStates, PAGE_STATE_NONE);
|
||||
mSpiderWorkers = new SpiderWorker[3];
|
||||
mImageHandler = new ImageHandler(gb, spiderInfo.pages, mMode);
|
||||
// Check stop
|
||||
if (mStop) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 4. Make Worker to do work
|
||||
ensureWorker();
|
||||
mRender = new Render();
|
||||
Thread thread = new Thread(mRender, "Render");
|
||||
thread.setPriority(Process.THREAD_PRIORITY_BACKGROUND);
|
||||
thread.start();
|
||||
|
||||
// 4. Get tokens
|
||||
while (!mStop) {
|
||||
Integer index;
|
||||
synchronized (mTokenLock) {
|
||||
index = mRequestTokens.poll();
|
||||
}
|
||||
|
||||
if (index == null) {
|
||||
// Can't get request index
|
||||
synchronized (mQueenLock) {
|
||||
try {
|
||||
mQueenLock.wait();
|
||||
} catch (InterruptedException e) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if we has the token first
|
||||
String token;
|
||||
synchronized (mTokenLock) {
|
||||
token = spiderInfo.tokens.get(index);
|
||||
}
|
||||
if (token == null) {
|
||||
SpiderParser.Result result;
|
||||
int previewIndex = index / spiderInfo.previewCountPerPage;
|
||||
EhHttpRequest request = new EhHttpRequest();
|
||||
request.setEhConfig(ehConfig);
|
||||
request.setUrl(EhUrl.getDetailUrl(mSource, gb.gid, gb.token, previewIndex));
|
||||
try {
|
||||
HttpResponse response = mHttpClient.execute(request);
|
||||
String body = response.getString();
|
||||
result = SpiderParser.parse(body, SpiderParser.REQUEST_PREVIEW);
|
||||
} catch (Exception e) {
|
||||
// TODO Add a listener to tell spider error
|
||||
e.printStackTrace();
|
||||
break;
|
||||
} finally {
|
||||
request.disconnect();
|
||||
}
|
||||
synchronized (mTokenLock) {
|
||||
AutoExpandArray<String> tokens = spiderInfo.tokens;
|
||||
List<String> list = result.tokens;
|
||||
int start = result.startIndex;
|
||||
int end = start + list.size();
|
||||
for (int i = start; i < end; i++) {
|
||||
tokens.set(i, list.get(i - start));
|
||||
}
|
||||
}
|
||||
// Write to file
|
||||
try {
|
||||
spiderInfo.write(new FileOutputStream(spiderInfoFile));
|
||||
} catch (IOException e) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
// Notify
|
||||
synchronized (mWorkerLock) {
|
||||
mWorkerLock.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
// 5. The queen dies, workers die, render dies
|
||||
mWorkerArrayLock.lock();
|
||||
|
||||
for (SpiderWorker worker : mSpiderWorkers) {
|
||||
if (worker != null) {
|
||||
worker.mStop = true;
|
||||
}
|
||||
}
|
||||
synchronized (mWorkerLock) {
|
||||
mWorkerLock.notifyAll();
|
||||
}
|
||||
|
||||
mWorkerArrayLock.unlock();
|
||||
|
||||
mRender.stop();
|
||||
|
||||
|
||||
Say.d(TAG, "Spider dies");
|
||||
}
|
||||
|
||||
public int pages() {
|
||||
if (mSpiderInfo != null) {
|
||||
return mSpiderInfo.pages;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
mStop = true;
|
||||
synchronized (mQueenLock) {
|
||||
mQueenLock.notify();
|
||||
}
|
||||
}
|
||||
|
||||
private void ensureWorker() {
|
||||
mWorkerArrayLock.lock();
|
||||
|
||||
int length = mSpiderWorkers.length;
|
||||
for (int i = 0; i < length; i++) {
|
||||
if (mSpiderWorkers[i] == null) {
|
||||
SpiderWorker worker = new SpiderWorker(i);
|
||||
mSpiderWorkers[i] = worker;
|
||||
mThreadFactory.newThread(worker).start();
|
||||
}
|
||||
}
|
||||
|
||||
mWorkerArrayLock.unlock();
|
||||
}
|
||||
|
||||
public void setNextIndex(int index) {
|
||||
synchronized (mPageLock) {
|
||||
if (mSpiderInfo != null && index < mSpiderInfo.pages) {
|
||||
mNextIndex = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getTokenByIndex(int index) {
|
||||
synchronized (mTokenLock) {
|
||||
String token = mSpiderInfo.tokens.get(index);
|
||||
if (token == null && !mRequestTokens.contains(index)) {
|
||||
mRequestTokens.offer(index);
|
||||
}
|
||||
// Notify Queen
|
||||
synchronized (mQueenLock) {
|
||||
mQueenLock.notify();
|
||||
}
|
||||
return token;
|
||||
}
|
||||
}
|
||||
|
||||
private int getRequestIndex() {
|
||||
synchronized (mPageLock) {
|
||||
int length = mSpiderInfo.pages;
|
||||
if (mNextIndex >= length) {
|
||||
if (!mHasCheckIndexAgain) {
|
||||
mHasCheckIndexAgain = true;
|
||||
mNextIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
while (mNextIndex < length && mPageStates[mNextIndex] != PAGE_STATE_NONE) {
|
||||
mNextIndex++;
|
||||
}
|
||||
|
||||
return mNextIndex >= length ? -1 : mNextIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
class SpiderWorker implements Runnable {
|
||||
|
||||
private final String TAG = SpiderWorker.class.getSimpleName();
|
||||
|
||||
public int mIndex;
|
||||
|
||||
public boolean mStop = false;
|
||||
|
||||
public SpiderWorker(int index) {
|
||||
mIndex = index;
|
||||
}
|
||||
|
||||
private String getImageUrl(int gid, String token, int index) throws Exception {
|
||||
HttpRequest request = new HttpRequest();
|
||||
request.setUrl(EhUrl.getPageUrl(mSource, mGalleryBase.gid, token, index));
|
||||
try {
|
||||
HttpResponse response = mHttpClient.execute(request);
|
||||
String body = response.getString();
|
||||
String imageUrl = GalleryPageParser.parse(body);
|
||||
for (String suffix : URL_509_SUFFIX_ARRAY) {
|
||||
if (imageUrl.endsWith(suffix)) {
|
||||
// Get 509 gif here
|
||||
throw new Image509Expection();
|
||||
}
|
||||
}
|
||||
return imageUrl;
|
||||
} finally {
|
||||
request.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Say.d(TAG, "Spider worker starts");
|
||||
|
||||
GalleryBase gb = mGalleryBase;
|
||||
ImageHandler handler = mImageHandler;
|
||||
|
||||
while (!mStop) {
|
||||
// Get index
|
||||
int index;
|
||||
synchronized (mPageLock) {
|
||||
index = getRequestIndex();
|
||||
if (index == -1) {
|
||||
// There is no more
|
||||
break;
|
||||
} else {
|
||||
mPageStates[index] = PAGE_STATE_DOWNLOADING;
|
||||
}
|
||||
}
|
||||
|
||||
// Check contain
|
||||
if (handler.contain(index)) {
|
||||
// Find it, no need to download
|
||||
synchronized (mPageLock) {
|
||||
mPageStates[index] = PAGE_STATE_SUCCEED;
|
||||
}
|
||||
// Listener
|
||||
mSpiderListener.onSpiderSucceed(index);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get token
|
||||
String token;
|
||||
for (;;) {
|
||||
token = getTokenByIndex(index);
|
||||
if (token == null) {
|
||||
synchronized (mWorkerLock) {
|
||||
try {
|
||||
mWorkerLock.wait();
|
||||
} catch (InterruptedException e) {
|
||||
// Ignore
|
||||
}
|
||||
if (mStop) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// For stop
|
||||
if (mStop) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// Get image url
|
||||
String imageUrl;
|
||||
try {
|
||||
imageUrl = getImageUrl(gb.gid, token, index);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
// TODO notify 509 error
|
||||
synchronized (mPageLock) {
|
||||
mPageStates[index] = PAGE_STATE_FAILED;
|
||||
}
|
||||
// Listener
|
||||
mSpiderListener.onSpiderFailed(index);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Download image
|
||||
HttpRequest request = new HttpRequest();
|
||||
request.setUrl(imageUrl);
|
||||
try {
|
||||
HttpResponse response = mHttpClient.execute(request);
|
||||
handler.save(index, response);
|
||||
|
||||
synchronized (mPageLock) {
|
||||
mPageStates[index] = PAGE_STATE_SUCCEED;
|
||||
}
|
||||
// Listener
|
||||
mSpiderListener.onSpiderSucceed(index);
|
||||
} catch (Exception e) {
|
||||
synchronized (mPageLock) {
|
||||
mPageStates[index] = PAGE_STATE_FAILED;
|
||||
}
|
||||
// Listener
|
||||
mSpiderListener.onSpiderFailed(index);
|
||||
} finally {
|
||||
request.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO this lock is not right, we need to lock when before check it is over
|
||||
mWorkerArrayLock.lock();
|
||||
mSpiderWorkers[mIndex] = null;
|
||||
mWorkerArrayLock.unlock();
|
||||
|
||||
Say.d(TAG, "Spider Worker dies");
|
||||
}
|
||||
}
|
||||
|
||||
// The runner to handle request
|
||||
class Render implements Runnable {
|
||||
|
||||
private final String TAG = Render.class.getSimpleName();
|
||||
|
||||
private boolean mStop = false;
|
||||
|
||||
private final Object mRenderLock = new Object();
|
||||
|
||||
private BlockingQueue<Integer> mQueue = new LinkedBlockingQueue<>();
|
||||
|
||||
public void stop() {
|
||||
mStop = true;
|
||||
synchronized (mRenderLock) {
|
||||
mRenderLock.notify();
|
||||
}
|
||||
}
|
||||
|
||||
public void request(int index) {
|
||||
mQueue.offer(index);
|
||||
synchronized (mRenderLock) {
|
||||
mRenderLock.notify();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Say.d(TAG, "Render starts");
|
||||
|
||||
while (!mStop) {
|
||||
|
||||
Integer index = mQueue.poll();
|
||||
if (index == null) {
|
||||
synchronized (mRenderLock) {
|
||||
try {
|
||||
mRenderLock.wait();
|
||||
} catch (InterruptedException e) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
int state;
|
||||
synchronized (mPageLock) {
|
||||
state = mPageStates[index];
|
||||
}
|
||||
|
||||
switch (state) {
|
||||
case PAGE_STATE_NONE:
|
||||
mSpiderListener.onGetNone(index);
|
||||
break;
|
||||
case PAGE_STATE_DOWNLOADING:
|
||||
mSpiderListener.onGetSpider(index, 0.5f); // TODO
|
||||
break;
|
||||
case PAGE_STATE_SUCCEED:
|
||||
mSpiderListener.onGetBitmap(index, mImageHandler == null ? null : mImageHandler.getBitmap(index));
|
||||
break;
|
||||
default:
|
||||
case PAGE_STATE_FAILED:
|
||||
mSpiderListener.onGetFailed(index);
|
||||
}
|
||||
}
|
||||
|
||||
Say.d(TAG, "Render dies");
|
||||
}
|
||||
}
|
||||
|
||||
public interface SpiderListener {
|
||||
|
||||
void onGetPages(int pages);
|
||||
|
||||
void onSpiderPage(int index, float percent);
|
||||
|
||||
void onSpiderSucceed(int index);
|
||||
|
||||
void onSpiderFailed(int index);
|
||||
|
||||
void onGetNone(int index);
|
||||
|
||||
void onGetBitmap(int index, Bitmap bitmap);
|
||||
|
||||
void onGetSpider(int index, float percent);
|
||||
|
||||
void onGetFailed(int index);
|
||||
}
|
||||
}
|
||||
@@ -58,6 +58,10 @@ public class EhHttpClient extends HttpClient {
|
||||
mEhConfig = Settings.generateEhConfig();
|
||||
}
|
||||
|
||||
public EhConfig getEhConfigClone() {
|
||||
return mEhConfig.clone();
|
||||
}
|
||||
|
||||
public void setExcludedLanguages(String excludedLanguages) {
|
||||
mEhConfig.excludedLanguages = excludedLanguages;
|
||||
mEhConfig.setDirty();
|
||||
|
||||
@@ -40,9 +40,9 @@ public class CommentScene extends AppbarScene implements EasyRecyclerView.OnItem
|
||||
return;
|
||||
}
|
||||
|
||||
Object obj = announcer.getExtra(KEY_COMMENTS);
|
||||
if (obj instanceof List) {
|
||||
mCommentList = (List<Comment>) obj;
|
||||
List<Comment> list = announcer.getExtra(KEY_COMMENTS, List.class);
|
||||
if (list != null) {
|
||||
mCommentList = list;
|
||||
} else {
|
||||
finish();
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ import android.widget.ViewSwitcher;
|
||||
import com.hippo.conaco.Conaco;
|
||||
import com.hippo.effect.ViewTransition;
|
||||
import com.hippo.ehviewer.EhApplication;
|
||||
import com.hippo.ehviewer.EhImageKeyFactory;
|
||||
import com.hippo.ehviewer.EhCacheKeyFactory;
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.client.EhClient;
|
||||
import com.hippo.ehviewer.client.EhException;
|
||||
@@ -144,12 +144,11 @@ public class GalleryDetailScene extends Scene implements View.OnClickListener,
|
||||
|
||||
String action = announcer.getAction();
|
||||
if (ACTION_GALLERY_INFO.equals(action)) {
|
||||
Object obj = announcer.getExtra(KEY_GALLERY_INFO);
|
||||
if (obj instanceof GalleryInfo) {
|
||||
GalleryInfo gi = (GalleryInfo) obj;
|
||||
GalleryInfo gi = announcer.getExtra(KEY_GALLERY_INFO, GalleryInfo.class);
|
||||
if (gi != null) {
|
||||
|
||||
Conaco conaco = EhApplication.getConaco(getStageActivity());
|
||||
mThumb.load(conaco, EhImageKeyFactory.getThumbKey(gi.gid), gi.thumb);
|
||||
mThumb.load(conaco, EhCacheKeyFactory.getThumbKey(gi.gid), gi.thumb);
|
||||
String title;
|
||||
if (Settings.getJpnTitle()) {
|
||||
title = TextUtils.isEmpty(gi.titleJpn) ? gi.title : gi.titleJpn;
|
||||
@@ -279,7 +278,9 @@ public class GalleryDetailScene extends Scene implements View.OnClickListener,
|
||||
}
|
||||
|
||||
if (v == mRead) {
|
||||
|
||||
Announcer announcer = new Announcer();
|
||||
announcer.putExtra(GalleryScene.KEY_GALLERY_BASE, mGalleryDetail);
|
||||
startScene(GalleryScene.class, announcer);
|
||||
} else if (v == mDownload) {
|
||||
|
||||
} else if (v == mFavorite) {
|
||||
|
||||
@@ -42,7 +42,7 @@ import com.hippo.drawable.AddDeleteDrawable;
|
||||
import com.hippo.effect.ViewTransition;
|
||||
import com.hippo.ehviewer.Constants;
|
||||
import com.hippo.ehviewer.EhApplication;
|
||||
import com.hippo.ehviewer.EhImageKeyFactory;
|
||||
import com.hippo.ehviewer.EhCacheKeyFactory;
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.client.EhClient;
|
||||
import com.hippo.ehviewer.client.EhRequest;
|
||||
@@ -958,7 +958,7 @@ public final class GalleryListScene extends Scene implements SearchBar.Helper,
|
||||
GalleryInfo gi = getDataAt(position);
|
||||
|
||||
Conaco conaco = EhApplication.getConaco(getStageActivity());
|
||||
holder.thumb.load(conaco, EhImageKeyFactory.getThumbKey(gi.gid), gi.thumb);
|
||||
holder.thumb.load(conaco, EhCacheKeyFactory.getThumbKey(gi.gid), gi.thumb);
|
||||
String title;
|
||||
if (mJpnTitle) {
|
||||
title = TextUtils.isEmpty(gi.titleJpn) ? gi.title : gi.titleJpn;
|
||||
|
||||
@@ -110,9 +110,8 @@ public class InfoScene extends AppbarScene implements EasyRecyclerView.OnItemLon
|
||||
return;
|
||||
}
|
||||
|
||||
Object obj = announcer.getExtra(KEY_INFO);
|
||||
if (obj instanceof GalleryDetail) {
|
||||
GalleryDetail gd = (GalleryDetail) obj;
|
||||
GalleryDetail gd = announcer.getExtra(KEY_INFO, GalleryDetail.class);
|
||||
if (gd != null) {
|
||||
addData(R.string.header_key, mResources.getString(R.string.header_value));
|
||||
addData(R.string.key_gid, Integer.toString(gd.gid));
|
||||
addData(R.string.key_token, gd.token);
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright 2015 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.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
|
||||
import com.hippo.ehviewer.client.data.GalleryBase;
|
||||
import com.hippo.ehviewer.dao.DaoMaster;
|
||||
import com.hippo.ehviewer.dao.DaoSession;
|
||||
import com.hippo.ehviewer.dao.GalleryBaseObj;
|
||||
import com.hippo.ehviewer.dao.GalleryBaseObjDao;
|
||||
import com.hippo.ehviewer.dao.SpiderObj;
|
||||
|
||||
public class DBUtils {
|
||||
|
||||
private static DaoSession sDaoSession;
|
||||
|
||||
public static void initialize(Context context) {
|
||||
DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(
|
||||
context.getApplicationContext(), "ehviewer", null);
|
||||
SQLiteDatabase db = helper.getWritableDatabase();
|
||||
DaoMaster daoMaster = new DaoMaster(db);
|
||||
sDaoSession = daoMaster.newSession();
|
||||
}
|
||||
|
||||
public static SpiderObj getSpiderObj(int gid) {
|
||||
return sDaoSession.getSpiderObjDao().load((long) gid);
|
||||
}
|
||||
|
||||
public static void insertSpiderObj(SpiderObj spiderObj) {
|
||||
sDaoSession.getSpiderObjDao().insert(spiderObj);
|
||||
}
|
||||
|
||||
public static void addGalleryBase(GalleryBase galleryBase) {
|
||||
GalleryBaseObjDao galleryBaseObjDao = sDaoSession.getGalleryBaseObjDao();
|
||||
GalleryBaseObj galleryBaseObj = galleryBaseObjDao.load((long) galleryBase.gid);
|
||||
if (galleryBaseObj == null) {
|
||||
// add new item, set refernce 1
|
||||
galleryBaseObj = new GalleryBaseObj();
|
||||
galleryBaseObj.setGid((long) galleryBase.gid);
|
||||
galleryBaseObj.setToken(galleryBase.token);
|
||||
galleryBaseObj.setTitle(galleryBase.title);
|
||||
galleryBaseObj.setTitleJpn(galleryBase.titleJpn);
|
||||
galleryBaseObj.setThumb(galleryBase.thumb);
|
||||
galleryBaseObj.setCategory(galleryBase.category);
|
||||
galleryBaseObj.setPosted(galleryBase.posted);
|
||||
galleryBaseObj.setUploader(galleryBase.uploader);
|
||||
galleryBaseObj.setRating(galleryBase.rating);
|
||||
galleryBaseObj.setReference(1);
|
||||
galleryBaseObjDao.insert(galleryBaseObj);
|
||||
} else {
|
||||
// already in db, add refernce
|
||||
galleryBaseObj.setReference(galleryBaseObj.getReference() + 1);
|
||||
galleryBaseObjDao.update(galleryBaseObj);
|
||||
}
|
||||
}
|
||||
|
||||
public static void removeGalleryBase(GalleryBase galleryBase) {
|
||||
GalleryBaseObjDao galleryBaseObjDao = sDaoSession.getGalleryBaseObjDao();
|
||||
GalleryBaseObj galleryBaseObj = galleryBaseObjDao.load((long) galleryBase.gid);
|
||||
if (galleryBaseObj.getReference() <= 1) {
|
||||
// No reference, delete it
|
||||
galleryBaseObjDao.deleteByKey((long) galleryBase.gid);
|
||||
} else {
|
||||
// Still has reference, sub refernce
|
||||
galleryBaseObj.setReference(galleryBaseObj.getReference() - 1);
|
||||
galleryBaseObjDao.update(galleryBaseObj);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,9 +20,11 @@ import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import com.hippo.ehviewer.AppConfig;
|
||||
import com.hippo.ehviewer.BuildConfig;
|
||||
import com.hippo.ehviewer.client.EhConfig;
|
||||
import com.hippo.ehviewer.client.EhUrl;
|
||||
import com.hippo.unifile.UniFile;
|
||||
|
||||
public final class Settings {
|
||||
|
||||
@@ -188,6 +190,11 @@ public final class Settings {
|
||||
return getInt(KEY_PREVIEW_SIZE, DEFAULT_PREVIEW_SIZE);
|
||||
}
|
||||
|
||||
|
||||
public static UniFile getDownloadPath() {
|
||||
return UniFile.fromFile(AppConfig.getDownloadDir());
|
||||
}
|
||||
|
||||
/****** Advance ******/
|
||||
private static final String KEY_SHOW_APPLICATION_STATS = "show_application_stats";
|
||||
private static final boolean DEFAULT_SHOW_APPLICATION_STATS = BuildConfig.DEBUG;
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2015 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.io;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import com.hippo.unifile.UniFile;
|
||||
import com.hippo.yorozuya.IOUtils;
|
||||
import com.hippo.yorozuya.io.InputStreamPipe;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public class UniFileInputStreamPipe implements InputStreamPipe {
|
||||
|
||||
private UniFile mUniFile;
|
||||
|
||||
private InputStream mIs;
|
||||
|
||||
public UniFileInputStreamPipe(UniFile uniFile) {
|
||||
mUniFile = uniFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void obtain() {
|
||||
// Empty
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release() {
|
||||
// Empty
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull InputStream open() throws IOException {
|
||||
if (mIs != null) {
|
||||
throw new IllegalStateException("Please close it first");
|
||||
}
|
||||
|
||||
mIs = mUniFile.openInputStream();
|
||||
return mIs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
IOUtils.closeQuietly(mIs);
|
||||
mIs = null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2015 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.io;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import com.hippo.unifile.UniFile;
|
||||
import com.hippo.yorozuya.IOUtils;
|
||||
import com.hippo.yorozuya.io.OutputStreamPipe;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class UniFileOutputStreamPipe implements OutputStreamPipe {
|
||||
|
||||
private UniFile mUniFile;
|
||||
|
||||
private OutputStream mOs;
|
||||
|
||||
public UniFileOutputStreamPipe(UniFile uniFile) {
|
||||
mUniFile = uniFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void obtain() {
|
||||
// Empty
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release() {
|
||||
// Empty
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull OutputStream open() throws IOException {
|
||||
if (mOs != null) {
|
||||
throw new IllegalStateException("Please close it first");
|
||||
}
|
||||
|
||||
mOs = mUniFile.openOutputStream();
|
||||
return mOs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
IOUtils.closeQuietly(mOs);
|
||||
mOs = null;
|
||||
}
|
||||
}
|
||||
@@ -118,8 +118,14 @@ public class Announcer {
|
||||
}
|
||||
}
|
||||
|
||||
public Object getExtra(String key) {
|
||||
return mMap.get(key);
|
||||
@SuppressWarnings("unchecked")
|
||||
public <E> E getExtra(String key, Class<E> clazz) {
|
||||
Object obj = mMap.get(key);
|
||||
if (clazz.isInstance(obj)) {
|
||||
return (E) obj;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void removeExtra(String key) {
|
||||
|
||||
Reference in new issue
Block a user