Register photo creation receiver for internal storage for auto upload
This commit is contained in:
parent
a42919911d
commit
7dca46864d
@ -7,12 +7,13 @@ import android.app.job.JobScheduler
|
|||||||
import android.app.job.JobService
|
import android.app.job.JobService
|
||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.database.Cursor
|
import android.database.MergeCursor
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.provider.MediaStore
|
import android.provider.MediaStore
|
||||||
import android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI
|
import android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI
|
||||||
|
import android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import org.cryptomator.domain.exception.FatalBackendException
|
import org.cryptomator.domain.exception.FatalBackendException
|
||||||
import org.cryptomator.presentation.R
|
import org.cryptomator.presentation.R
|
||||||
@ -21,72 +22,69 @@ import org.cryptomator.presentation.util.ResourceHelper
|
|||||||
import org.cryptomator.util.file.MimeTypeMap_Factory
|
import org.cryptomator.util.file.MimeTypeMap_Factory
|
||||||
import org.cryptomator.util.file.MimeTypes
|
import org.cryptomator.util.file.MimeTypes
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.lang.String.format
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
@RequiresApi(api = Build.VERSION_CODES.N)
|
@RequiresApi(api = Build.VERSION_CODES.N)
|
||||||
class PhotoContentJob : JobService() {
|
class PhotoContentJob : JobService() {
|
||||||
|
|
||||||
private val mHandler = Handler()
|
private val handler = Handler()
|
||||||
private val mWorker: Runnable = Runnable {
|
private val worker: Runnable = Runnable {
|
||||||
scheduleJob(applicationContext)
|
scheduleJob(applicationContext)
|
||||||
jobFinished(mRunningParams, false)
|
jobFinished(runningParams, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var mRunningParams: JobParameters
|
private lateinit var runningParams: JobParameters
|
||||||
|
|
||||||
override fun onStartJob(params: JobParameters): Boolean {
|
override fun onStartJob(params: JobParameters): Boolean {
|
||||||
Timber.tag("PhotoContentJob").i("Job started!")
|
Timber.tag("PhotoContentJob").i("Job started!")
|
||||||
|
|
||||||
val fileUtil = FileUtil(baseContext, MimeTypes(MimeTypeMap_Factory.newInstance()))
|
val fileUtil = FileUtil(baseContext, MimeTypes(MimeTypeMap_Factory.newInstance()))
|
||||||
|
|
||||||
mRunningParams = params
|
runningParams = params
|
||||||
if (params.triggeredContentAuthorities != null) {
|
|
||||||
|
params.triggeredContentAuthorities?.let {
|
||||||
if (params.triggeredContentUris != null) {
|
if (params.triggeredContentUris != null) {
|
||||||
val ids = getIds(params)
|
val ids = getIds(params)
|
||||||
if (ids != null && ids.size > 0) {
|
if (ids != null && ids.isNotEmpty()) {
|
||||||
val selection = buildSelection(ids)
|
val selection = buildSelection(ids)
|
||||||
var cursor: Cursor? = null
|
contentResolver.query(EXTERNAL_CONTENT_URI, PROJECTION, selection, null, null).use { externalCursor ->
|
||||||
try {
|
contentResolver.query(INTERNAL_CONTENT_URI, PROJECTION, selection, null, null).use { internalCursor ->
|
||||||
cursor = contentResolver.query(EXTERNAL_CONTENT_URI, PROJECTION, selection, null, null)
|
MergeCursor(arrayOf(externalCursor, internalCursor)).use { cursor ->
|
||||||
cursor?.let {
|
while (cursor.moveToNext()) {
|
||||||
while (cursor.moveToNext()) {
|
try {
|
||||||
val dir = cursor.getString(PROJECTION_DATA)
|
val dir = cursor.getString(PROJECTION_DATA)
|
||||||
try {
|
fileUtil.addImageToAutoUploads(dir)
|
||||||
fileUtil.addImageToAutoUploads(dir)
|
Timber.tag("PhotoContentJob").i("Added file to UploadList")
|
||||||
Timber.tag("PhotoContentJob").i("Added file to UploadList")
|
Timber.tag("PhotoContentJob").d(String.format("Added file to UploadList %s", dir))
|
||||||
Timber.tag("PhotoContentJob").d(format("Added file to UploadList %s", dir))
|
} catch (e: FatalBackendException) {
|
||||||
} catch (e: FatalBackendException) {
|
Timber.tag("PhotoContentJob").e(e, "Failed to add image to auto upload list")
|
||||||
Timber.tag("PhotoContentJob").e(e, "Failed to add image to auto upload list")
|
} catch (e: SecurityException) {
|
||||||
|
Timber.tag("PhotoContentJob").e(e, "No access to storage")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} ?: Timber.tag("PhotoContentJob").e("Error: no access to media!")
|
}
|
||||||
} catch (e: SecurityException) {
|
|
||||||
Timber.tag("PhotoContentJob").e("Error: no access to media!")
|
|
||||||
} finally {
|
|
||||||
cursor?.close()
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Timber.tag("PhotoContentJob").d("ids are null or 0: %s", ids)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Timber.tag("PhotoContentJob").w("Photos rescan needed!")
|
Timber.tag("PhotoContentJob").w("Photos rescan needed!")
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
} else {
|
} ?: Timber.tag("PhotoContentJob").w("No photos content")
|
||||||
Timber.tag("PhotoContentJob").w("No photos content")
|
|
||||||
}
|
|
||||||
|
|
||||||
mHandler.post(mWorker)
|
handler.post(worker)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getIds(params: JobParameters): ArrayList<String>? {
|
private fun getIds(params: JobParameters): Set<String>? {
|
||||||
return params.triggeredContentUris
|
return params.triggeredContentUris
|
||||||
?.map { it.pathSegments }
|
?.map { it.pathSegments }
|
||||||
?.filter { it != null && it.size == EXTERNAL_PATH_SEGMENTS.size + 1 }
|
?.filter { it != null && (it.size == EXTERNAL_CONTENT_URI.pathSegments.size + 1 || it.size == INTERNAL_CONTENT_URI.pathSegments.size + 1) }
|
||||||
?.mapTo(ArrayList()) { it[it.size - 1] }
|
?.mapTo(HashSet()) { it[it.size - 1] }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildSelection(ids: ArrayList<String>): String {
|
private fun buildSelection(ids: Set<String>): String {
|
||||||
val selection = StringBuilder()
|
val selection = StringBuilder()
|
||||||
ids.indices.forEach { i ->
|
ids.indices.forEach { i ->
|
||||||
if (selection.isNotEmpty()) {
|
if (selection.isNotEmpty()) {
|
||||||
@ -94,7 +92,7 @@ class PhotoContentJob : JobService() {
|
|||||||
}
|
}
|
||||||
selection.append(MediaStore.Images.ImageColumns._ID)
|
selection.append(MediaStore.Images.ImageColumns._ID)
|
||||||
selection.append("='")
|
selection.append("='")
|
||||||
selection.append(ids[i])
|
selection.append(ids.elementAt(i))
|
||||||
selection.append("'")
|
selection.append("'")
|
||||||
}
|
}
|
||||||
return selection.toString()
|
return selection.toString()
|
||||||
@ -102,7 +100,7 @@ class PhotoContentJob : JobService() {
|
|||||||
|
|
||||||
override fun onStopJob(params: JobParameters): Boolean {
|
override fun onStopJob(params: JobParameters): Boolean {
|
||||||
Timber.tag("PhotoContentJob").i("onStopJob called, must stop, reschedule later")
|
Timber.tag("PhotoContentJob").i("onStopJob called, must stop, reschedule later")
|
||||||
mHandler.removeCallbacks(mWorker)
|
handler.removeCallbacks(worker)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,7 +112,6 @@ class PhotoContentJob : JobService() {
|
|||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
private val MEDIA_URI = Uri.parse("content://" + MediaStore.AUTHORITY + "/")
|
private val MEDIA_URI = Uri.parse("content://" + MediaStore.AUTHORITY + "/")
|
||||||
internal val EXTERNAL_PATH_SEGMENTS = EXTERNAL_CONTENT_URI.pathSegments
|
|
||||||
internal val PROJECTION = arrayOf(MediaStore.Images.ImageColumns._ID, MediaStore.Images.ImageColumns.DATA)
|
internal val PROJECTION = arrayOf(MediaStore.Images.ImageColumns._ID, MediaStore.Images.ImageColumns.DATA)
|
||||||
|
|
||||||
internal const val PROJECTION_DATA = 1
|
internal const val PROJECTION_DATA = 1
|
||||||
@ -125,6 +122,7 @@ class PhotoContentJob : JobService() {
|
|||||||
init {
|
init {
|
||||||
val builder = JobInfo.Builder(PHOTOS_CONTENT_JOB, ComponentName(ResourceHelper.getString(R.string.app_id), PhotoContentJob::class.java.name))
|
val builder = JobInfo.Builder(PHOTOS_CONTENT_JOB, ComponentName(ResourceHelper.getString(R.string.app_id), PhotoContentJob::class.java.name))
|
||||||
builder.addTriggerContentUri(JobInfo.TriggerContentUri(EXTERNAL_CONTENT_URI, FLAG_NOTIFY_FOR_DESCENDANTS))
|
builder.addTriggerContentUri(JobInfo.TriggerContentUri(EXTERNAL_CONTENT_URI, FLAG_NOTIFY_FOR_DESCENDANTS))
|
||||||
|
builder.addTriggerContentUri(JobInfo.TriggerContentUri(INTERNAL_CONTENT_URI, FLAG_NOTIFY_FOR_DESCENDANTS))
|
||||||
builder.addTriggerContentUri(JobInfo.TriggerContentUri(MEDIA_URI, FLAG_NOTIFY_FOR_DESCENDANTS))
|
builder.addTriggerContentUri(JobInfo.TriggerContentUri(MEDIA_URI, FLAG_NOTIFY_FOR_DESCENDANTS))
|
||||||
jobInfo = builder.build()
|
jobInfo = builder.build()
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user