make obtaining photo and video asynchronous

This commit is contained in:
tibbi 2016-11-19 22:05:44 +01:00
parent 828b4f4256
commit 93e37ec8e6
3 changed files with 111 additions and 81 deletions

View file

@ -3,12 +3,10 @@ package com.simplemobiletools.gallery.activities
import android.app.Activity import android.app.Activity
import android.app.WallpaperManager import android.app.WallpaperManager
import android.content.Intent import android.content.Intent
import android.database.Cursor
import android.graphics.Bitmap import android.graphics.Bitmap
import android.graphics.Color import android.graphics.Color
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.provider.MediaStore
import android.support.design.widget.Snackbar import android.support.design.widget.Snackbar
import android.util.Log import android.util.Log
import android.view.Menu import android.view.Menu
@ -22,6 +20,7 @@ import com.simplemobiletools.filepicker.extensions.*
import com.simplemobiletools.gallery.Constants import com.simplemobiletools.gallery.Constants
import com.simplemobiletools.gallery.R import com.simplemobiletools.gallery.R
import com.simplemobiletools.gallery.adapters.MediaAdapter import com.simplemobiletools.gallery.adapters.MediaAdapter
import com.simplemobiletools.gallery.asynctasks.GetMediaAsynctask
import com.simplemobiletools.gallery.dialogs.ChangeSortingDialog import com.simplemobiletools.gallery.dialogs.ChangeSortingDialog
import com.simplemobiletools.gallery.extensions.getHumanizedFilename import com.simplemobiletools.gallery.extensions.getHumanizedFilename
import com.simplemobiletools.gallery.models.Medium import com.simplemobiletools.gallery.models.Medium
@ -29,7 +28,6 @@ import kotlinx.android.synthetic.main.activity_media.*
import java.io.File import java.io.File
import java.io.IOException import java.io.IOException
import java.util.* import java.util.*
import java.util.regex.Pattern
class MediaActivity : SimpleActivity(), View.OnTouchListener, MediaAdapter.MediaOperationsListener { class MediaActivity : SimpleActivity(), View.OnTouchListener, MediaAdapter.MediaOperationsListener {
companion object { companion object {
@ -45,6 +43,7 @@ class MediaActivity : SimpleActivity(), View.OnTouchListener, MediaAdapter.Media
private var mIsGetImageIntent = false private var mIsGetImageIntent = false
private var mIsGetVideoIntent = false private var mIsGetVideoIntent = false
private var mIsGetAnyIntent = false private var mIsGetAnyIntent = false
private var mIsGettingMedia = false
} }
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
@ -56,7 +55,7 @@ class MediaActivity : SimpleActivity(), View.OnTouchListener, MediaAdapter.Media
mIsGetAnyIntent = getBooleanExtra(Constants.GET_ANY_INTENT, false) mIsGetAnyIntent = getBooleanExtra(Constants.GET_ANY_INTENT, false)
} }
media_holder.setOnRefreshListener({ refreshDir() }) media_holder.setOnRefreshListener({ getMedia() })
mPath = intent.getStringExtra(Constants.DIRECTORY) mPath = intent.getStringExtra(Constants.DIRECTORY)
mToBeDeleted = ArrayList<String>() mToBeDeleted = ArrayList<String>()
mMedia = ArrayList<Medium>() mMedia = ArrayList<Medium>()
@ -74,19 +73,15 @@ class MediaActivity : SimpleActivity(), View.OnTouchListener, MediaAdapter.Media
private fun tryloadGallery() { private fun tryloadGallery() {
if (hasStoragePermission()) { if (hasStoragePermission()) {
initializeGallery() val dirName = getHumanizedFilename(mPath)
title = dirName
getMedia()
} else { } else {
finish() finish()
} }
} }
private fun initializeGallery() { private fun initializeGallery() {
val newMedia = getMedia()
if (newMedia.toString() == mMedia.toString()) {
return
}
mMedia = newMedia
if (isDirEmpty()) if (isDirEmpty())
return return
@ -97,9 +92,6 @@ class MediaActivity : SimpleActivity(), View.OnTouchListener, MediaAdapter.Media
media_grid.adapter = adapter media_grid.adapter = adapter
media_grid.setOnTouchListener(this) media_grid.setOnTouchListener(this)
mIsSnackbarShown = false mIsSnackbarShown = false
val dirName = getHumanizedFilename(mPath)
title = dirName
} }
override fun onCreateOptionsMenu(menu: Menu): Boolean { override fun onCreateOptionsMenu(menu: Menu): Boolean {
@ -141,7 +133,7 @@ class MediaActivity : SimpleActivity(), View.OnTouchListener, MediaAdapter.Media
private fun showSortingDialog() { private fun showSortingDialog() {
ChangeSortingDialog(this, false, object : ChangeSortingDialog.OnChangeSortingListener { ChangeSortingDialog(this, false, object : ChangeSortingDialog.OnChangeSortingListener {
override fun sortingChanged() { override fun sortingChanged() {
initializeGallery() getMedia()
} }
}) })
} }
@ -167,55 +159,23 @@ class MediaActivity : SimpleActivity(), View.OnTouchListener, MediaAdapter.Media
} }
} }
private fun getMedia(): ArrayList<Medium> { private fun getMedia() {
val media = ArrayList<Medium>() if (mIsGettingMedia)
val invalidFiles = ArrayList<File>() return
for (i in 0..1) {
if (mIsGetVideoIntent && i == 0)
continue
var uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI mIsGettingMedia = true
if (i == 1) { GetMediaAsynctask(applicationContext, mPath, mIsGetVideoIntent, mIsGetImageIntent, mToBeDeleted, object : GetMediaAsynctask.GetMediaListener {
if (mIsGetImageIntent) override fun gotMedia(media: ArrayList<Medium>) {
continue mIsGettingMedia = false
media_holder.isRefreshing = false
uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI if (media.toString() == mMedia.toString()) {
} return
val where = "${MediaStore.Images.Media.DATA} LIKE ? "
val args = arrayOf("$mPath%")
val columns = arrayOf(MediaStore.Images.Media.DATA, MediaStore.Images.Media.DATE_MODIFIED)
val pattern = "${Pattern.quote(mPath)}/[^/]*"
var cursor: Cursor? = null
try {
cursor = contentResolver.query(uri, columns, where, args, null)
if (cursor != null && cursor.moveToFirst()) {
val pathIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATA)
do {
val curPath = cursor.getString(pathIndex) ?: continue
if (curPath.matches(pattern.toRegex()) && !mToBeDeleted.contains(curPath.toLowerCase())) {
val file = File(curPath)
if (file.exists()) {
val dateIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATE_MODIFIED)
val timestamp = cursor.getLong(dateIndex)
media.add(Medium(file.name, curPath, i == 1, timestamp, file.length()))
} else {
invalidFiles.add(file)
}
}
} while (cursor.moveToNext())
}
} finally {
cursor?.close()
}
} }
Medium.sorting = mConfig.sorting mMedia = media
media.sort() initializeGallery()
scanFiles(invalidFiles) {} }
return media }).execute()
} }
private fun isDirEmpty(): Boolean { private fun isDirEmpty(): Boolean {
@ -239,7 +199,7 @@ class MediaActivity : SimpleActivity(), View.OnTouchListener, MediaAdapter.Media
} }
private fun notifyDeletion(cnt: Int) { private fun notifyDeletion(cnt: Int) {
mMedia = getMedia() getMedia()
if (mMedia.isEmpty()) { if (mMedia.isEmpty()) {
deleteFiles() deleteFiles()
@ -299,14 +259,12 @@ class MediaActivity : SimpleActivity(), View.OnTouchListener, MediaAdapter.Media
mSnackbar!!.dismiss() mSnackbar!!.dismiss()
mIsSnackbarShown = false mIsSnackbarShown = false
mToBeDeleted.clear() mToBeDeleted.clear()
mMedia = getMedia()
updateMediaView() updateMediaView()
} }
private fun updateMediaView() { private fun updateMediaView() {
if (!isDirEmpty()) { if (!isDirEmpty()) {
(media_grid.adapter as MediaAdapter).updateMedia(mMedia) getMedia()
initializeGallery()
} }
} }
@ -359,15 +317,6 @@ class MediaActivity : SimpleActivity(), View.OnTouchListener, MediaAdapter.Media
} }
override fun refreshItems() { override fun refreshItems() {
refreshDir() getMedia()
}
private fun refreshDir() {
val dir = File(mPath)
if (dir.isDirectory) {
scanPath(mPath) {}
}
initializeGallery()
media_holder.isRefreshing = false
} }
} }

