save medias with location data if it's allowed
This commit is contained in:
parent
cc41804745
commit
e957ce607a
|
@ -63,7 +63,7 @@ android {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'com.github.fatihergin:Simple-Commons:49f496ea16'
|
implementation 'com.github.fatihergin:Simple-Commons:23b8cf8be1' // TODO: replace it with SimpleMobileTools after merging the Commons PR
|
||||||
implementation 'androidx.documentfile:documentfile:1.0.1'
|
implementation 'androidx.documentfile:documentfile:1.0.1'
|
||||||
implementation "androidx.exifinterface:exifinterface:1.3.5"
|
implementation "androidx.exifinterface:exifinterface:1.3.5"
|
||||||
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.5.1"
|
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.5.1"
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
package com.simplemobiletools.camera.helpers
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
|
import android.location.Location
|
||||||
|
import android.location.LocationListener
|
||||||
|
import android.location.LocationManager
|
||||||
|
import androidx.annotation.RequiresPermission
|
||||||
|
import com.simplemobiletools.camera.extensions.checkLocationPermission
|
||||||
|
import com.simplemobiletools.camera.extensions.config
|
||||||
|
import com.simplemobiletools.commons.activities.BaseSimpleActivity
|
||||||
|
import com.simplemobiletools.commons.helpers.PERMISSION_ACCESS_FINE_LOCATION
|
||||||
|
|
||||||
|
class SimpleLocationManager(private val activity: BaseSimpleActivity) {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val LOCATION_UPDATE_MIN_TIME_INTERVAL_MS = 5_000L
|
||||||
|
private const val LOCATION_UPDATE_MIN_DISTANCE_M = 10F
|
||||||
|
}
|
||||||
|
|
||||||
|
private val locationManager = activity.getSystemService(LocationManager::class.java)!!
|
||||||
|
private val locationListener = LocationListener { location ->
|
||||||
|
this@SimpleLocationManager.location = location
|
||||||
|
}
|
||||||
|
|
||||||
|
private var location: Location? = null
|
||||||
|
|
||||||
|
fun getLocation(): Location? {
|
||||||
|
if (location == null) {
|
||||||
|
location = getLastKnownLocation()
|
||||||
|
}
|
||||||
|
|
||||||
|
return location
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getLastKnownLocation(): Location? {
|
||||||
|
return if (activity.checkLocationPermission()) {
|
||||||
|
var accurateLocation: Location? = null
|
||||||
|
for (provider in locationManager.allProviders) {
|
||||||
|
val location = locationManager.getLastKnownLocation(provider) ?: continue
|
||||||
|
if (accurateLocation == null || location.accuracy < accurateLocation.accuracy) {
|
||||||
|
accurateLocation = location
|
||||||
|
}
|
||||||
|
}
|
||||||
|
accurateLocation
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun requestLocationUpdates() {
|
||||||
|
activity.apply {
|
||||||
|
if (checkLocationPermission()) {
|
||||||
|
registerLocationUpdateListener()
|
||||||
|
} else {
|
||||||
|
handlePermission(PERMISSION_ACCESS_FINE_LOCATION) { _ ->
|
||||||
|
if (checkLocationPermission()) {
|
||||||
|
registerLocationUpdateListener()
|
||||||
|
} else {
|
||||||
|
config.saveMediaLocation = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiresPermission(anyOf = [Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION])
|
||||||
|
private fun registerLocationUpdateListener() {
|
||||||
|
locationManager.allProviders.forEach { provider ->
|
||||||
|
locationManager.requestLocationUpdates(
|
||||||
|
provider,
|
||||||
|
LOCATION_UPDATE_MIN_TIME_INTERVAL_MS,
|
||||||
|
LOCATION_UPDATE_MIN_DISTANCE_M,
|
||||||
|
locationListener
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun dropLocationUpdates() {
|
||||||
|
locationManager.removeUpdates(locationListener)
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,12 +2,12 @@ package com.simplemobiletools.camera.implementations
|
||||||
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import androidx.camera.view.PreviewView
|
import androidx.camera.view.PreviewView
|
||||||
|
import com.simplemobiletools.camera.activities.MainActivity
|
||||||
import com.simplemobiletools.camera.helpers.CameraErrorHandler
|
import com.simplemobiletools.camera.helpers.CameraErrorHandler
|
||||||
import com.simplemobiletools.camera.helpers.MediaOutputHelper
|
import com.simplemobiletools.camera.helpers.MediaOutputHelper
|
||||||
import com.simplemobiletools.camera.helpers.MediaSoundHelper
|
import com.simplemobiletools.camera.helpers.MediaSoundHelper
|
||||||
import com.simplemobiletools.commons.activities.BaseSimpleActivity
|
|
||||||
|
|
||||||
class CameraXInitializer(private val activity: BaseSimpleActivity) {
|
class CameraXInitializer(private val activity: MainActivity) {
|
||||||
|
|
||||||
fun createCameraXPreview(
|
fun createCameraXPreview(
|
||||||
previewView: PreviewView,
|
previewView: PreviewView,
|
||||||
|
|
|
@ -10,8 +10,6 @@ import android.util.Rational
|
||||||
import android.util.Size
|
import android.util.Size
|
||||||
import android.view.*
|
import android.view.*
|
||||||
import android.view.GestureDetector.SimpleOnGestureListener
|
import android.view.GestureDetector.SimpleOnGestureListener
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
|
||||||
import androidx.camera.core.*
|
import androidx.camera.core.*
|
||||||
import androidx.camera.core.ImageCapture.*
|
import androidx.camera.core.ImageCapture.*
|
||||||
import androidx.camera.lifecycle.ProcessCameraProvider
|
import androidx.camera.lifecycle.ProcessCameraProvider
|
||||||
|
@ -34,11 +32,12 @@ import com.simplemobiletools.camera.models.CaptureMode
|
||||||
import com.simplemobiletools.camera.models.MediaOutput
|
import com.simplemobiletools.camera.models.MediaOutput
|
||||||
import com.simplemobiletools.camera.models.MySize
|
import com.simplemobiletools.camera.models.MySize
|
||||||
import com.simplemobiletools.camera.models.ResolutionOption
|
import com.simplemobiletools.camera.models.ResolutionOption
|
||||||
|
import com.simplemobiletools.commons.activities.BaseSimpleActivity
|
||||||
import com.simplemobiletools.commons.extensions.toast
|
import com.simplemobiletools.commons.extensions.toast
|
||||||
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
||||||
|
|
||||||
class CameraXPreview(
|
class CameraXPreview(
|
||||||
private val activity: AppCompatActivity,
|
private val activity: BaseSimpleActivity,
|
||||||
private val previewView: PreviewView,
|
private val previewView: PreviewView,
|
||||||
private val mediaSoundHelper: MediaSoundHelper,
|
private val mediaSoundHelper: MediaSoundHelper,
|
||||||
private val mediaOutputHelper: MediaOutputHelper,
|
private val mediaOutputHelper: MediaOutputHelper,
|
||||||
|
@ -122,6 +121,7 @@ class CameraXPreview(
|
||||||
private var isPhotoCapture = initInPhotoMode
|
private var isPhotoCapture = initInPhotoMode
|
||||||
private var lastRotation = 0
|
private var lastRotation = 0
|
||||||
private var lastCameraStartTime = 0L
|
private var lastCameraStartTime = 0L
|
||||||
|
private var simpleLocationManager: SimpleLocationManager? = null
|
||||||
|
|
||||||
init {
|
init {
|
||||||
bindToLifeCycle()
|
bindToLifeCycle()
|
||||||
|
@ -351,6 +351,21 @@ class CameraXPreview(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onResume(owner: LifecycleOwner) {
|
||||||
|
super.onResume(owner)
|
||||||
|
if (config.saveMediaLocation) {
|
||||||
|
if (simpleLocationManager == null) {
|
||||||
|
simpleLocationManager = SimpleLocationManager(activity)
|
||||||
|
}
|
||||||
|
simpleLocationManager?.requestLocationUpdates()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPause(owner: LifecycleOwner) {
|
||||||
|
super.onPause(owner)
|
||||||
|
simpleLocationManager?.dropLocationUpdates()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onStop(owner: LifecycleOwner) {
|
override fun onStop(owner: LifecycleOwner) {
|
||||||
orientationEventListener.disable()
|
orientationEventListener.disable()
|
||||||
}
|
}
|
||||||
|
@ -473,6 +488,9 @@ class CameraXPreview(
|
||||||
|
|
||||||
val metadata = Metadata().apply {
|
val metadata = Metadata().apply {
|
||||||
isReversedHorizontal = isFrontCameraInUse() && config.flipPhotos
|
isReversedHorizontal = isFrontCameraInUse() && config.flipPhotos
|
||||||
|
if (config.saveMediaLocation) {
|
||||||
|
location = simpleLocationManager?.getLocation()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val mediaOutput = mediaOutputHelper.getImageMediaOutput()
|
val mediaOutput = mediaOutputHelper.getImageMediaOutput()
|
||||||
|
@ -572,16 +590,26 @@ class CameraXPreview(
|
||||||
|
|
||||||
val recording = when (val mediaOutput = mediaOutputHelper.getVideoMediaOutput()) {
|
val recording = when (val mediaOutput = mediaOutputHelper.getVideoMediaOutput()) {
|
||||||
is MediaOutput.FileDescriptorMediaOutput -> {
|
is MediaOutput.FileDescriptorMediaOutput -> {
|
||||||
FileDescriptorOutputOptions.Builder(mediaOutput.fileDescriptor).build()
|
FileDescriptorOutputOptions.Builder(mediaOutput.fileDescriptor).apply {
|
||||||
.let { videoCapture!!.output.prepareRecording(activity, it) }
|
if (config.saveMediaLocation) {
|
||||||
|
setLocation(simpleLocationManager?.getLocation())
|
||||||
|
}
|
||||||
|
}.build().let { videoCapture!!.output.prepareRecording(activity, it) }
|
||||||
}
|
}
|
||||||
is MediaOutput.FileMediaOutput -> {
|
is MediaOutput.FileMediaOutput -> {
|
||||||
FileOutputOptions.Builder(mediaOutput.file).build()
|
FileOutputOptions.Builder(mediaOutput.file).apply {
|
||||||
.let { videoCapture!!.output.prepareRecording(activity, it) }
|
if (config.saveMediaLocation) {
|
||||||
|
setLocation(simpleLocationManager?.getLocation())
|
||||||
|
}
|
||||||
|
}.build().let { videoCapture!!.output.prepareRecording(activity, it) }
|
||||||
}
|
}
|
||||||
is MediaOutput.MediaStoreOutput -> {
|
is MediaOutput.MediaStoreOutput -> {
|
||||||
MediaStoreOutputOptions.Builder(contentResolver, mediaOutput.contentUri).setContentValues(mediaOutput.contentValues).build()
|
MediaStoreOutputOptions.Builder(contentResolver, mediaOutput.contentUri).apply {
|
||||||
.let { videoCapture!!.output.prepareRecording(activity, it) }
|
setContentValues(mediaOutput.contentValues)
|
||||||
|
if (config.saveMediaLocation) {
|
||||||
|
setLocation(simpleLocationManager?.getLocation())
|
||||||
|
}
|
||||||
|
}.build().let { videoCapture!!.output.prepareRecording(activity, it) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue