diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index dff3c06f6..aa2a48308 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -263,6 +263,11 @@
android:resource="@xml/widget_info"/>
+
+
TYPE_VIDEOS
path.isGif() -> TYPE_GIFS
@@ -709,8 +713,9 @@ fun Context.addPathToDB(path: String) {
else -> TYPE_IMAGES
}
+ val videoDuration = if (type == TYPE_VIDEOS) path.getVideoDuration() else 0
val medium = Medium(null, path.getFilenameFromPath(), path, path.getParentPath(), System.currentTimeMillis(), System.currentTimeMillis(),
- File(path).length(), type, 0, false, 0L)
+ File(path).length(), type, videoDuration, false, 0L)
galleryDB.MediumDao().insert(medium)
}.start()
}
diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/jobs/NewPhotoFetcher.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/jobs/NewPhotoFetcher.kt
new file mode 100644
index 000000000..8039ae280
--- /dev/null
+++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/jobs/NewPhotoFetcher.kt
@@ -0,0 +1,101 @@
+package com.simplemobiletools.gallery.pro.jobs
+
+import android.annotation.TargetApi
+import android.app.job.JobInfo
+import android.app.job.JobParameters
+import android.app.job.JobScheduler
+import android.app.job.JobService
+import android.content.ComponentName
+import android.content.Context
+import android.database.Cursor
+import android.net.Uri
+import android.os.Build
+import android.os.Handler
+import android.provider.MediaStore
+import com.simplemobiletools.commons.extensions.getStringValue
+import com.simplemobiletools.gallery.pro.extensions.addPathToDB
+
+// based on https://developer.android.com/reference/android/app/job/JobInfo.Builder.html#addTriggerContentUri(android.app.job.JobInfo.TriggerContentUri)
+@TargetApi(Build.VERSION_CODES.N)
+class NewPhotoFetcher : JobService() {
+ companion object {
+ const val PHOTO_VIDEO_CONTENT_JOB = 1
+ private val MEDIA_URI = Uri.parse("content://${MediaStore.AUTHORITY}/")
+ private val PHOTO_PATH_SEGMENTS = MediaStore.Images.Media.EXTERNAL_CONTENT_URI.pathSegments
+ private val VIDEO_PATH_SEGMENTS = MediaStore.Video.Media.EXTERNAL_CONTENT_URI.pathSegments
+ }
+
+ private val mHandler = Handler()
+ private val mWorker = Runnable {
+ scheduleJob(this@NewPhotoFetcher)
+ jobFinished(mRunningParams, false)
+ }
+
+ private var mRunningParams: JobParameters? = null
+
+ fun scheduleJob(context: Context) {
+ val componentName = ComponentName(context, NewPhotoFetcher::class.java)
+ val photoUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
+ val videoUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI
+ JobInfo.Builder(PHOTO_VIDEO_CONTENT_JOB, componentName).apply {
+ addTriggerContentUri(JobInfo.TriggerContentUri(photoUri, JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS))
+ addTriggerContentUri(JobInfo.TriggerContentUri(videoUri, JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS))
+ addTriggerContentUri(JobInfo.TriggerContentUri(MEDIA_URI, 0))
+ context.getSystemService(JobScheduler::class.java).schedule(build())
+ }
+ }
+
+ fun isScheduled(context: Context): Boolean {
+ val jobScheduler = context.getSystemService(JobScheduler::class.java)
+ val jobs = jobScheduler.allPendingJobs ?: return false
+ return jobs.any { it.id == PHOTO_VIDEO_CONTENT_JOB }
+ }
+
+ override fun onStartJob(params: JobParameters): Boolean {
+ mRunningParams = params
+
+ if (params.triggeredContentAuthorities != null && params.triggeredContentUris != null) {
+ val ids = arrayListOf()
+ for (uri in params.triggeredContentUris!!) {
+ val path = uri.pathSegments
+ if (path != null && (path.size == PHOTO_PATH_SEGMENTS.size + 1 || path.size == VIDEO_PATH_SEGMENTS.size + 1)) {
+ ids.add(path[path.size - 1])
+ }
+ }
+
+ if (ids.isNotEmpty()) {
+ val selection = StringBuilder()
+ for (id in ids) {
+ if (selection.isNotEmpty()) {
+ selection.append(" OR ")
+ }
+ selection.append("${MediaStore.Images.ImageColumns._ID} = '$id'")
+ }
+
+ var cursor: Cursor? = null
+ try {
+ val projection = arrayOf(MediaStore.Images.ImageColumns.DATA)
+ val uris = arrayListOf(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, MediaStore.Video.Media.EXTERNAL_CONTENT_URI)
+ uris.forEach {
+ cursor = contentResolver.query(it, projection, selection.toString(), null, null)
+ while (cursor!!.moveToNext()) {
+ val path = cursor!!.getStringValue(MediaStore.Images.ImageColumns.DATA)
+ addPathToDB(path)
+ }
+ }
+ } catch (ignored: Exception) {
+ } finally {
+ cursor?.close()
+ }
+ }
+ }
+
+ mHandler.post(mWorker)
+ return true
+ }
+
+ override fun onStopJob(params: JobParameters): Boolean {
+ mHandler.removeCallbacks(mWorker)
+ return false
+ }
+}