fix #1293, create a JobService for storing new media files in db

This commit is contained in:
tibbi 2019-03-09 20:07:15 +01:00
parent 2cc93282ff
commit 15f6d18f46
4 changed files with 121 additions and 1 deletions

View file

@ -263,6 +263,11 @@
android:resource="@xml/widget_info"/>
</receiver>
<service
android:name=".jobs.NewPhotoFetcher"
android:exported="true"
android:permission="android.permission.BIND_JOB_SERVICE"/>
<activity-alias
android:name=".activities.SplashActivity.Red"
android:enabled="false"

View file

@ -37,6 +37,7 @@ import com.simplemobiletools.gallery.pro.helpers.*
import com.simplemobiletools.gallery.pro.interfaces.DirectoryDao
import com.simplemobiletools.gallery.pro.interfaces.DirectoryOperationsListener
import com.simplemobiletools.gallery.pro.interfaces.MediumDao
import com.simplemobiletools.gallery.pro.jobs.NewPhotoFetcher
import com.simplemobiletools.gallery.pro.models.AlbumCover
import com.simplemobiletools.gallery.pro.models.Directory
import com.simplemobiletools.gallery.pro.models.Medium
@ -99,6 +100,7 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
config.tempSkipDeleteConfirmation = false
removeTempFolder()
checkRecycleBinItems()
startNewPhotoFetcher()
}
mIsPickImageIntent = isPickImageIntent(intent)
@ -365,6 +367,13 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
})
}
private fun startNewPhotoFetcher() {
val photoFetcher = NewPhotoFetcher()
if (isNougatPlus() && !photoFetcher.isScheduled(applicationContext)) {
photoFetcher.scheduleJob(applicationContext)
}
}
private fun removeTempFolder() {
if (config.tempFolderPath.isNotEmpty()) {
val newFolder = File(config.tempFolderPath)

View file

@ -701,6 +701,10 @@ fun Context.parseFileChannel(path: String, fc: FileChannel, level: Int, start: L
fun Context.addPathToDB(path: String) {
Thread {
if (!File(path).exists()) {
return@Thread
}
val type = when {
path.isVideoFast() -> 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()
}

View file

@ -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<String>()
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
}
}