save medias with location data if it's allowed

This commit is contained in:
fatih ergin 2023-07-24 01:54:34 +03:00
parent cc41804745
commit e957ce607a
4 changed files with 121 additions and 12 deletions

View File

@ -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"

View File

@ -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)
}
}

View File

@ -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,

View File

@ -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) }
} }
} }