From 486c9485b952a25f3cb175fe32b5360ea81a7127 Mon Sep 17 00:00:00 2001 From: Jorgen Johnsen <jamjohns@stud.ntnu.no> Date: Wed, 7 Dec 2022 17:58:00 +0100 Subject: [PATCH] final update --- .idea/vcs.xml | 6 + app/build.gradle | 26 +- app/src/main/AndroidManifest.xml | 11 +- .../com/daerikus/bachelorproject2/Albums.kt | 35 ++ .../bachelorproject2/CameraActivity.kt | 327 ++++++++++++++++++ .../bachelorproject2/GalleryActivity.kt | 37 +- .../bachelorproject2/GalleryAdapter.kt | 23 +- .../daerikus/bachelorproject2/MainActivity.kt | 41 ++- app/src/main/res/layout/activity_camera.xml | 32 ++ app/src/main/res/layout/activity_gallery.xml | 13 +- app/src/main/res/layout/activity_main.xml | 14 +- app/src/main/res/layout/image_item.xml | 20 +- app/src/main/res/values/strings.xml | 1 + 13 files changed, 526 insertions(+), 60 deletions(-) create mode 100644 .idea/vcs.xml create mode 100644 app/src/main/java/com/daerikus/bachelorproject2/Albums.kt create mode 100644 app/src/main/java/com/daerikus/bachelorproject2/CameraActivity.kt create mode 100644 app/src/main/res/layout/activity_camera.xml diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="VcsDirectoryMappings"> + <mapping directory="" vcs="Git" /> + </component> +</project> \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 61c5522..f141a7b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -5,12 +5,12 @@ plugins { } android { - compileSdk 31 + compileSdk 32 defaultConfig { applicationId "com.daerikus.bachelorproject2" minSdk 26 - targetSdk 31 + targetSdk 32 versionCode 1 versionName "1.0" @@ -37,15 +37,25 @@ android { dependencies { - implementation 'androidx.core:core-ktx:1.7.0' - implementation 'androidx.appcompat:appcompat:1.4.1' - implementation 'com.google.android.material:material:1.5.0' - implementation 'androidx.constraintlayout:constraintlayout:2.1.3' - implementation 'androidx.navigation:navigation-fragment-ktx:2.3.5' - implementation 'androidx.navigation:navigation-ui-ktx:2.3.5' + implementation 'androidx.core:core-ktx:1.8.0' + implementation 'androidx.appcompat:appcompat:1.5.1' + implementation 'com.google.android.material:material:1.7.0' + implementation 'com.github.bumptech.glide:glide:4.14.2' + implementation 'androidx.constraintlayout:constraintlayout:2.1.4' + implementation 'androidx.navigation:navigation-fragment-ktx:2.5.3' + implementation 'androidx.navigation:navigation-ui-ktx:2.5.3' implementation 'androidx.legacy:legacy-support-v4:1.0.0' implementation 'androidx.recyclerview:recyclerview:1.2.1' testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' + + def camerax_version = "1.1.0-beta01" + implementation "androidx.camera:camera-core:${camerax_version}" + implementation "androidx.camera:camera-camera2:${camerax_version}" + implementation "androidx.camera:camera-lifecycle:${camerax_version}" + implementation "androidx.camera:camera-video:${camerax_version}" + + implementation "androidx.camera:camera-view:${camerax_version}" + implementation "androidx.camera:camera-extensions:${camerax_version}" } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 1ae979d..84ac5e8 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,8 +2,10 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.daerikus.bachelorproject2"> + <uses-feature android:name="android.hardware.camera.any" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> - + <uses-permission android:name="android.permission.RECORD_AUDIO" /> + <uses-permission android:name="android.permission.CAMERA" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" @@ -11,6 +13,13 @@ android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.Bachelorproject2"> + <activity + android:name=".CameraActivity" + android:exported="false"> + <meta-data + android:name="android.app.lib_name" + android:value="" /> + </activity> <activity android:name=".GalleryActivity" android:exported="false" diff --git a/app/src/main/java/com/daerikus/bachelorproject2/Albums.kt b/app/src/main/java/com/daerikus/bachelorproject2/Albums.kt new file mode 100644 index 0000000..2cd7b24 --- /dev/null +++ b/app/src/main/java/com/daerikus/bachelorproject2/Albums.kt @@ -0,0 +1,35 @@ +package com.daerikus.bachelorproject2 + +import android.os.Parcel +import android.os.Parcelable + +data class Albums(var folderNames: String, var imagePath: String, var imgCount: Int, var isVideo: Boolean) : Parcelable { + constructor(parcel: Parcel) : this( + parcel.readString()!!, + parcel.readString()!!, + parcel.readInt(), + parcel.readByte() != 0.toByte() + ) { + } + + override fun writeToParcel(p0: Parcel?, p1: Int) { + p0?.writeString(folderNames) + p0?.writeString(imagePath) + p0?.writeInt(imgCount) + p0?.writeByte(if (isVideo) 1 else 0) + } + + override fun describeContents(): Int { + return 0 + } + + companion object CREATOR : Parcelable.Creator<Albums> { + override fun createFromParcel(p0: Parcel?): Albums { + return Albums(p0!!) + } + + override fun newArray(p0: Int): Array<Albums?> { + return arrayOfNulls(p0) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/daerikus/bachelorproject2/CameraActivity.kt b/app/src/main/java/com/daerikus/bachelorproject2/CameraActivity.kt new file mode 100644 index 0000000..e10e680 --- /dev/null +++ b/app/src/main/java/com/daerikus/bachelorproject2/CameraActivity.kt @@ -0,0 +1,327 @@ +package com.daerikus.bachelorproject2 + +import android.Manifest +import android.content.ContentValues +import android.content.Context +import android.content.pm.PackageManager +import android.hardware.Sensor +import android.hardware.SensorEvent +import android.hardware.SensorEventListener +import android.hardware.SensorManager +import android.os.* +import android.provider.MediaStore +import android.util.Log +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.camera.video.* +import androidx.core.app.ActivityCompat +import androidx.core.content.ContextCompat +import androidx.core.content.PermissionChecker +import com.daerikus.bachelorproject2.databinding.ActivityCameraBinding +import java.io.OutputStreamWriter +import java.text.SimpleDateFormat +import java.util.* +import java.util.concurrent.ExecutorService +import java.util.concurrent.Executors + +class CameraActivity : AppCompatActivity(), SensorEventListener { + private lateinit var viewBinding: ActivityCameraBinding + + private var imageCapture: ImageCapture? = null + + private var videoCapture: VideoCapture<Recorder>? = null + private var recording: Recording? = null + + private lateinit var cameraExecutor: ExecutorService + + private lateinit var sensorManager: SensorManager + private var accelerometer: Sensor ?= null + private var gyroscope: Sensor ?= null + + private var timeOnStart = 0L + + private var hasAccelerometer = false + private var hasGyroscope = false + + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + viewBinding = ActivityCameraBinding.inflate(layoutInflater) + setContentView(viewBinding.root) + + detectSensors() + + // Create file to write data to + /* + dataFileDir = File(baseContext.getExternalFilesDir(null), "/IMQdata") + if (!dataFileDir!!.exists()) { + dataFileDir!!.mkdir() + if (dataFileDir!!.exists()) { + Toast.makeText(baseContext, "Made file", Toast.LENGTH_SHORT).show() + dataFile = File(baseContext.getExternalFilesDir(null).toString() + "/IMQdata", + SimpleDateFormat(FILENAME_FORMAT, Locale.US).format(System.currentTimeMillis()).toString() + ".txt" + ) + } + }*/ + + + // Request permission + if (allPermissionsGranted()) { + startCamera() + } else { + ActivityCompat.requestPermissions( + this, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS + ) + } + + // Listener for image capture button + viewBinding.imageCaptureButton.setOnClickListener{ + takePhoto() + recording?.stop() + finish() + } + + // Sensor listeners + if (hasAccelerometer){ + sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL) + } + if (hasGyroscope) { + sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE), SensorManager.SENSOR_DELAY_NORMAL) + } + + // Start video recording + Handler(Looper.getMainLooper()).postDelayed( + { + timeOnStart = SystemClock.elapsedRealtime() + takeVideo() + }, 500 + ) + + cameraExecutor = Executors.newSingleThreadExecutor() + } + + private fun takePhoto() { + val imageCapture = imageCapture ?: return + + val name = SimpleDateFormat(FILENAME_FORMAT, Locale.US).format(System.currentTimeMillis()) + val contentValues = ContentValues().apply { + put(MediaStore.MediaColumns.DISPLAY_NAME, name) + put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg") + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) + put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/IMQ_pictures") + } + + val outputOptions = ImageCapture.OutputFileOptions + .Builder(contentResolver, + MediaStore.Images.Media.EXTERNAL_CONTENT_URI, + contentValues) + .build() + + imageCapture.takePicture( + outputOptions, + ContextCompat.getMainExecutor(this), + object : ImageCapture.OnImageSavedCallback { + override fun onError(exception: ImageCaptureException) { + Log.e(TAG, "Photo capture failed: ${exception.message}", exception) + } + + override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) { + val msg = "Photo capture succeeded: ${outputFileResults.savedUri}" + Toast.makeText(baseContext, msg, Toast.LENGTH_SHORT).show() + Log.d(TAG, msg) + } + } + ) + } + + private fun takeVideo() { + val videoCapture = this.videoCapture ?: return + + val curRecording = recording + if (curRecording != null) { + // Stop recording + curRecording.stop() + recording = null + return + } + + // Start new recording + val name = SimpleDateFormat(FILENAME_FORMAT, Locale.US) + .format(System.currentTimeMillis()) + val contentValues = ContentValues().apply { + put(MediaStore.MediaColumns.DISPLAY_NAME, name) + put(MediaStore.MediaColumns.MIME_TYPE, "video/mp4") + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) + put(MediaStore.Video.Media.RELATIVE_PATH, "Movies/IMQ_Videos") + } + + val mediaStoreOutputOptions = MediaStoreOutputOptions + .Builder(contentResolver, MediaStore.Video.Media.EXTERNAL_CONTENT_URI) + .setContentValues(contentValues) + .build() + recording = videoCapture.output + .prepareRecording(this, mediaStoreOutputOptions) + .apply { + if (PermissionChecker.checkSelfPermission(this@CameraActivity, + Manifest.permission.RECORD_AUDIO) == + PermissionChecker.PERMISSION_GRANTED) { + withAudioEnabled() + } + } + .start(ContextCompat.getMainExecutor(this)) { recordEvent -> + when(recordEvent) { + is VideoRecordEvent.Start -> { + val msg = "Video capture started" + Toast.makeText(baseContext, msg, Toast.LENGTH_SHORT).show() + } + is VideoRecordEvent.Finalize -> { + if (!recordEvent.hasError()) { + val msg = "Video capture succeeded: " + + "${recordEvent.outputResults.outputUri}" + Toast.makeText(baseContext, msg, Toast.LENGTH_SHORT).show() + Log.d(TAG, msg) + } else { + recording?.close() + recording = null + Log.e(TAG, "Video capture ends with error: " + + "${recordEvent.error}") + } + } + } + } + } + + private fun startCamera() { + val cameraProviderFuture = ProcessCameraProvider.getInstance(this) + + cameraProviderFuture.addListener({ + val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get() + + val preview = Preview.Builder().build().also { + it.setSurfaceProvider(viewBinding.viewFinder.surfaceProvider) + } + + val recorder = Recorder.Builder() + /*.setQualitySelector(QualitySelector.from(Quality.HIGHEST, + FallbackStrategy.higherQualityOrLowerThan(Quality.SD)))*/ + .setQualitySelector(QualitySelector.from(Quality.SD)) + .build() + + videoCapture = VideoCapture.withOutput(recorder) + + imageCapture = ImageCapture.Builder().build() + + // Select back camera as default + val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA + + try { + cameraProvider.unbindAll() + + cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageCapture, videoCapture) + } catch (exc: Exception) { + Log.e(TAG, "Use case binding failed", exc) + } + }, ContextCompat.getMainExecutor(this)) + } + + private fun detectSensors() { + sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager + + if (sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) != null) { + hasAccelerometer = true + accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) + } else { + Log.e(TAG, "Device does not have accelerometer") + } + + if (sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE) != null) { + hasGyroscope = true + gyroscope = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE) + } else { + Log.e(TAG, "Device does not have gyroscope") + } + } + + private fun writeDataToFile(/*file: File?,*/ dataToWrite: String, fileName: String) { + /*file?.writeBytes(dataToWrite.toByteArray()) + Toast.makeText(baseContext, "Saved data to file", Toast.LENGTH_SHORT).show()*/ + val text = dataToWrite + "\n" + try { + val fileOutputStream = openFileOutput(fileName, Context.MODE_APPEND) + val outputWriter = OutputStreamWriter(fileOutputStream) + outputWriter.write(text) + outputWriter.close() + Toast.makeText(baseContext, "Saved data to file", Toast.LENGTH_SHORT).show() + } catch (e: Exception) { + e.printStackTrace() + } + } + + private fun timeSinceActivityStart() : Long { + return SystemClock.elapsedRealtime() - timeOnStart + } + + private fun allPermissionsGranted() = REQUIRED_PERMISSIONS.all { + ContextCompat.checkSelfPermission(baseContext, it) == PackageManager.PERMISSION_GRANTED + } + + companion object { + private const val TAG = "IMQ capture app" + private const val FILENAME_FORMAT = "yyyy-MM-dd-HH-mm" + private const val TIME_FORMAT = "mm-ss" + private const val DATAFILE_NAME = "IMQdata.txt" + private const val REQUEST_CODE_PERMISSIONS = 10 + private val REQUIRED_PERMISSIONS = + mutableListOf ( + Manifest.permission.CAMERA, + Manifest.permission.RECORD_AUDIO + ).apply { + if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) { + add(Manifest.permission.WRITE_EXTERNAL_STORAGE) + } + }.toTypedArray() + } + + override fun onRequestPermissionsResult( + requestCode: Int, permissions: Array<String>, grantResults: + IntArray) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + if (requestCode == REQUEST_CODE_PERMISSIONS) { + if (allPermissionsGranted()) { + startCamera() + } else { + Toast.makeText(this, + "Permissions not granted by the user.", + Toast.LENGTH_SHORT).show() + finish() + } + } + } + + override fun onSensorChanged(event: SensorEvent?) { + if (event != null){ + if (event.sensor.type == Sensor.TYPE_ACCELEROMETER) { + val accelX = event.values[0] + val accelY = event.values[1] + val accelZ = event.values[2] + + val lineToWrite = "Significant movement at ${SimpleDateFormat(TIME_FORMAT, Locale.US).format(timeSinceActivityStart())}" + val threshold = 8.0f + + if (accelX > threshold && accelY > threshold || accelX > threshold && accelZ > threshold || accelY > threshold && accelZ > threshold) { + writeDataToFile(lineToWrite, DATAFILE_NAME) + } + } + } + } + + override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) { + return + } +} \ No newline at end of file diff --git a/app/src/main/java/com/daerikus/bachelorproject2/GalleryActivity.kt b/app/src/main/java/com/daerikus/bachelorproject2/GalleryActivity.kt index b10e7d0..b541312 100644 --- a/app/src/main/java/com/daerikus/bachelorproject2/GalleryActivity.kt +++ b/app/src/main/java/com/daerikus/bachelorproject2/GalleryActivity.kt @@ -1,30 +1,61 @@ package com.daerikus.bachelorproject2 +import android.app.Activity +import android.content.ContentUris +import android.database.Cursor +import android.graphics.Bitmap +import android.graphics.BitmapFactory import android.net.Uri import androidx.appcompat.app.AppCompatActivity import android.os.Bundle +import android.provider.MediaStore import androidx.recyclerview.widget.GridLayoutManager import kotlinx.android.synthetic.main.activity_gallery.* class GalleryActivity : AppCompatActivity() { - lateinit var layoutManager: GridLayoutManager - lateinit var adapter: GalleryAdapter + private lateinit var layoutManager: GridLayoutManager + private lateinit var adapter: GalleryAdapter override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_gallery) - val imageUri = Uri.parse(intent.getStringExtra("IMAGE_URI")) + //val imageUri = Uri.parse(intent.getStringExtra("IMAGE_URI")) + val imageUri = loadImagesFromStorage() layoutManager = GridLayoutManager(this, 4) galleryRecycler.layoutManager = layoutManager + //val image = ImageItem(imageUri) + adapter = GalleryAdapter(this, imageUri) galleryRecycler.adapter = adapter } + private fun loadImagesFromStorage(): ArrayList<Uri> { + val uri: Uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI + val cursor: Cursor? + val columnIndexId: Int + val listOfAllImages = arrayListOf<Uri>() + val projection = arrayOf(MediaStore.Images.Media._ID) + var imageId: Long + cursor = this.contentResolver.query(uri, projection, null, null, null) + + if (cursor != null) { + columnIndexId = cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID) + while (cursor.moveToNext()) { + imageId = cursor.getLong(columnIndexId) + val uriImage = Uri.withAppendedPath(uri, "" + imageId) + listOfAllImages.add(uriImage) + } + cursor.close() + } + return listOfAllImages + } + override fun onResume() { super.onResume() + layoutManager = GridLayoutManager(this, 2) galleryRecycler.adapter?.notifyDataSetChanged() } } \ No newline at end of file diff --git a/app/src/main/java/com/daerikus/bachelorproject2/GalleryAdapter.kt b/app/src/main/java/com/daerikus/bachelorproject2/GalleryAdapter.kt index 3c89630..213e1d7 100644 --- a/app/src/main/java/com/daerikus/bachelorproject2/GalleryAdapter.kt +++ b/app/src/main/java/com/daerikus/bachelorproject2/GalleryAdapter.kt @@ -1,20 +1,24 @@ package com.daerikus.bachelorproject2 -import android.content.Intent +import android.content.Context import android.net.Uri import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.ImageView import androidx.recyclerview.widget.RecyclerView +import com.bumptech.glide.Glide import kotlinx.android.synthetic.main.image_item.view.* -class GalleryAdapter(val images: ArrayList<Uri>) : RecyclerView.Adapter <GalleryAdapter.GalleryViewHolder>() { +class GalleryAdapter(val context: Context, val images: ArrayList<Uri>) : RecyclerView.Adapter <GalleryAdapter.GalleryViewHolder>() { class GalleryViewHolder(v: View) : RecyclerView.ViewHolder(v) { var view: View = v - var imageUri: Uri = Uri.parse("") + lateinit var imageUri: Uri + val imageView: ImageView = view.findViewById(R.id.imageView) fun bindImage(imageUri: Uri) { this.imageUri = imageUri + //this.imageView = view.findViewById(R.id.imageView) view.imageView.setImageURI(imageUri) } } @@ -26,8 +30,17 @@ class GalleryAdapter(val images: ArrayList<Uri>) : RecyclerView.Adapter <Gallery override fun onBindViewHolder(holder: GalleryViewHolder, position: Int) { val image = images[position] - holder.bindImage(image) + //holder.bindImage(image) + Glide.with(context).load(image).into(holder.imageView) } override fun getItemCount() = images.size -} \ No newline at end of file +} + + + + + + + + diff --git a/app/src/main/java/com/daerikus/bachelorproject2/MainActivity.kt b/app/src/main/java/com/daerikus/bachelorproject2/MainActivity.kt index 40c71e6..b86a61b 100644 --- a/app/src/main/java/com/daerikus/bachelorproject2/MainActivity.kt +++ b/app/src/main/java/com/daerikus/bachelorproject2/MainActivity.kt @@ -1,14 +1,20 @@ package com.daerikus.bachelorproject2 import android.content.ContentValues +import android.Manifest import android.content.Intent import android.net.Uri +import android.os.Build import android.os.Bundle +import android.os.Environment import android.provider.MediaStore +import android.util.Log import android.widget.Button import android.widget.ImageView +import android.widget.Toast import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AppCompatActivity +import java.io.File class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { @@ -16,39 +22,50 @@ class MainActivity : AppCompatActivity() { setContentView(R.layout.activity_main) val cameraButton: Button = findViewById(R.id.openCamera) - val galleryButton: Button = findViewById(R.id.openGallery) + //val galleryButton: Button = findViewById(R.id.openGallery) val previewImage: ImageView = findViewById(R.id.imagePreview) - var camUri: Uri = Uri.parse("") + val camUri: Uri? = null + + // Create output folder if it does not already exist + val fullPath = Environment.getExternalStorageDirectory().absolutePath + "/IMQdata" + try { + val f = File(fullPath) + if (!f.exists()) + f.mkdir() + } catch (e: Exception){ + Log.w("Something", e.toString()) + } val getImageFromCamera = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { if (it.resultCode == RESULT_OK) { // This is where the picture gets handled previewImage.setImageURI(camUri) - } } - fun pickCamera() { - val values = ContentValues() + cameraButton.setOnClickListener{ + /*val values = ContentValues() values.put(MediaStore.Images.Media.TITLE, "New Picture") values.put(MediaStore.Images.Media.DESCRIPTION, "From Camera") camUri = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)!! val cameraIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE) cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, camUri) - - getImageFromCamera.launch(cameraIntent) - } - - cameraButton.setOnClickListener{ - pickCamera() + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) { + cameraIntent.putExtra(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/TestFolder") + } + getImageFromCamera.launch(cameraIntent)*/ + val cameraIntent = Intent(this, CameraActivity::class.java) + startActivity(cameraIntent) } + /* galleryButton.setOnClickListener { // Open gallery val galleryIntent = Intent(this, GalleryActivity:: class.java) - galleryIntent.putExtra("IMAGE_URI", camUri.toString()) + //galleryIntent.putExtra("IMAGE_URI", camUri.toString()) startActivity(galleryIntent) } + */ } } \ No newline at end of file diff --git a/app/src/main/res/layout/activity_camera.xml b/app/src/main/res/layout/activity_camera.xml new file mode 100644 index 0000000..58a350a --- /dev/null +++ b/app/src/main/res/layout/activity_camera.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + tools:context=".CameraActivity"> + + <androidx.camera.view.PreviewView + android:id="@+id/viewFinder" + android:layout_width="match_parent" + android:layout_height="match_parent" /> + + <Button + android:id="@+id/image_capture_button" + android:layout_width="110dp" + android:layout_height="110dp" + android:layout_marginBottom="50dp" + android:layout_marginEnd="50dp" + android:elevation="2dp" + android:text="@string/take_picture" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toEndOf="@id/vertical_centerline"/> + + <androidx.constraintlayout.widget.Guideline + android:id="@+id/vertical_centerline" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="vertical" + app:layout_constraintGuide_percent=".40" /> + +</androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/activity_gallery.xml b/app/src/main/res/layout/activity_gallery.xml index e1a2af3..673443f 100644 --- a/app/src/main/res/layout/activity_gallery.xml +++ b/app/src/main/res/layout/activity_gallery.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> -<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" +<RelativeLayout + xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" @@ -8,14 +9,14 @@ <androidx.recyclerview.widget.RecyclerView android:id="@+id/galleryRecycler" - android:layout_width="0dp" - android:layout_height="0dp" + android:layout_width="wrap_content" + android:layout_height="wrap_content" android:layout_marginStart="8dp" android:layout_marginTop="8dp" android:layout_marginEnd="8dp" - android:layout_marginBottom="8dp" - app:layout_constraintBottom_toBottomOf="parent" + android:scrollbars="vertical" + app:layoutManager="androidx.recyclerview.widget.GridLayoutManager" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> -</androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file +</RelativeLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 8ecadac..3e88632 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -28,16 +28,6 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/textView" /> - <Button - android:id="@+id/openGallery" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginStart="124dp" - android:layout_marginTop="56dp" - android:text="@string/open_gallery" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@+id/openCamera" /> - <ImageView android:id="@+id/imagePreview" android:layout_width="216dp" @@ -48,8 +38,6 @@ app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="1.0" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@+id/openGallery" - app:layout_constraintVertical_bias="1.0" /> + app:layout_constraintStart_toStartOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/image_item.xml b/app/src/main/res/layout/image_item.xml index 5c0bea4..c718023 100644 --- a/app/src/main/res/layout/image_item.xml +++ b/app/src/main/res/layout/image_item.xml @@ -1,16 +1,12 @@ <?xml version="1.0" encoding="utf-8"?> -<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" +<ImageView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" - android:layout_height="match_parent"> - - <ImageView - android:id="@+id/imageView" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginStart="8dp" - android:layout_marginTop="8dp" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toTopOf="parent" /> -</androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file + android:layout_height="wrap_content" + android:padding="1dp" + android:id="@+id/imageView" + android:scaleType="centerCrop" + app:layout_constraintDimensionRatio="1" + tools:ignore="ContentDescription"> +</ImageView> \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 33a892b..3894326 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -3,6 +3,7 @@ <string name="open_camera">Open Camera</string> <string name="open_gallery">Open Gallery</string> <string name="title_activity_gallery">GalleryActivity</string> + <string name="take_picture">Take Picture</string> <!-- Strings used for fragments for navigation --> <string name="first_fragment_label">First Fragment</string> <string name="second_fragment_label">Second Fragment</string> -- GitLab