fix #1293, create a JobService for storing new media files in db
This commit is contained in:
parent
2cc93282ff
commit
15f6d18f46
4 changed files with 121 additions and 1 deletions
|
@ -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"
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue