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"/>
|
android:resource="@xml/widget_info"/>
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
|
<service
|
||||||
|
android:name=".jobs.NewPhotoFetcher"
|
||||||
|
android:exported="true"
|
||||||
|
android:permission="android.permission.BIND_JOB_SERVICE"/>
|
||||||
|
|
||||||
<activity-alias
|
<activity-alias
|
||||||
android:name=".activities.SplashActivity.Red"
|
android:name=".activities.SplashActivity.Red"
|
||||||
android:enabled="false"
|
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.DirectoryDao
|
||||||
import com.simplemobiletools.gallery.pro.interfaces.DirectoryOperationsListener
|
import com.simplemobiletools.gallery.pro.interfaces.DirectoryOperationsListener
|
||||||
import com.simplemobiletools.gallery.pro.interfaces.MediumDao
|
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.AlbumCover
|
||||||
import com.simplemobiletools.gallery.pro.models.Directory
|
import com.simplemobiletools.gallery.pro.models.Directory
|
||||||
import com.simplemobiletools.gallery.pro.models.Medium
|
import com.simplemobiletools.gallery.pro.models.Medium
|
||||||
|
@ -99,6 +100,7 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
|
||||||
config.tempSkipDeleteConfirmation = false
|
config.tempSkipDeleteConfirmation = false
|
||||||
removeTempFolder()
|
removeTempFolder()
|
||||||
checkRecycleBinItems()
|
checkRecycleBinItems()
|
||||||
|
startNewPhotoFetcher()
|
||||||
}
|
}
|
||||||
|
|
||||||
mIsPickImageIntent = isPickImageIntent(intent)
|
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() {
|
private fun removeTempFolder() {
|
||||||
if (config.tempFolderPath.isNotEmpty()) {
|
if (config.tempFolderPath.isNotEmpty()) {
|
||||||
val newFolder = File(config.tempFolderPath)
|
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) {
|
fun Context.addPathToDB(path: String) {
|
||||||
Thread {
|
Thread {
|
||||||
|
if (!File(path).exists()) {
|
||||||
|
return@Thread
|
||||||
|
}
|
||||||
|
|
||||||
val type = when {
|
val type = when {
|
||||||
path.isVideoFast() -> TYPE_VIDEOS
|
path.isVideoFast() -> TYPE_VIDEOS
|
||||||
path.isGif() -> TYPE_GIFS
|
path.isGif() -> TYPE_GIFS
|
||||||
|
@ -709,8 +713,9 @@ fun Context.addPathToDB(path: String) {
|
||||||
else -> TYPE_IMAGES
|
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(),
|
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)
|
galleryDB.MediumDao().insert(medium)
|
||||||
}.start()
|
}.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