From 3781234251d99696fc1d5bd4bfde7d1b4779f5b3 Mon Sep 17 00:00:00 2001 From: Dmitriy Bulygin Date: Sat, 13 Sep 2025 11:20:10 +0300 Subject: [PATCH 1/2] added solution --- app/build.gradle | 6 +- app/release/baselineProfiles/0/app-release.dm | Bin 0 -> 3025 bytes app/release/baselineProfiles/1/app-release.dm | Bin 0 -> 2962 bytes app/src/main/AndroidManifest.xml | 14 +- .../activities/EditProfileActivity.kt | 171 +++++++++++++++++- .../homework/activities/FillFormActivity.kt | 50 +++++ .../main/res/layout/activity_edit_profile.xml | 20 +- .../main/res/layout/activity_fill_form.xml | 73 ++++++++ app/src/main/res/values/strings.xml | 15 +- 9 files changed, 333 insertions(+), 16 deletions(-) create mode 100644 app/release/baselineProfiles/0/app-release.dm create mode 100644 app/release/baselineProfiles/1/app-release.dm create mode 100644 app/src/main/java/otus/gpb/homework/activities/FillFormActivity.kt create mode 100644 app/src/main/res/layout/activity_fill_form.xml diff --git a/app/build.gradle b/app/build.gradle index 57688408..0b8d43c8 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -4,8 +4,9 @@ plugins { id("io.gitlab.arturbosch.detekt") } + android { - compileSdk 34 + compileSdk 36 defaultConfig { applicationId "otus.gpb.homework.activities" @@ -57,7 +58,8 @@ dependencies { implementation 'androidx.appcompat:appcompat:1.6.1' implementation 'com.google.android.material:material:1.12.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' - implementation 'androidx.activity:activity-ktx:1.9.0' implementation 'androidx.fragment:fragment-ktx:1.7.1' implementation 'com.squareup.picasso:picasso:2.71828' + implementation 'androidx.activity:activity-ktx:1.8.0' + implementation 'androidx.activity:activity:1.8.0' } \ No newline at end of file diff --git a/app/release/baselineProfiles/0/app-release.dm b/app/release/baselineProfiles/0/app-release.dm new file mode 100644 index 0000000000000000000000000000000000000000..b91332f371a06f0def2aa32f2dbfb6276a937e4f GIT binary patch literal 3025 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 cQ|Z4$;?s7ep$ew*UYD literal 0 HcmV?d00001 diff --git a/app/release/baselineProfiles/1/app-release.dm b/app/release/baselineProfiles/1/app-release.dm new file mode 100644 index 0000000000000000000000000000000000000000..35292f9fb4cbe456925fd8ce98b9269cf02abbb1 GIT binary patch literal 2962 zcmZ`*2T&8(7EMH&k!k@9MHdC7FK84ZK}5+{z@TVCm0kowC=x&^u8K$zq=}$OhJ^ZY=FeaM{{PRLJMZ3k_r95X-hDI2+=OrcVStd35WpF! zZUguU2lsqm|9fah{}2sde~cS2L)ewG=K!>R)dB!b5dc86FaQt?oXaKY1*N43A6q(!Q?)QHb1#|`*c z=WiFRK8d;3e(yczs))z2U#b5vwRnN+>S!xMTQBkG(1>~+yMhx+9jjU7fWCm7^%Vp6 z?@a;h8|9mk;DrDmuGm+D9a?5DdXyN_mxF$oil%cueYWbo+Dq&|J#*Y8Ag_^Z9Ls~#O zb4AmQH_nxac2KnJLtBs#hZgQJMegi$firwfTX?%qTs=_r)BS_%daN2!%t$dS%Tah@^Wz~QF8N&3z#rtJ%T zuP5*4`c`7#xe3CEyP?k!YQaJgt0b8zP>W&|yp!iuDG{(A#M`FaI9P=;{k9TV>E17= zV~uH(wM5|~OD%YdtqMfW^ZPNm<*^~c%FLMJjpwI6AAv(kV=FnKFgPqHc)B#0Y;0tCvfBcmtYRdCHKJHrW%dWye~qAfL^?M$7SL z3SVQw4;u74Mwu?Lk~@K6IcW+jkuP;Lw^|OQJ269eVuV$yV5vgWR)Mn`aZXVQcC1Gk zGnS6h3w@ftr8i{)yHj4DOZaZB8s{KMX$?#?5ew71Q%!o#5$`Bfh3*jA&%U-2kEMzj9eJN|$I7pi1?CC>#E_h8T!qaWyvBU%N3Hv%H z6;ZwUKQs~wS+ac&=hT`8)!SZYgzO@K7p3%_S6X!F?4 z>?tN%kHs}Ta)`)aJP{d+e$~tWP6zug!X38tT=}vXBDd~N^Fx~l9S#~ikq$4rmuKXO zZ!t29F}&OjVx&*?pnZ!I5>4LMV^Ps}<2Q2kOHY#y{?t=i^J>Xqe_S}5p4#kj)g2t8#TrnME2d!@AuYSF3y;#rZFF9x(>OfjJkAsp=oIA z)h!&J)LTLlG)uD5xUL)g{DReePqlg;oy4}1yE1cq&8nt^6>$c#^0~@2adI*SCzV)9 zRsqI-Lb@SAbnj;lsaH=on03$@kV?zuko`MRLb5QHZPwZO>f2*(-W>7N}8ou@LQK|7iX$!p53Gh96DjBw@oHMGWkswh^tv)dPxjM_@p5j!=}T zcHfcwk~%#_4fXV|NY~8#+1>s#lcjbQQYH02jd8w~#MhiBNve?X#rkB!&xr@BFObXxmqsV%f4I{^Ip4wd- znCYl>{#OXKkFE36^=|uVT0jl6*Cyj~#v9%5Jo^>PNvGJJQTnA@x!DxCV$5#f{+)J3 z)rpJyzTte(SDZfpdN|LY5(*_b*L58~&64+o*x0AQ@y(nEaf6-Z zQcc%6^5$@GRb@LuuT8F%YXoh+MGUm@E-zjity|{Y7#et7{k?|X&lsvYJN|Kn6ppgT zZj2Ov)Te3jqy0P5YvGk7(*f@DK1rFrB^n?LxA# z*u7sI7elGw(7Hjb$v*m9!-MeNLf4OH;{ab2N{Bh~p+ zJMlz!sX*t_I}IjdTGjR2<4eK*?z60!Naym8SoZcpB{2f8q(6xZ(I_FFd(mgmvKh@c zHRws!&!@Z7RXJa4SBf>W{D+4PbzwYZjonuS`^~9pCp)}b z={5+l|FF2WFunY7y%6_$zaxQicBvg3Kao7}he_?4qBE#d-oI>@L+=h@!?e81)0LIT z1XL{1u(~XKA@V$}D`ID7;30<&anXcZ865TP;(POp&;N3(cC>zma%8%|5wuXiDMI{s){NQVHtZ0M$aWdVYFq?Q$A z8q4ef|8o6tB1FoE{U2V}S}M z92~6gWhg@%D{+Lk)9N|WxI!qX0qUDKwx+-^#_BXw-EdbUGeuQVRMsrHVEepXxr!vT zRh4<|c~lu*vi_cpR=;p=fa+un*jG62K*(2e`fNB5dKg6 mEQ|kM`SYzmnEnf+d$00yCEDDCU*N~_zP%N=w+n)PME?Yx&!bcT literal 0 HcmV?d00001 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e3d3319b..425aa7eb 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,6 +2,13 @@ + + + + + - - + + + \ 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..a3e243fc 100644 --- a/app/src/main/java/otus/gpb/homework/activities/EditProfileActivity.kt +++ b/app/src/main/java/otus/gpb/homework/activities/EditProfileActivity.kt @@ -1,14 +1,112 @@ package otus.gpb.homework.activities +import android.Manifest +import android.content.ActivityNotFoundException +import android.content.Context +import android.content.Intent +import android.graphics.Bitmap import android.graphics.BitmapFactory +import android.graphics.drawable.BitmapDrawable import android.net.Uri import android.os.Bundle +import android.os.Environment +import android.provider.MediaStore +import android.provider.Settings +import android.util.Log +import android.widget.Button +import android.widget.EditText import android.widget.ImageView +import android.widget.TextView +import android.widget.Toast +import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.widget.Toolbar +import androidx.core.content.FileProvider +import androidx.core.net.toUri +import com.google.android.material.dialog.MaterialAlertDialogBuilder +import java.io.ByteArrayOutputStream +import java.io.File +import java.io.FileOutputStream class EditProfileActivity : AppCompatActivity() { + private val launchPermissionCamera = registerForActivityResult( + ActivityResultContracts.RequestPermission() + ) { isGranted -> + when (isGranted) { + // Разрешение получено - показываем кота + true -> findViewById(R.id.imageview_photo).setImageResource(R.drawable.cat) + // Разрешение не получено + false -> if (shouldShowRequestPermissionRationale(Manifest.permission.CAMERA)) { + // Отображаем диалог с обоснованием перед запросом разрешения + showRationaleDialog() + } else { + showOpenSettingsDialog() + } + } + } + + private val launcherGetPicture = registerForActivityResult( + ActivityResultContracts.GetContent() + ) { image -> + if (image != null) { + //findViewById(R.id.imageview_photo).setImageURI(image) + populateImage(image) + } + } + + private val launcherFillFormActivity = registerForActivityResult( + ActivityResultContracts.StartActivityForResult() + ) { result -> + when (result.resultCode) { + RESULT_OK -> { + val data = result.data + if (data != null) { + val name = data.getStringExtra("name") ?: "" + val surname = data.getStringExtra("surname") ?: "" + val age = data.getIntExtra("age", 0) + + findViewById(R.id.textview_name).text = name + findViewById(R.id.textview_surname).text = surname + findViewById(R.id.textview_age).text = age.toString() + } + } + + RESULT_CANCELED -> { + Toast.makeText(this, "Галя, у нас отмена!", Toast.LENGTH_SHORT).show() + } + } + } + + private fun showRationaleDialog() { + MaterialAlertDialogBuilder(this) + .setTitle("Нужен доступ к камере") + .setMessage("Для создания фотографии профиля необходимо разрешение на использование камеры") + .setPositiveButton("Дать доступ") { dialog, which -> + // Повторно запрашиваем разрешение + launchPermissionCamera.launch(Manifest.permission.CAMERA) + } + .setNegativeButton("Отмена") { dialog, which -> + dialog.dismiss() + }.show() + } + + private fun showOpenSettingsDialog() { + MaterialAlertDialogBuilder(this) + .setTitle("Доступ к камере запрещен") + .setMessage("Для использования камеры необходимо предоставить разрешение в настройках приложения") + .setPositiveButton("Открыть настройки") { dialog, which -> + startActivity( + Intent( + Settings.ACTION_APPLICATION_DETAILS_SETTINGS, + "package:$packageName".toUri() + ) + ) + } + .setCancelable(false) + .show() + } + private lateinit var imageView: ImageView override fun onCreate(savedInstanceState: Bundle?) { @@ -24,10 +122,35 @@ class EditProfileActivity : AppCompatActivity() { openSenderApp() true } + else -> false } } } + + imageView.setOnClickListener { + val items = arrayOf("Сделать фото", "Выбрать фото") + MaterialAlertDialogBuilder(this) + .setTitle("Выберите действие") + .setItems(items) { dialog, which -> + when (which) { + 0 -> { // Сделать фото + launchPermissionCamera.launch(Manifest.permission.CAMERA) + } + + 1 -> { // Выбрать фото из галереи + launcherGetPicture.launch("image/*") + } + } + } + .show() + } + + findViewById