diff --git a/app/src/main/cpp/CMakeLists.txt b/app/src/main/cpp/CMakeLists.txt index 4f24abfd8..84963e609 100644 --- a/app/src/main/cpp/CMakeLists.txt +++ b/app/src/main/cpp/CMakeLists.txt @@ -45,6 +45,6 @@ SET(LIBARCHIVE_CUSTOM_LIBS "liblzma" "nettle") add_subdirectory(libarchive) # Build and link our app's native lib -add_library(${PROJECT_NAME} SHARED main.c archive.c image.c) +add_library(${PROJECT_NAME} SHARED main.c archive.c image.c fdutils.c) target_include_directories(${PROJECT_NAME} PUBLIC libarchive/libarchive) target_link_libraries(${PROJECT_NAME} archive_static log jnigraphics GLESv2 -Wl,--gc-sections) diff --git a/app/src/main/cpp/archive.c b/app/src/main/cpp/archive.c index 01fb10bff..f787851f9 100644 --- a/app/src/main/cpp/archive.c +++ b/app/src/main/cpp/archive.c @@ -252,7 +252,7 @@ typedef struct Memarea { } Memarea; JNIEXPORT jlong JNICALL -Java_com_hippo_UriArchiveAccessor_extracttoOutputStream(JNIEnv *env, jobject thiz, jint index) { +Java_com_hippo_UriArchiveAccessor_extractToAddr(JNIEnv *env, jobject thiz, jint index) { (void)env; /* UNUSED */ (void)thiz; /* UNUSED */ archive_ctx *ctx = NULL; @@ -337,3 +337,30 @@ Java_com_hippo_UriArchiveAccessor_providePassword(JNIEnv *env, jobject thiz, jst archive_release_ctx(ctx); return ret; } + +JNIEXPORT jstring JNICALL +Java_com_hippo_UriArchiveAccessor_getFilename(JNIEnv *env, jobject thiz, jint index) { + (void)env; /* UNUSED */ + (void)thiz; /* UNUSED */ + archive_ctx *ctx = NULL; + int ret; + ret = archive_get_ctx(&ctx, index); + if (ret) + return NULL; + jstring str = (*env)->NewStringUTF(env, archive_entry_pathname(ctx->entry)); + ctx->using = 0; + return str; +} + +JNIEXPORT void JNICALL +Java_com_hippo_UriArchiveAccessor_extractToFd(JNIEnv *env, jobject thiz,jint index, jint fd) { + (void)env; /* UNUSED */ + (void)thiz; /* UNUSED */ + archive_ctx *ctx = NULL; + int ret; + ret = archive_get_ctx(&ctx, index); + if (!ret) { + archive_read_data_into_fd(ctx->arc, fd); + ctx->using = 0; + } +} \ No newline at end of file diff --git a/app/src/main/cpp/fdutils.c b/app/src/main/cpp/fdutils.c new file mode 100644 index 000000000..d13b6b161 --- /dev/null +++ b/app/src/main/cpp/fdutils.c @@ -0,0 +1,16 @@ +#include + +JNIEXPORT jint JNICALL +Java_com_hippo_Native_getFd(JNIEnv *env, jclass clazz, jobject fileDescriptor) { + jint fd = -1; + jclass fdClass = (*env)->FindClass(env, "java/io/FileDescriptor"); + + if (fdClass != NULL) { + jfieldID fdClassDescriptorFieldID = (*env)->GetFieldID(env, fdClass, "descriptor", "I"); + if (fdClassDescriptorFieldID != NULL && fileDescriptor != NULL) { + fd = (*env)->GetIntField(env, fileDescriptor, fdClassDescriptorFieldID); + } + } + + return fd; +} \ No newline at end of file diff --git a/app/src/main/cpp/image.c b/app/src/main/cpp/image.c index 71a6aae72..8eda55267 100644 --- a/app/src/main/cpp/image.c +++ b/app/src/main/cpp/image.c @@ -263,32 +263,12 @@ void advance(IMAGE *image) { } } -static int jniGetFDFromFileDescriptor(JNIEnv *env, jobject fileDescriptor) { - jint fd = -1; - jclass fdClass = (*env)->FindClass(env, "java/io/FileDescriptor"); - - if (fdClass != NULL) { - jfieldID fdClassDescriptorFieldID = (*env)->GetFieldID(env, fdClass, "descriptor", "I"); - if (fdClassDescriptorFieldID != NULL && fileDescriptor != NULL) { - fd = (*env)->GetIntField(env, fileDescriptor, fdClassDescriptorFieldID); - } - } - - return fd; -} - JNIEXPORT jlong JNICALL -Java_com_hippo_image_Image_nativeDecodeFdInt(JNIEnv *env, jclass clazz, jint fd) { +Java_com_hippo_image_Image_nativeDecode(JNIEnv *env, jclass clazz, jint fd) { IMAGE *image = createFromFd(fd); return (jlong) image; } -JNIEXPORT jlong JNICALL -Java_com_hippo_image_Image_nativeDecode(JNIEnv *env, jclass clazz, jobject fd) { - return Java_com_hippo_image_Image_nativeDecodeFdInt(env, clazz, - jniGetFDFromFileDescriptor(env, fd)); -} - JNIEXPORT jlong JNICALL Java_com_hippo_image_Image_nativeCreate(JNIEnv *env, jclass clazz, jobject bitmap) { AndroidBitmapInfo info; diff --git a/app/src/main/java/com/hippo/Native.java b/app/src/main/java/com/hippo/Native.java index 06d02cb10..18fad5260 100644 --- a/app/src/main/java/com/hippo/Native.java +++ b/app/src/main/java/com/hippo/Native.java @@ -18,8 +18,12 @@ package com.hippo; +import java.io.FileDescriptor; + public class Native { public static void initialize() { System.loadLibrary("ehviewer"); } + + public static native int getFd(FileDescriptor fd); } diff --git a/app/src/main/java/com/hippo/UriArchiveAccessor.java b/app/src/main/java/com/hippo/UriArchiveAccessor.java index d913922e4..350291798 100644 --- a/app/src/main/java/com/hippo/UriArchiveAccessor.java +++ b/app/src/main/java/com/hippo/UriArchiveAccessor.java @@ -21,10 +21,6 @@ package com.hippo; import android.content.Context; import android.net.Uri; import android.os.ParcelFileDescriptor; -import android.system.Os; -import android.system.OsConstants; - -import java.io.FileDescriptor; public class UriArchiveAccessor { ParcelFileDescriptor pfd; @@ -43,7 +39,11 @@ public class UriArchiveAccessor { private native int openArchive(int fd, long size); - public native long extracttoOutputStream(int index); + public native long extractToAddr(int index); + + public native void extractToFd(int index, int fd); + + public native String getFilename(int index); public native boolean needPassword(); diff --git a/app/src/main/java/com/hippo/ehviewer/gallery/ArchiveGalleryProvider.java b/app/src/main/java/com/hippo/ehviewer/gallery/ArchiveGalleryProvider.java index 1b37a8522..659b793a5 100644 --- a/app/src/main/java/com/hippo/ehviewer/gallery/ArchiveGalleryProvider.java +++ b/app/src/main/java/com/hippo/ehviewer/gallery/ArchiveGalleryProvider.java @@ -24,15 +24,19 @@ import android.os.Process; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import com.hippo.Native; import com.hippo.UriArchiveAccessor; import com.hippo.ehviewer.GetText; import com.hippo.ehviewer.R; import com.hippo.ehviewer.Settings; import com.hippo.image.Image; import com.hippo.unifile.UniFile; +import com.hippo.yorozuya.FileUtils; import com.hippo.yorozuya.thread.PVLock; import com.hippo.yorozuya.thread.PriorityThread; +import java.io.FileOutputStream; +import java.io.IOException; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; @@ -143,28 +147,43 @@ public class ArchiveGalleryProvider extends GalleryProvider2 { @NonNull @Override public String getImageFilename(int index) { - // TODO - return Integer.toString(index); - } - - @Override - public boolean save(int index, @NonNull UniFile file) { - // TODO - return false; - } - - @Nullable - @Override - public UniFile save(int index, @NonNull UniFile dir, @NonNull String filename) { - // TODO - return null; + return FileUtils.getNameFromFilename(getImageFilenameWithExtension(index)); } @NonNull @Override public String getImageFilenameWithExtension(int index) { - // TODO - return Integer.toString(index); + return FileUtils.sanitizeFilename(archiveAccessor.getFilename(index)); + } + + @Override + public boolean save(int index, @NonNull UniFile file) { + int fd; + FileOutputStream stream; + try { + stream = (FileOutputStream)file.openOutputStream(); + fd = Native.getFd(stream.getFD()); + } catch (IOException e) { + e.printStackTrace(); + return false; + } + archiveAccessor.extractToFd(index, fd); + try { + stream.close(); + } catch (IOException e) { + e.printStackTrace(); + return false; + } + return true; + } + + @Nullable + @Override + public UniFile save(int index, @NonNull UniFile dir, @NonNull String filename) { + String extension = FileUtils.getExtensionFromFilename(getImageFilenameWithExtension(index)); + UniFile dst = dir.subFile(null != extension ? filename + "." + extension : filename); + save(index, dst); + return dst; } private class ArchiveHostTask implements Runnable { @@ -279,7 +298,7 @@ public class ArchiveGalleryProvider extends GalleryProvider2 { } } - long addr = archiveAccessor.extracttoOutputStream(index); + long addr = archiveAccessor.extractToAddr(index); synchronized (streams) { streams.put(index, addr); diff --git a/app/src/main/java/com/hippo/ehviewer/ui/GalleryActivity.java b/app/src/main/java/com/hippo/ehviewer/ui/GalleryActivity.java index aac8cea7a..d178586dc 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/GalleryActivity.java +++ b/app/src/main/java/com/hippo/ehviewer/ui/GalleryActivity.java @@ -858,7 +858,8 @@ public class GalleryActivity extends EhActivity implements SeekBar.OnSeekBarChan intent.setAction(Intent.ACTION_SEND); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); intent.putExtra(Intent.EXTRA_STREAM, uri); - intent.putExtra(Intent.EXTRA_TEXT, EhUrl.getGalleryDetailUrl(mGalleryInfo.gid, mGalleryInfo.token)); + if (mGalleryInfo != null) + intent.putExtra(Intent.EXTRA_TEXT, EhUrl.getGalleryDetailUrl(mGalleryInfo.gid, mGalleryInfo.token)); intent.setDataAndType(uri, mimeType); try { diff --git a/app/src/main/java/com/hippo/image/Image.java b/app/src/main/java/com/hippo/image/Image.java index b2e155ca1..8d2b4f534 100644 --- a/app/src/main/java/com/hippo/image/Image.java +++ b/app/src/main/java/com/hippo/image/Image.java @@ -20,6 +20,8 @@ import android.graphics.Bitmap; import androidx.annotation.Nullable; +import com.hippo.Native; + import java.io.FileDescriptor; import java.util.ArrayList; @@ -64,7 +66,7 @@ public final class Image { */ @Nullable public static Image decode(FileDescriptor fd, boolean partially) { - return newFromAddr(nativeDecode(fd)); + return newFromAddr(nativeDecode(Native.getFd(fd))); } /** @@ -72,7 +74,7 @@ public final class Image { */ @Nullable public static Image decode(Integer fd, boolean partially) { - return newFromAddr(nativeDecodeFdInt(fd)); + return newFromAddr(nativeDecode(fd)); } /** @@ -99,9 +101,7 @@ public final class Image { return imageList.size(); } - private static native long nativeDecode(FileDescriptor fd); - - private static native long nativeDecodeFdInt(int fd); + private static native long nativeDecode(int fd); private static native long nativeDecodeAddr(long addr);