diff --git a/app/build.gradle b/app/build.gradle
index 65597609..762094e5 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -2,13 +2,13 @@ apply plugin: 'com.android.application'
apply plugin: 'org.ajoberstar.grgit'
android {
- compileSdk 34
+ compileSdk 35
namespace 'ai.elimu.content_provider'
defaultConfig {
applicationId "ai.elimu.content_provider"
minSdkVersion 24
- targetSdkVersion 34
+ targetSdkVersion 35
versionCode 1002029
versionName "1.2.29-SNAPSHOT"
setProperty("archivesBaseName", "${applicationId}-${versionCode}")
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 3587b8ea..552d6413 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -52,7 +52,12 @@
android:name=".provider.ImageContentProvider"
android:authorities="${applicationId}.provider.image_provider"
android:enabled="true"
- android:exported="true" />
+ android:exported="true"
+ android:grantUriPermissions="true">
+
+
segments = uri.getPathSegments();
+ if (segments.size() < 2) {
+ throw new FileNotFoundException("Invalid URI: " + uri);
+ }
+ String fileId = segments.get(1);
+
+ RoomDb roomDb = RoomDb.getDatabase(getContext());
+ ImageDao imageDao = roomDb.imageDao();
+
+ long imageId;
+ try {
+ imageId = Long.parseLong(fileId);
+ } catch (NumberFormatException e) {
+ Log.e(TAG, "Failed to parse image ID: " + fileId, e);
+ throw new FileNotFoundException("Invalid image ID format: " + fileId);
+ }
+
+ Image image = imageDao.load(imageId);
+
+ if (image == null) {
+ throw new FileNotFoundException("File not found with id: " + imageId);
+ }
+
+ File imageFile = FileHelper.getImageFile(image, getContext());
+ if (imageFile == null) {
+ throw new FileNotFoundException("imageFile not found with id: " + imageId);
+ }
+ if (!imageFile.exists()) {
+ Log.e(TAG, "imageFile doesn't exist: " + imageFile.getAbsolutePath());
+ throw new FileNotFoundException("File not found: " + imageFile.getAbsolutePath());
+ }
+ return ParcelFileDescriptor.open(imageFile, ParcelFileDescriptor.MODE_READ_ONLY);
+ }
+
}
diff --git a/app/src/main/java/ai/elimu/content_provider/util/FileHelper.java b/app/src/main/java/ai/elimu/content_provider/util/FileHelper.java
index 54122675..369b7de4 100644
--- a/app/src/main/java/ai/elimu/content_provider/util/FileHelper.java
+++ b/app/src/main/java/ai/elimu/content_provider/util/FileHelper.java
@@ -3,8 +3,11 @@
import android.content.Context;
import android.os.Environment;
+import androidx.annotation.RestrictTo;
+
import java.io.File;
+import ai.elimu.content_provider.room.entity.Image;
import ai.elimu.model.v2.gson.content.AudioGson;
import ai.elimu.model.v2.gson.content.ImageGson;
import ai.elimu.model.v2.gson.content.VideoGson;
@@ -19,8 +22,20 @@ public static File getImageFile(ImageGson imageGson, Context context) {
return null;
}
File imagesDirectory = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
- File file = new File(imagesDirectory, imageGson.getId() + "_r" + imageGson.getRevisionNumber() + "." + imageGson.getImageFormat().toString().toLowerCase());
- return file;
+ return new File(imagesDirectory, imageGson.getId()
+ + "_r" + imageGson.getRevisionNumber() + "."
+ + imageGson.getImageFormat().toString().toLowerCase());
+ }
+
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+ public static File getImageFile(Image imageGson, Context context) {
+ if ((imageGson.getId() == null) || (imageGson.getRevisionNumber() == null)) {
+ return null;
+ }
+ File imagesDirectory = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
+ return new File(imagesDirectory, imageGson.getId()
+ + "_r" + imageGson.getRevisionNumber() + "."
+ + imageGson.getImageFormat().toString().toLowerCase());
}
public static File getAudioFile(AudioGson audioGson, Context context) {
diff --git a/app/src/main/res/xml/image_file_path.xml b/app/src/main/res/xml/image_file_path.xml
new file mode 100644
index 00000000..f734c0c0
--- /dev/null
+++ b/app/src/main/res/xml/image_file_path.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file