|
|
@@ -42,6 +42,9 @@ public class ImageDeepDetector {
|
|
|
private static final int GALLERY_CACHE = 3;
|
|
|
private static final int JPG_MAGIC = 4;
|
|
|
private static final int OPPO_GALLERY_CACHE = 5;
|
|
|
+ private static final int VIVO_GALLERY_CACHE = 6;
|
|
|
+ private static final int XIAOMI_GALLERY_CACHE = 7;
|
|
|
+ private static final int MEIZU_GALLERY_CACHE = 8;
|
|
|
|
|
|
public static Flowable<ImageFile> detect(Context context) {
|
|
|
return Flowable.create((FlowableOnSubscribe<XFile>) emitter -> {
|
|
|
@@ -84,21 +87,38 @@ public class ImageDeepDetector {
|
|
|
switch (tag) {
|
|
|
case JPG_MAGIC:
|
|
|
case IMAGE_SUFFIX:
|
|
|
- return Flowable.just(new ImageFile(xFile));
|
|
|
+ case XIAOMI_GALLERY_CACHE:
|
|
|
+ return Flowable.just(new ImageFile(xFile, ImageFile.CATEGORY_GALLERY));
|
|
|
case WECHAT_CACHE:
|
|
|
return detectWechatCache(context, xFile);
|
|
|
case GALLERY_CACHE:
|
|
|
return detectGalleryCache(context, xFile);
|
|
|
case OPPO_GALLERY_CACHE:
|
|
|
return detectOppoGalleryCache(context, xFile);
|
|
|
+ case VIVO_GALLERY_CACHE:
|
|
|
+ return detectVivoGalleryCache(context, xFile);
|
|
|
+ case MEIZU_GALLERY_CACHE:
|
|
|
+ return detectMeizuGalleryCache(context, xFile);
|
|
|
default:
|
|
|
return Flowable.empty();
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
|
|
|
- private static Publisher<ImageFile> detectOppoGalleryCache(Context context, XFile xFile) {
|
|
|
- return new GenericImgCollectionDetector(context, xFile)
|
|
|
+ private static Flowable<ImageFile> detectMeizuGalleryCache(Context context, XFile xFile) {
|
|
|
+ return new GenericImgCollectionDetector(context, xFile, ImageFile.CATEGORY_GALLERY)
|
|
|
+ .subscribeOn(Schedulers.io())
|
|
|
+ .onErrorComplete();
|
|
|
+ }
|
|
|
+
|
|
|
+ private static Flowable<ImageFile> detectVivoGalleryCache(Context context, XFile xFile) {
|
|
|
+ return new GenericImgCollectionDetector(context, xFile, ImageFile.CATEGORY_GALLERY)
|
|
|
+ .subscribeOn(Schedulers.io())
|
|
|
+ .onErrorComplete();
|
|
|
+ }
|
|
|
+
|
|
|
+ private static Flowable<ImageFile> detectOppoGalleryCache(Context context, XFile xFile) {
|
|
|
+ return new GenericImgCollectionDetector(context, xFile, ImageFile.CATEGORY_GALLERY)
|
|
|
.subscribeOn(Schedulers.io())
|
|
|
.onErrorComplete();
|
|
|
}
|
|
|
@@ -152,6 +172,18 @@ public class ImageDeepDetector {
|
|
|
file.setTag(OPPO_GALLERY_CACHE);
|
|
|
return true;
|
|
|
}
|
|
|
+ if (isVivoGalleryCacheFile(path)) {
|
|
|
+ file.setTag(VIVO_GALLERY_CACHE);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ if (isXiaomiGalleryCacheFile(path)) {
|
|
|
+ file.setTag(XIAOMI_GALLERY_CACHE);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ if (isMeizuGalleryCacheFile(path)) {
|
|
|
+ file.setTag(MEIZU_GALLERY_CACHE);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
} catch (Exception ignore) {
|
|
|
}
|
|
|
if (hasJpgMagic(file)) {
|
|
|
@@ -218,6 +250,40 @@ public class ImageDeepDetector {
|
|
|
|| path.contains("tilecache");
|
|
|
}
|
|
|
|
|
|
+ private static boolean isVivoGalleryCacheFile(String path) {
|
|
|
+ if (TextUtils.isEmpty(path)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (!path.contains("com.vivo.gallery%2Fcache") &&
|
|
|
+ !path.contains("com.vivo.gallery/cache")) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return path.contains("imgcache") || path.contains("trackthumbnail_cache");
|
|
|
+ }
|
|
|
+
|
|
|
+ private static boolean isXiaomiGalleryCacheFile(String path) {
|
|
|
+ if (TextUtils.isEmpty(path)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (!path.contains("com.miui.gallery%2Ffiles%2Fgallery_disk_cache") &&
|
|
|
+ !path.contains("com.miui.gallery/files/gallery_disk_cache")) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return path.contains("full_size") || path.contains("small_size");
|
|
|
+ }
|
|
|
+
|
|
|
+ private static boolean isMeizuGalleryCacheFile(String path) {
|
|
|
+ if (TextUtils.isEmpty(path)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (!path.contains("com.meizu.media.gallery%2Fcache") &&
|
|
|
+ !path.contains("com.meizu.media.gallery/cache")) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return path.contains("bestPhotoCache") || path.contains("face_thumbnails")
|
|
|
+ || path.contains("uri_thumbnail_cache");
|
|
|
+ }
|
|
|
+
|
|
|
private static boolean isImageSuffix(String name) {
|
|
|
if (TextUtils.isEmpty(name)) {
|
|
|
return false;
|
|
|
@@ -290,12 +356,24 @@ public class ImageDeepDetector {
|
|
|
}
|
|
|
|
|
|
public static class ImageFile {
|
|
|
+ public static int CATEGORY_UNKNOWN = -1;
|
|
|
+ public static int CATEGORY_OTHER = 0;
|
|
|
+ public static int CATEGORY_QQ = 1;
|
|
|
+ public static int CATEGORY_WECHAT = 2;
|
|
|
+ public static int CATEGORY_GALLERY = 3;
|
|
|
private final XFile xFile;
|
|
|
private String name;
|
|
|
private long size;
|
|
|
private Uri uri;
|
|
|
+ private String path;
|
|
|
+ private int category;
|
|
|
|
|
|
public ImageFile(XFile xFile) {
|
|
|
+ this(xFile, CATEGORY_UNKNOWN);
|
|
|
+ }
|
|
|
+
|
|
|
+ public ImageFile(XFile xFile, int category) {
|
|
|
+ this.category = category;
|
|
|
this.xFile = xFile;
|
|
|
try {
|
|
|
this.name = xFile.getName();
|
|
|
@@ -309,6 +387,10 @@ public class ImageDeepDetector {
|
|
|
this.uri = xFile.getUri();
|
|
|
} catch (Exception ignore) {
|
|
|
}
|
|
|
+ try {
|
|
|
+ this.path = xFile.getPath();
|
|
|
+ } catch (Exception ignore) {
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
public String getName() {
|
|
|
@@ -326,6 +408,55 @@ public class ImageDeepDetector {
|
|
|
public InputStream newInputStream() throws Exception {
|
|
|
return xFile.newInputStream();
|
|
|
}
|
|
|
+
|
|
|
+ public boolean delete() throws Exception {
|
|
|
+ return xFile.delete();
|
|
|
+ }
|
|
|
+
|
|
|
+ public int getCategory() {
|
|
|
+ if (category != CATEGORY_UNKNOWN) {
|
|
|
+ return category;
|
|
|
+ }
|
|
|
+ if (isGallery()) {
|
|
|
+ return CATEGORY_GALLERY;
|
|
|
+ } else if (isWechat()) {
|
|
|
+ return CATEGORY_WECHAT;
|
|
|
+ } else if (isQQ()) {
|
|
|
+ return CATEGORY_QQ;
|
|
|
+ } else {
|
|
|
+ return CATEGORY_OTHER;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean isQQ() {
|
|
|
+ if (TextUtils.isEmpty(path)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return path.contains("com.tencent.mobileqq") || path.contains("com.tencent.tim");
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean isWechat() {
|
|
|
+ if (!TextUtils.isEmpty(path) && path.contains("com.tencent.mm")) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean isGallery() {
|
|
|
+ if (!TextUtils.isEmpty(path) && (
|
|
|
+ path.contains("com.android.gallery3d") ||
|
|
|
+ path.contains("com.coloros.gallery3d") ||
|
|
|
+ path.contains("com.vivo.gallery") ||
|
|
|
+ path.contains("com.miui.gallery") ||
|
|
|
+ path.contains("com.meizu.media.gallery") ||
|
|
|
+ path.contains("com.oppo.gallery3d") ||
|
|
|
+ path.contains("com.android.gallery") ||
|
|
|
+ path.contains("DCIM")
|
|
|
+ )) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
private static class WechatCacheDetector extends Flowable<ImageFile> {
|
|
|
@@ -382,7 +513,7 @@ public class ImageDeepDetector {
|
|
|
if (imageBytes.get(imageBytes.size() - 2) == (byte) 0xFF && imageBytes.get(imageBytes.size() - 1) == (byte) 0xD9) {
|
|
|
File cache = new File(detectedCacheDir, UUID.randomUUID() + ".jpg");
|
|
|
if (cache.createNewFile() && bytes2File(imageBytes, cache)) {
|
|
|
- subscriber.onNext(new ImageFile(new XPathFile(context, cache)));
|
|
|
+ subscriber.onNext(new ImageFile(new XPathFile(context, cache), ImageFile.CATEGORY_WECHAT));
|
|
|
}
|
|
|
}
|
|
|
imageBytes.clear();
|
|
|
@@ -396,7 +527,7 @@ public class ImageDeepDetector {
|
|
|
imageBytes.remove(imageBytes.size() - 1);
|
|
|
File cache = new File(detectedCacheDir, UUID.randomUUID() + ".jpg");
|
|
|
if (cache.createNewFile() && bytes2File(imageBytes, cache)) {
|
|
|
- subscriber.onNext(new ImageFile(new XPathFile(context, cache)));
|
|
|
+ subscriber.onNext(new ImageFile(new XPathFile(context, cache), ImageFile.CATEGORY_WECHAT));
|
|
|
}
|
|
|
imageBytes.clear();
|
|
|
imageBytes.add((byte) 0xFF);
|
|
|
@@ -417,7 +548,7 @@ public class ImageDeepDetector {
|
|
|
File[] files = targetCaches.exists() && targetCaches.isDirectory() ? targetCaches.listFiles() : null;
|
|
|
if (files != null && files.length > 0) {
|
|
|
for (File file : files) {
|
|
|
- subscriber.onNext(new ImageFile(new XPathFile(this.context, file)));
|
|
|
+ subscriber.onNext(new ImageFile(new XPathFile(this.context, file), ImageFile.CATEGORY_WECHAT));
|
|
|
}
|
|
|
return true;
|
|
|
}
|
|
|
@@ -555,7 +686,7 @@ public class ImageDeepDetector {
|
|
|
}
|
|
|
File cache = new File(detectedCacheDir, UUID.randomUUID() + ".jpg");
|
|
|
if (cache.createNewFile() && bytes2File(cropData, cache)) {
|
|
|
- subscriber.onNext(new ImageFile(new XPathFile(context, cache)));
|
|
|
+ subscriber.onNext(new ImageFile(new XPathFile(context, cache), ImageFile.CATEGORY_GALLERY));
|
|
|
}
|
|
|
} catch (Exception ignore) {
|
|
|
}
|
|
|
@@ -574,7 +705,7 @@ public class ImageDeepDetector {
|
|
|
File[] files = targetCaches.exists() && targetCaches.isDirectory() ? targetCaches.listFiles() : null;
|
|
|
if (files != null && files.length > 0) {
|
|
|
for (File file : files) {
|
|
|
- subscriber.onNext(new ImageFile(new XPathFile(this.context, file)));
|
|
|
+ subscriber.onNext(new ImageFile(new XPathFile(this.context, file), ImageFile.CATEGORY_GALLERY));
|
|
|
}
|
|
|
return true;
|
|
|
}
|
|
|
@@ -845,13 +976,15 @@ public class ImageDeepDetector {
|
|
|
|
|
|
private static class GenericImgCollectionDetector extends Flowable<ImageFile> {
|
|
|
|
|
|
+ private final int category;
|
|
|
private String CACHE_DOMAIN = "generic_img_collection_detector";
|
|
|
private final Context context;
|
|
|
private final XFile xFile;
|
|
|
|
|
|
- public GenericImgCollectionDetector(Context context, XFile xFile) {
|
|
|
+ public GenericImgCollectionDetector(Context context, XFile xFile, int category) {
|
|
|
this.context = context;
|
|
|
this.xFile = xFile;
|
|
|
+ this.category = category;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
@@ -899,7 +1032,7 @@ public class ImageDeepDetector {
|
|
|
if (imageBytes.get(imageBytes.size() - 2) == (byte) 0xFF && imageBytes.get(imageBytes.size() - 1) == (byte) 0xD9) {
|
|
|
File cache = new File(detectedCacheDir, UUID.randomUUID() + ".jpg");
|
|
|
if (cache.createNewFile() && bytes2File(imageBytes, cache)) {
|
|
|
- subscriber.onNext(new ImageFile(new XPathFile(context, cache)));
|
|
|
+ subscriber.onNext(new ImageFile(new XPathFile(context, cache), category));
|
|
|
}
|
|
|
}
|
|
|
imageBytes.clear();
|
|
|
@@ -909,7 +1042,7 @@ public class ImageDeepDetector {
|
|
|
) {
|
|
|
File cache = new File(detectedCacheDir, UUID.randomUUID() + ".jpg");
|
|
|
if (cache.createNewFile() && bytes2File(imageBytes, cache)) {
|
|
|
- subscriber.onNext(new ImageFile(new XPathFile(context, cache)));
|
|
|
+ subscriber.onNext(new ImageFile(new XPathFile(context, cache), category));
|
|
|
}
|
|
|
imageBytes.clear();
|
|
|
}
|
|
|
@@ -928,7 +1061,7 @@ public class ImageDeepDetector {
|
|
|
File[] files = targetCaches.exists() && targetCaches.isDirectory() ? targetCaches.listFiles() : null;
|
|
|
if (files != null && files.length > 0) {
|
|
|
for (File file : files) {
|
|
|
- subscriber.onNext(new ImageFile(new XPathFile(this.context, file)));
|
|
|
+ subscriber.onNext(new ImageFile(new XPathFile(this.context, file), category));
|
|
|
}
|
|
|
return true;
|
|
|
}
|