Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<uses-feature
android:name="android.hardware.camera"
android:required="false" />

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.CAMERA" />

<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
Expand All @@ -13,7 +21,7 @@
android:theme="@style/Theme.OTUSLocationMapsHW"
tools:targetApi="31">
<!--
TODO: Before you run your application, you need a Google Maps API key.
Before you run your application, you need a Google Maps API key.

To get one, follow the directions here:

Expand All @@ -25,7 +33,7 @@
-->
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="YOUR_API_KEY" />
android:value="${MAPS_API_KEY}" />

<activity
android:name=".MapsActivity"
Expand Down
22 changes: 11 additions & 11 deletions app/src/main/java/com/sample/otuslocationmapshw/MapsActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import com.sample.otuslocationmapshw.camera.CameraActivity
import com.sample.otuslocationmapshw.data.utils.LocationDataUtils
import com.sample.otuslocationmapshw.databinding.ActivityMapsBinding
import java.io.File
import androidx.core.graphics.scale

class MapsActivity : AppCompatActivity(), OnMapReadyCallback {

Expand All @@ -31,7 +32,7 @@ class MapsActivity : AppCompatActivity(), OnMapReadyCallback {
ActivityResultContracts.StartActivityForResult()
) {
if (it.resultCode == CameraActivity.SUCCESS_RESULT_CODE) {
// TODO("Обновить точки на карте при получении результата от камеры")
showPreviewsOnMap()
}
}

Expand All @@ -43,7 +44,8 @@ class MapsActivity : AppCompatActivity(), OnMapReadyCallback {

val mapFragment = supportFragmentManager
.findFragmentById(R.id.map) as SupportMapFragment
// TODO("Вызвать инициализацию карты")

mapFragment.getMapAsync(this)
}

override fun onCreateOptionsMenu(menu: Menu?): Boolean {
Expand Down Expand Up @@ -76,19 +78,17 @@ class MapsActivity : AppCompatActivity(), OnMapReadyCallback {
val exifInterface = ExifInterface(it)
val location = locationDataUtils.getLocationFromExif(exifInterface)
val point = LatLng(location.latitude, location.longitude)
val pinBitmap = Bitmap.createScaledBitmap(
BitmapFactory.decodeFile(
it.path,
BitmapFactory.Options().apply {
inPreferredConfig = Bitmap.Config.ARGB_8888
}), 64, 64, false
)
// TODO("Указать pinBitmap как иконку для маркера")
val pinBitmap = BitmapFactory.decodeFile(
it.path,
BitmapFactory.Options().apply {
inPreferredConfig = Bitmap.Config.ARGB_8888
}).scale(64, 64, false)
map.addMarker(
MarkerOptions()
.position(point)
.icon(BitmapDescriptorFactory.fromBitmap(pinBitmap))
)
// TODO("Передвинуть карту к местоположению последнего фото")
map.moveCamera(CameraUpdateFactory.newLatLngZoom(point, 20f))
}
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
package com.sample.otuslocationmapshw.camera

import android.Manifest.permission.ACCESS_COARSE_LOCATION
import android.Manifest.permission.ACCESS_FINE_LOCATION
import android.Manifest.permission.CAMERA
import android.annotation.SuppressLint
import android.content.pm.PackageManager
import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import android.hardware.SensorManager
import android.hardware.SensorManager.SENSOR_DELAY_NORMAL
import android.location.Location
import android.os.Bundle
import android.util.Log
Expand All @@ -14,10 +18,12 @@ import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.camera.core.CameraSelector
import androidx.camera.core.ImageCapture
import androidx.camera.core.ImageCaptureException
import androidx.camera.core.Preview
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import com.google.android.gms.location.CurrentLocationRequest
import com.google.android.gms.location.FusedLocationProviderClient
import com.google.android.gms.location.LocationServices
import com.google.common.util.concurrent.ListenableFuture
Expand Down Expand Up @@ -58,9 +64,12 @@ class CameraActivity : AppCompatActivity() {
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
cameraProviderFuture = ProcessCameraProvider.getInstance(this)

// TODO("Получить экземпляр SensorManager")
// TODO("Добавить проверку на наличие датчика акселерометра и присвоить значение tiltSensor")
tiltSensor = TODO("Get tilt sensor")
sensorManager = getSystemService(SensorManager::class.java)
tiltSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
if (tiltSensor == null) {
Log.e(TAG, "Sensor.TYPE_ACCELEROMETER not found")
}

cameraProviderFuture.addListener({
cameraProvider = cameraProviderFuture.get()
}, ContextCompat.getMainExecutor(this))
Expand All @@ -81,9 +90,17 @@ class CameraActivity : AppCompatActivity() {
}
}

// TODO("Подписаться на получение событий обновления датчика")
override fun onResume() {
super.onResume()
if (tiltSensor != null) {
sensorManager.registerListener(sensorEventListener, tiltSensor, SENSOR_DELAY_NORMAL)
}
}

// TODO("Остановить получение событий от датчика")
override fun onPause() {
super.onPause()
sensorManager.unregisterListener(sensorEventListener)
}

override fun onRequestPermissionsResult(
requestCode: Int,
Expand Down Expand Up @@ -117,19 +134,41 @@ class CameraActivity : AppCompatActivity() {
}
val filePath = folderPath + SimpleDateFormat(FILENAME_FORMAT, Locale.getDefault()).format(Date())

// TODO("4. Добавить установку местоположения в метаданные фото")
val outputFileOptions = ImageCapture.OutputFileOptions.Builder(File(filePath))
.setMetadata(ImageCapture.Metadata().also { it.location = location })
.build()

// TODO("Добавить вызов CameraX для фото")
// TODO("Вывести Toast о том, что фото успешно сохранено и закрыть текущее активити c указанием кода результата SUCCESS_RESULT_CODE")
// imageCapture...
imageCapture.takePicture(
outputFileOptions,
ContextCompat.getMainExecutor(this),
object : ImageCapture.OnImageSavedCallback {
override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
Toast.makeText(
this@CameraActivity,
"Photo is saved",
Toast.LENGTH_SHORT
).show()
setResult(SUCCESS_RESULT_CODE)
finish()
}

override fun onError(e: ImageCaptureException) {
Toast.makeText(
this@CameraActivity,
"Error: ${e.message}",
Toast.LENGTH_LONG
).show()
}
})
}
}

