diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index ee3789d8..0074dcd6 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -202,6 +202,10 @@ # Keep data models used for JSON parsing (Gson/Fruit) -keep class me.ghui.v2er.network.bean.** { *; } +# Keep ImagesInfo and related classes for Fruit HTML parsing +-keep class me.ghui.v2er.module.imgviewer.ImagesInfo { *; } +-keep class me.ghui.v2er.module.imgviewer.ImagesInfo$* { *; } +-keep class me.ghui.v2er.module.imgviewer.ImagesInfo$*$* { *; } # Keep classes with native methods -keepclasseswithmembernames class * { diff --git a/app/src/main/java/me/ghui/v2er/module/gallery/GalleryActivity.java b/app/src/main/java/me/ghui/v2er/module/gallery/GalleryActivity.java index 785e3ed7..f3a6d000 100644 --- a/app/src/main/java/me/ghui/v2er/module/gallery/GalleryActivity.java +++ b/app/src/main/java/me/ghui/v2er/module/gallery/GalleryActivity.java @@ -48,6 +48,26 @@ public class GalleryActivity extends BaseActivity implements SwipeToDismissTouch private ImagesInfo mData; public static void open(ImagesInfo imgsData, Context context) { + // Validate images data before opening gallery + if (imgsData == null || imgsData.getImages() == null || imgsData.getImages().isEmpty()) { + Voast.show("图片不存在"); + return; + } + + // Check if at least one valid image exists + boolean hasValidImage = false; + for (ImagesInfo.Images.Image img : imgsData.getImages()) { + if (img != null && img.getUrl() != null) { + hasValidImage = true; + break; + } + } + + if (!hasValidImage) { + Voast.show("图片不存在"); + return; + } + Navigator.from(context) .putExtra(EXTRA_IMG_DATA, imgsData) .to(GalleryActivity.class) @@ -134,12 +154,22 @@ public void onPageScrollStateChanged(int state) { private String getCurrentImage() { int index = mViewPager.getCurrentItem(); + if (mData == null || mData.getImages() == null || + index < 0 || index >= mData.getImages().size() || + mData.getImages().get(index) == null) { + return null; + } return mData.getImages().get(index).getUrl(); } private void saveImage() { + String currentImage = getCurrentImage(); + if (currentImage == null) { + Voast.show("图片不存在"); + return; + } // Already have permission, do the thing - glideRequest(getCurrentImage()).into(new SimpleTarget() { + glideRequest(currentImage).into(new SimpleTarget() { @Override public void onResourceReady(File file, Transition transition) { if (!FileUtils.isExternalStorageWritable()) { @@ -148,7 +178,7 @@ public void onResourceReady(File file, Transition transition) { } Observable.just(file) .compose(RxUtils.io_main()) - .map(f -> FileUtils.saveImg(f, Utils.getTypeFromImgUrl(getCurrentImage()))) + .map(f -> FileUtils.saveImg(f, Utils.getTypeFromImgUrl(currentImage))) .subscribe(new BaseConsumer() { @Override public void onConsume(String path) { @@ -166,19 +196,25 @@ public void onConsume(String path) { @Override public boolean onMenuItemClick(MenuItem item) { + String currentImage = getCurrentImage(); + if (currentImage == null) { + Voast.show("图片不存在"); + return false; + } + switch (item.getItemId()) { case R.id.action_open_in_browser: - Utils.openInBrowser(getCurrentImage(), this); + Utils.openInBrowser(currentImage, this); break; case R.id.action_save: //check write external permission then do save stuff saveImage(); break; case R.id.action_share: - glideRequest(getCurrentImage()).into(new SimpleTarget() { + glideRequest(currentImage).into(new SimpleTarget() { @Override public void onResourceReady(File file, Transition transition) { - Utils.shareImg(file, Utils.getTypeFromImgUrl(getCurrentImage()), GalleryActivity.this); + Utils.shareImg(file, Utils.getTypeFromImgUrl(currentImage), GalleryActivity.this); } }); break; diff --git a/app/src/main/java/me/ghui/v2er/module/gallery/GalleryAdapter.java b/app/src/main/java/me/ghui/v2er/module/gallery/GalleryAdapter.java index 54618d67..bd5a632a 100644 --- a/app/src/main/java/me/ghui/v2er/module/gallery/GalleryAdapter.java +++ b/app/src/main/java/me/ghui/v2er/module/gallery/GalleryAdapter.java @@ -49,6 +49,10 @@ public void destroyItem(ViewGroup container, int position, Object object) { } private ImagesInfo.Images.Image getItem(int postion) { + if (mImagesInfo == null || mImagesInfo.getImages() == null || + postion < 0 || postion >= mImagesInfo.getImages().size()) { + return null; + } return mImagesInfo.getImages().get(postion); } @@ -59,7 +63,13 @@ public Object instantiateItem(ViewGroup container, int position) { root.setOnImageClicked(mOnImageClickedListener); container.addView(root); // TODO: 2019/1/4 support svg - String url = getItem(position).getUrl(); + ImagesInfo.Images.Image image = getItem(position); + if (image == null || image.getUrl() == null) { + // This shouldn't happen now that we validate before opening gallery + // But keep it as a safety net + return root; + } + String url = image.getUrl(); if (!Utils.isSVG(url)) { GlideApp.with(mContext) .load(url)