From 53bb927c3a60166be5debc126c845e1c10e674c6 Mon Sep 17 00:00:00 2001 From: "stepan.shulgin" Date: Mon, 5 Oct 2026 18:39:22 +0300 Subject: [PATCH 1/4] Implement runtime permissions and activity results homework --- app/src/main/AndroidManifest.xml | 8 +- .../activities/EditProfileActivity.kt | 133 ++++++++++++++++-- .../homework/activities/FillFormActivity.kt | 27 ++++ .../gpb/homework/activities/ProfileExtras.kt | 7 + .../main/res/layout/activity_edit_profile.xml | 6 +- .../main/res/layout/activity_fill_form.xml | 35 +++++ app/src/main/res/values/strings.xml | 14 +- 7 files changed, 211 insertions(+), 19 deletions(-) create mode 100644 app/src/main/java/otus/gpb/homework/activities/FillFormActivity.kt create mode 100644 app/src/main/java/otus/gpb/homework/activities/ProfileExtras.kt create mode 100644 app/src/main/res/layout/activity_fill_form.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e3d3319b..6e85efc6 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,6 +2,8 @@ + + + + @@ -24,4 +30,4 @@ - \ No newline at end of file + diff --git a/app/src/main/java/otus/gpb/homework/activities/EditProfileActivity.kt b/app/src/main/java/otus/gpb/homework/activities/EditProfileActivity.kt index d55ee922..7b41b65b 100644 --- a/app/src/main/java/otus/gpb/homework/activities/EditProfileActivity.kt +++ b/app/src/main/java/otus/gpb/homework/activities/EditProfileActivity.kt @@ -1,22 +1,58 @@ package otus.gpb.homework.activities -import android.graphics.BitmapFactory +import android.Manifest +import android.content.Intent +import android.content.pm.PackageManager import android.net.Uri import android.os.Bundle -import android.widget.ImageView +import android.provider.Settings +import androidx.activity.result.PickVisualMediaRequest +import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AppCompatActivity -import androidx.appcompat.widget.Toolbar +import com.google.android.material.dialog.MaterialAlertDialogBuilder +import otus.gpb.homework.activities.databinding.ActivityEditProfileBinding class EditProfileActivity : AppCompatActivity() { + private lateinit var binding: ActivityEditProfileBinding + private var selectedPhotoUri: Uri? = null - private lateinit var imageView: ImageView + private val cameraPermissionLauncher = registerForActivityResult( + ActivityResultContracts.RequestPermission() + ) { granted -> + if (granted) { + binding.imageviewPhoto.setImageResource(R.drawable.cat) + } else if (!shouldShowRequestPermissionRationale(Manifest.permission.CAMERA)) { + showSettingsDialog() + } + } + + private val photoPickerLauncher = registerForActivityResult( + ActivityResultContracts.PickVisualMedia() + ) { uri -> + uri?.let { + selectedPhotoUri = it + populateImage(it) + } + } + + private val editProfileLauncher = registerForActivityResult( + ActivityResultContracts.StartActivityForResult() + ) { result -> + if (result.resultCode == RESULT_OK) { + result.data?.let { data -> + binding.textviewName.text = data.getStringExtra(ProfileExtras.NAME).orEmpty() + binding.textviewSurname.text = data.getStringExtra(ProfileExtras.SURNAME).orEmpty() + binding.textviewAge.text = data.getStringExtra(ProfileExtras.AGE).orEmpty() + } + } + } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.activity_edit_profile) - imageView = findViewById(R.id.imageview_photo) + binding = ActivityEditProfileBinding.inflate(layoutInflater) + setContentView(binding.root) - findViewById(R.id.toolbar).apply { + binding.toolbar.apply { inflateMenu(R.menu.menu) setOnMenuItemClickListener { when (it.itemId) { @@ -28,17 +64,86 @@ class EditProfileActivity : AppCompatActivity() { } } } + binding.imageviewPhoto.setOnClickListener { showPhotoActionDialog() } + binding.buttonEditProfile.setOnClickListener { + editProfileLauncher.launch(Intent(this, FillFormActivity::class.java)) + } } - /** - * Используйте этот метод чтобы отобразить картинку полученную из медиатеки в ImageView - */ private fun populateImage(uri: Uri) { - val bitmap = BitmapFactory.decodeStream(contentResolver.openInputStream(uri)) - imageView.setImageBitmap(bitmap) + binding.imageviewPhoto.setImageURI(uri) } private fun openSenderApp() { - TODO("В качестве реализации метода отправьте неявный Intent чтобы поделиться профилем. В качестве extras передайте заполненные строки и картинку") + val profileDescription = listOf( + binding.textviewName.text, + binding.textviewSurname.text, + binding.textviewAge.text + ).joinToString(separator = " ") + val intent = Intent(Intent.ACTION_SEND).apply { + type = "image/*" + setPackage(TELEGRAM_PACKAGE) + putExtra(Intent.EXTRA_TEXT, profileDescription) + putExtra(ProfileExtras.NAME, binding.textviewName.text.toString()) + putExtra(ProfileExtras.SURNAME, binding.textviewSurname.text.toString()) + putExtra(ProfileExtras.AGE, binding.textviewAge.text.toString()) + selectedPhotoUri?.let { uri -> + putExtra(Intent.EXTRA_STREAM, uri) + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) + } + } + startActivity(intent) + } + + private fun showPhotoActionDialog() { + MaterialAlertDialogBuilder(this) + .setItems(arrayOf(getString(R.string.take_photo), getString(R.string.select_photo))) { _, index -> + when (index) { + TAKE_PHOTO_INDEX -> requestCameraPermission() + SELECT_PHOTO_INDEX -> photoPickerLauncher.launch( + PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly) + ) + } + } + .show() + } + + private fun requestCameraPermission() { + when { + checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED -> { + binding.imageviewPhoto.setImageResource(R.drawable.cat) + } + shouldShowRequestPermissionRationale(Manifest.permission.CAMERA) -> showRationaleDialog() + else -> cameraPermissionLauncher.launch(Manifest.permission.CAMERA) + } + } + + private fun showRationaleDialog() { + MaterialAlertDialogBuilder(this) + .setMessage(R.string.camera_rationale) + .setPositiveButton(R.string.grant_access) { _, _ -> + cameraPermissionLauncher.launch(Manifest.permission.CAMERA) + } + .setNegativeButton(R.string.cancel, null) + .show() + } + + private fun showSettingsDialog() { + MaterialAlertDialogBuilder(this) + .setMessage(R.string.camera_settings_message) + .setPositiveButton(R.string.open_settings) { _, _ -> + val intent = Intent( + Settings.ACTION_APPLICATION_DETAILS_SETTINGS, + Uri.fromParts("package", packageName, null) + ) + startActivity(intent) + } + .show() + } + + private companion object { + const val TAKE_PHOTO_INDEX = 0 + const val SELECT_PHOTO_INDEX = 1 + const val TELEGRAM_PACKAGE = "org.telegram.messenger" } -} \ No newline at end of file +} diff --git a/app/src/main/java/otus/gpb/homework/activities/FillFormActivity.kt b/app/src/main/java/otus/gpb/homework/activities/FillFormActivity.kt new file mode 100644 index 00000000..8cb407dc --- /dev/null +++ b/app/src/main/java/otus/gpb/homework/activities/FillFormActivity.kt @@ -0,0 +1,27 @@ +package otus.gpb.homework.activities + +import android.app.Activity +import android.content.Intent +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import otus.gpb.homework.activities.databinding.ActivityFillFormBinding + +class FillFormActivity : AppCompatActivity() { + private lateinit var binding: ActivityFillFormBinding + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivityFillFormBinding.inflate(layoutInflater) + setContentView(binding.root) + + binding.applyButton.setOnClickListener { + val result = Intent().apply { + putExtra(ProfileExtras.NAME, binding.nameEditText.text.toString()) + putExtra(ProfileExtras.SURNAME, binding.surnameEditText.text.toString()) + putExtra(ProfileExtras.AGE, binding.ageEditText.text.toString()) + } + setResult(Activity.RESULT_OK, result) + finish() + } + } +} diff --git a/app/src/main/java/otus/gpb/homework/activities/ProfileExtras.kt b/app/src/main/java/otus/gpb/homework/activities/ProfileExtras.kt new file mode 100644 index 00000000..6b1068f4 --- /dev/null +++ b/app/src/main/java/otus/gpb/homework/activities/ProfileExtras.kt @@ -0,0 +1,7 @@ +package otus.gpb.homework.activities + +object ProfileExtras { + const val NAME = "name" + const val SURNAME = "surname" + const val AGE = "age" +} diff --git a/app/src/main/res/layout/activity_edit_profile.xml b/app/src/main/res/layout/activity_edit_profile.xml index eb4a7197..54eb2f92 100644 --- a/app/src/main/res/layout/activity_edit_profile.xml +++ b/app/src/main/res/layout/activity_edit_profile.xml @@ -61,13 +61,13 @@ app:layout_constraintTop_toBottomOf="@+id/textview_surname" />