diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
new file mode 100644
index 00000000..7643783a
--- /dev/null
+++ b/.idea/codeStyles/Project.xml
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ xmlns:android
+
+ ^$
+
+
+
+
+
+
+
+
+ xmlns:.*
+
+ ^$
+
+
+ BY_NAME
+
+
+
+
+
+
+ .*:id
+
+ http://schemas.android.com/apk/res/android
+
+
+
+
+
+
+
+
+ .*:name
+
+ http://schemas.android.com/apk/res/android
+
+
+
+
+
+
+
+
+ name
+
+ ^$
+
+
+
+
+
+
+
+
+ style
+
+ ^$
+
+
+
+
+
+
+
+
+ .*
+
+ ^$
+
+
+ BY_NAME
+
+
+
+
+
+
+ .*
+
+ http://schemas.android.com/apk/res/android
+
+
+ ANDROID_ATTRIBUTE_ORDER
+
+
+
+
+
+
+ .*
+
+ .*
+
+
+ BY_NAME
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 00000000..79ee123c
--- /dev/null
+++ b/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/gallery/memories/MainActivity.kt b/app/src/main/java/gallery/memories/MainActivity.kt
index 105ed09f..19fc569c 100644
--- a/app/src/main/java/gallery/memories/MainActivity.kt
+++ b/app/src/main/java/gallery/memories/MainActivity.kt
@@ -26,7 +26,7 @@ class MainActivity : AppCompatActivity() {
}
@SuppressLint("SetJavaScriptEnabled")
- protected fun initializeWebView() {
+ private fun initializeWebView() {
binding.webview.webViewClient = object : WebViewClient() {
override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean {
view.loadUrl(request.url.toString())
diff --git a/app/src/main/java/gallery/memories/NativeX.kt b/app/src/main/java/gallery/memories/NativeX.kt
index ef3395bd..91ce7d70 100644
--- a/app/src/main/java/gallery/memories/NativeX.kt
+++ b/app/src/main/java/gallery/memories/NativeX.kt
@@ -48,14 +48,19 @@ class NativeX(private val mActivity: AppCompatActivity) {
}
fun handleRequest(request: WebResourceRequest): WebResourceResponse {
- val path = request.url.path
- val response: WebResourceResponse = try {
- if (request.method == "GET") {
- routerGet(path)
- } else if (request.method == "OPTIONS") {
- WebResourceResponse("text/plain", "UTF-8", ByteArrayInputStream("".toByteArray()))
- } else {
- throw Exception("Method Not Allowed")
+ val path = request.url.path ?: return makeErrorResponse()
+
+ val response = try {
+ when (request.method) {
+ "GET" -> {
+ routerGet(path)
+ }
+ "OPTIONS" -> {
+ WebResourceResponse("text/plain", "UTF-8", ByteArrayInputStream("".toByteArray()))
+ }
+ else -> {
+ throw Exception("Method Not Allowed")
+ }
}
} catch (e: Exception) {
Log.e(TAG, "handleRequest: ", e)
@@ -89,12 +94,13 @@ class NativeX(private val mActivity: AppCompatActivity) {
@JavascriptInterface
fun downloadFromUrl(url: String?, filename: String?) {
- mDlService.queue(url!!, filename!!)
+ if (url == null || filename == null) return;
+ mDlService.queue(url, filename)
}
@Throws(Exception::class)
- private fun routerGet(path: String?): WebResourceResponse {
- val parts = path!!.split("/").toTypedArray()
+ private fun routerGet(path: String): WebResourceResponse {
+ val parts = path.split("/").toTypedArray()
if (path.matches(API.IMAGE_PREVIEW)) {
return makeResponse(mImageService.getPreview(parts[3].toLong()), "image/jpeg")
} else if (path.matches(API.IMAGE_FULL)) {
diff --git a/app/src/main/java/gallery/memories/mapper/SystemImage.kt b/app/src/main/java/gallery/memories/mapper/SystemImage.kt
new file mode 100644
index 00000000..81e28096
--- /dev/null
+++ b/app/src/main/java/gallery/memories/mapper/SystemImage.kt
@@ -0,0 +1,76 @@
+package gallery.memories.mapper
+
+import android.content.ContentUris
+import android.content.Context
+import android.net.Uri
+import android.provider.MediaStore
+
+class SystemImage {
+ var fileId = 0L;
+ var baseName = ""
+ var mimeType = ""
+ var dateTaken = 0L
+ var height = 0L
+ var width = 0L
+ var size = 0L
+ var dataPath = ""
+ var isVideo = false
+
+ private var mCollection: Uri = IMAGE_URI
+
+ val uri: Uri
+ get() {
+ return ContentUris.withAppendedId(mCollection, fileId)
+ }
+
+ companion object {
+ val IMAGE_URI = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
+ val VIDEO_URI = MediaStore.Video.Media.EXTERNAL_CONTENT_URI
+
+ fun getByIds(ctx: Context, ids: List): List {
+ val images = getByIdsAndCollection(ctx, IMAGE_URI, ids)
+ if (images.size == ids.size) return images
+ return images + getByIdsAndCollection(ctx, VIDEO_URI, ids)
+ }
+
+ fun getByIdsAndCollection(ctx: Context, collection: Uri, ids: List): List {
+ val selection = MediaStore.Images.Media._ID + " IN (" + ids.joinToString(",") + ")"
+
+ val list = mutableListOf()
+
+ ctx.contentResolver.query(
+ collection,
+ arrayOf(
+ MediaStore.Images.Media._ID,
+ MediaStore.Images.Media.DISPLAY_NAME,
+ MediaStore.Images.Media.MIME_TYPE,
+ MediaStore.Images.Media.HEIGHT,
+ MediaStore.Images.Media.WIDTH,
+ MediaStore.Images.Media.SIZE,
+ MediaStore.Images.Media.DATE_TAKEN,
+ MediaStore.Images.Media.DATA
+ ),
+ selection,
+ null,
+ null
+ ).use { cursor ->
+ while (cursor!!.moveToNext()) {
+ val image = SystemImage()
+ image.fileId = cursor.getLong(0)
+ image.baseName = cursor.getString(1)
+ image.mimeType = cursor.getString(2)
+ image.height = cursor.getLong(3)
+ image.width = cursor.getLong(4)
+ image.size = cursor.getLong(5)
+ image.dateTaken = cursor.getLong(6)
+ image.dataPath = cursor.getString(7)
+ image.isVideo = collection == VIDEO_URI
+ image.mCollection = collection
+ list.add(image)
+ }
+ }
+
+ return list
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/gallery/memories/service/TimelineQuery.kt b/app/src/main/java/gallery/memories/service/TimelineQuery.kt
index 3ec229dd..e9137f4d 100644
--- a/app/src/main/java/gallery/memories/service/TimelineQuery.kt
+++ b/app/src/main/java/gallery/memories/service/TimelineQuery.kt
@@ -2,11 +2,9 @@ package gallery.memories.service
import android.annotation.SuppressLint
import android.app.Activity
-import android.content.ContentUris
import android.database.sqlite.SQLiteDatabase
import android.icu.text.SimpleDateFormat
import android.icu.util.TimeZone
-import android.net.Uri
import android.os.Build
import android.provider.MediaStore
import android.text.TextUtils
@@ -18,6 +16,7 @@ import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.collection.ArraySet
import androidx.exifinterface.media.ExifInterface
+import gallery.memories.mapper.SystemImage
import org.json.JSONArray
import org.json.JSONException
import org.json.JSONObject
@@ -165,68 +164,36 @@ class TimelineQuery(private val mCtx: AppCompatActivity) {
@Throws(Exception::class)
fun getImageInfo(id: Long): JSONObject {
- val sql = "SELECT local_id, date_taken, dayid FROM images WHERE local_id = ?"
+ val sql = "SELECT dayid, date_taken FROM images WHERE local_id = ?"
mDb.rawQuery(sql, arrayOf(id.toString())).use { cursor ->
if (!cursor.moveToNext()) {
throw Exception("Image not found")
}
- val localId = cursor.getLong(0)
- val dateTaken = cursor.getLong(1)
- val dayId = cursor.getLong(2)
-
- return getImageInfoForCollection(
- MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
- localId, dateTaken, dayId)
- ?: return getImageInfoForCollection(
- MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
- localId, dateTaken, dayId)
- ?: throw Exception("File not found in any collection")
- }
- }
-
- private fun getImageInfoForCollection(
- collection: Uri,
- localId: Long,
- dateTaken: Long,
- dayId: Long
- ): JSONObject? {
- val selection = MediaStore.Images.Media._ID + " = " + localId
- mCtx.contentResolver.query(
- collection,
- arrayOf(
- MediaStore.Images.Media._ID,
- MediaStore.Images.Media.DISPLAY_NAME,
- MediaStore.Images.Media.MIME_TYPE,
- MediaStore.Images.Media.HEIGHT,
- MediaStore.Images.Media.WIDTH,
- MediaStore.Images.Media.SIZE,
- MediaStore.Images.Media.DATA
- ),
- selection,
- null,
- null
- ).use { cursor ->
- if (!cursor!!.moveToNext()) {
- throw Exception("Image not found")
+ // Get image from system table
+ val imageList = SystemImage.getByIds(mCtx, arrayListOf(id))
+ if (imageList.isEmpty()) {
+ throw Exception("File not found in any collection")
}
- // Create basic info
+ // Add EXIF to json object
+ val image = imageList[0];
+ val dayId = cursor.getLong(0)
+ val dateTaken = cursor.getLong(1)
+
val obj = JSONObject()
- .put(Fields.Photo.FILEID, cursor.getLong(0))
- .put(Fields.Photo.BASENAME, cursor.getString(1))
- .put(Fields.Photo.MIMETYPE, cursor.getString(2))
+ .put(Fields.Photo.FILEID, image.fileId)
+ .put(Fields.Photo.BASENAME, image.baseName)
+ .put(Fields.Photo.MIMETYPE, image.mimeType)
.put(Fields.Photo.DAYID, dayId)
.put(Fields.Photo.DATETAKEN, dateTaken)
- .put(Fields.Photo.HEIGHT, cursor.getLong(3))
- .put(Fields.Photo.WIDTH, cursor.getLong(4))
- .put(Fields.Photo.SIZE, cursor.getLong(5))
+ .put(Fields.Photo.HEIGHT, image.height)
+ .put(Fields.Photo.WIDTH, image.width)
+ .put(Fields.Photo.SIZE, image.size)
.put(Fields.Photo.PERMISSIONS, Fields.Perm.DELETE)
- val uri = cursor.getString(6)
- // Get EXIF data
try {
- val exif = ExifInterface(uri)
+ val exif = ExifInterface(image.dataPath)
obj.put(Fields.Photo.EXIF, JSONObject()
.put("Aperture", exif.getAttribute(ExifInterface.TAG_APERTURE_VALUE))
.put("FocalLength", exif.getAttribute(ExifInterface.TAG_FOCAL_LENGTH))
@@ -245,7 +212,7 @@ class TimelineQuery(private val mCtx: AppCompatActivity) {
.put("Description", exif.getAttribute(ExifInterface.TAG_IMAGE_DESCRIPTION))
)
} catch (e: IOException) {
- Log.e(TAG, "Error reading EXIF data for $uri")
+ Log.e(TAG, "Error reading EXIF data for $id")
}
return obj
@@ -263,9 +230,7 @@ class TimelineQuery(private val mCtx: AppCompatActivity) {
return try {
// List of URIs
- val uris = ids.map {
- ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, it)
- }
+ val uris = SystemImage.getByIds(mCtx, ids).map { it.uri }
// Delete file with media store
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
@@ -301,7 +266,7 @@ class TimelineQuery(private val mCtx: AppCompatActivity) {
}
}
- protected fun fullSyncDb() {
+ private fun fullSyncDb() {
// Flag all images for removal
mDb.execSQL("UPDATE images SET flag = 1")
mCtx.contentResolver.query(
@@ -381,7 +346,7 @@ class TimelineQuery(private val mCtx: AppCompatActivity) {
// Get EXIF date using ExifInterface if image
if (!isVideo) {
try {
- val exif = ExifInterface(uri!!)
+ val exif = ExifInterface(uri)
val exifDate = exif.getAttribute(ExifInterface.TAG_DATETIME)
?: throw IOException()
val sdf = SimpleDateFormat("yyyy:MM:dd HH:mm:ss")