View file

@ -27,7 +27,7 @@ import kotlinx.android.synthetic.main.photo_video_tmb.view.*
import java.io.File import java.io.File
import java.util.* import java.util.*
class MediaAdapter(val activity: SimpleActivity, var media: MutableList<Medium>, val listener: MediaOperationsListener?, val itemClick: (Medium) -> Unit) : class MediaAdapter(val activity: SimpleActivity, val media: MutableList<Medium>, val listener: MediaOperationsListener?, val itemClick: (Medium) -> Unit) :
RecyclerView.Adapter<MediaAdapter.ViewHolder>() { RecyclerView.Adapter<MediaAdapter.ViewHolder>() {
val multiSelector = MultiSelector() val multiSelector = MultiSelector()
val views = ArrayList<View>() val views = ArrayList<View>()
@ -162,11 +162,6 @@ class MediaAdapter(val activity: SimpleActivity, var media: MutableList<Medium>,
notifyDataSetChanged() notifyDataSetChanged()
} }
fun updateMedia(media: MutableList<Medium>) {
this.media = media
notifyDataSetChanged()
}
override fun getItemCount() = media.size override fun getItemCount() = media.size
class ViewHolder(view: View, val itemClick: (Medium) -> (Unit)) : SwappingHolder(view, MultiSelector()) { class ViewHolder(view: View, val itemClick: (Medium) -> (Unit)) : SwappingHolder(view, MultiSelector()) {

View file

@ -0,0 +1,86 @@
package com.simplemobiletools.gallery.asynctasks
import android.content.Context
import android.database.Cursor
import android.os.AsyncTask
import android.provider.MediaStore
import com.simplemobiletools.filepicker.extensions.scanFiles
import com.simplemobiletools.gallery.Config
import com.simplemobiletools.gallery.models.Medium
import java.io.File
import java.lang.ref.WeakReference
import java.util.*
import java.util.regex.Pattern
class GetMediaAsynctask(val context: Context, val mPath: String, val isPickVideo: Boolean, val isPickImage: Boolean,
val mToBeDeleted: List<String>, val listener: GetMediaListener) : AsyncTask<Void, Void, ArrayList<Medium>>() {
lateinit var mConfig: Config
lateinit var mListener: WeakReference<GetMediaListener>
override fun onPreExecute() {
super.onPreExecute()
mConfig = Config.newInstance(context)
mListener = WeakReference(listener)
}
override fun doInBackground(vararg params: Void): ArrayList<Medium> {
val media = ArrayList<Medium>()
val invalidFiles = ArrayList<File>()
for (i in 0..1) {
if (isPickVideo && i == 0)
continue
var uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
if (i == 1) {
if (isPickImage)
continue
uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI
}
val where = "${MediaStore.Images.Media.DATA} LIKE ?"
val args = arrayOf("$mPath%")
val columns = arrayOf(MediaStore.Images.Media.DATA, MediaStore.Images.Media.DATE_MODIFIED)
val pattern = "${Pattern.quote(mPath)}/[^/]*"
var cursor: Cursor? = null
try {
cursor = context.contentResolver.query(uri, columns, where, args, null)
if (cursor != null && cursor.moveToFirst()) {
val pathIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATA)
do {
val curPath = cursor.getString(pathIndex) ?: continue
if (curPath.matches(pattern.toRegex()) && !mToBeDeleted.contains(curPath.toLowerCase())) {
val file = File(curPath)
if (file.exists()) {
val dateIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATE_MODIFIED)
val timestamp = cursor.getLong(dateIndex)
media.add(Medium(file.name, curPath, i == 1, timestamp, file.length()))
} else {
invalidFiles.add(file)
}
}
} while (cursor.moveToNext())
}
} finally {
cursor?.close()
}
}
Medium.sorting = mConfig.sorting
media.sort()
context.scanFiles(invalidFiles) {}
return media
}
override fun onPostExecute(media: ArrayList<Medium>) {
super.onPostExecute(media)
val listener = mListener.get()
listener?.gotMedia(media)
}
interface GetMediaListener {
fun gotMedia(media: ArrayList<Medium>)
}
}