@SuppressLint("MissingPermission")
private fun getLastLocation(callback: (location: Location?) -> Unit) {
// TODO("Добавить получение местоположения от fusedLocationClient и передать результат в callback после получения")
fusedLocationClient.getCurrentLocation(CurrentLocationRequest.Builder().build(), null)
.addOnCompleteListener {
callback.invoke(it.result)
}
}

private fun startCamera() {
Expand All @@ -140,7 +179,7 @@ class CameraActivity : AppCompatActivity() {
val preview = Preview.Builder()
.build()
.also {
it.setSurfaceProvider(binding.cameraPreview.surfaceProvider)
it.surfaceProvider = binding.cameraPreview.surfaceProvider
}

imageCapture = ImageCapture.Builder().build()
Expand All @@ -150,7 +189,7 @@ class CameraActivity : AppCompatActivity() {
try {
cameraProvider.unbindAll()
cameraProvider.bindToLifecycle(
this, cameraSelector, preview, imageCapture
this, cameraSelector, preview, imageCapture
)
} catch (exc: Exception) {
Log.e(TAG, "Use case binding failed", exc)
Expand All @@ -168,9 +207,10 @@ class CameraActivity : AppCompatActivity() {
private const val TAG = "CameraXApp"
private const val FILENAME_FORMAT = "yyyy-MM-dd-HH-mm-ss-SSS"
private const val REQUEST_CODE_PERMISSIONS = 10
// TODO("Указать набор требуемых разрешений")
private val REQUIRED_PERMISSIONS: Array<String> = mutableListOf<String>(
// TODO("Добавить требуемые разрешения")
private val REQUIRED_PERMISSIONS: Array<String> = mutableListOf(
ACCESS_COARSE_LOCATION,
ACCESS_FINE_LOCATION,
CAMERA
).toTypedArray()

const val SUCCESS_RESULT_CODE = 15
Expand Down