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
1 change: 1 addition & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id("io.gitlab.arturbosch.detekt")
id("kotlin-parcelize")
}

android {
Expand Down
9 changes: 9 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
<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.CAMERA"/>
<uses-permission android:name="android.permission.INTERNET" />

<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
Expand All @@ -13,6 +19,9 @@
android:theme="@style/Theme.Activities"
tools:targetApi="31">

<activity
android:name=".FillFormActivity"
android:exported="false" />
<activity
android:name=".EditProfileActivity"
android:exported="true">
Expand Down
152 changes: 148 additions & 4 deletions app/src/main/java/otus/gpb/homework/activities/EditProfileActivity.kt
Original file line number Diff line number Diff line change
@@ -1,15 +1,119 @@
package otus.gpb.homework.activities

import android.Manifest
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Bundle
import android.provider.Settings
import android.widget.ImageView
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.content.ContextCompat
import android.content.DialogInterface
import android.widget.Button
import android.widget.TextView
import android.widget.Toast
import androidx.activity.result.PickVisualMediaRequest
import androidx.activity.result.launch

class EditProfileActivity : AppCompatActivity() {

private lateinit var imageView: ImageView
private var repeatRequest : Boolean = false
private lateinit var editProfileButton: Button

private val launchPermissionCamera =
registerForActivityResult(ActivityResultContracts.RequestPermission()) { granted ->
when {
granted -> {
// Permission granted
imageView.setImageResource(R.drawable.cat)
}
!shouldShowRequestPermissionRationale(Manifest.permission.CAMERA) -> {
if( !repeatRequest ){
ViewDialogSettings()
}
}
else -> {
repeatRequest = true
// Permission denied
}
}
}

fun onButtonMakePhoto(dialog: DialogInterface?, which: Int) {
val isGrantedCamera = ContextCompat.checkSelfPermission(
this,
Manifest.permission.CAMERA
) == PackageManager.PERMISSION_GRANTED
if(isGrantedCamera){
imageView.setImageResource(R.drawable.cat)
}
else{
if( repeatRequest ){
ViewDialogRepeat()
}
else{
launchPermissionCamera.launch(android.Manifest.permission.CAMERA)
}
}
}

fun onButtonSelectPhoto(dialog: DialogInterface?, which: Int) {
launchSelectPhoto.launch(
PickVisualMediaRequest(
ActivityResultContracts.PickVisualMedia.ImageOnly
)
)
}

fun onButtonCancel(dialog: DialogInterface?, which: Int) {
dialog?.dismiss()
}

fun onButtonGiveACCESS(dialog: DialogInterface?, which: Int) {
launchPermissionCamera.launch(Manifest.permission.CAMERA)
repeatRequest = false
}

fun onButtonOpenSettings(dialog: DialogInterface?, which: Int) {
startActivity(Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
data = Uri.fromParts("package", packageName, null)
})
}

private fun ViewDialog()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Не соответствуют конвенциям именования. Методы должны начинаться с маленькой буквы и быть глаголами. Предлагаю переименовать их в showPhotoSelectionDialog(), showRationaleDialog() и showSettingsDialog()

{
MaterialAlertDialogBuilder(this)
.setTitle(resources.getString(R.string.title))
.setNeutralButton(resources.getString(R.string.cancel), ::onButtonCancel)
.setPositiveButton(resources.getString(R.string.make_photo), ::onButtonMakePhoto)
.setNegativeButton(resources.getString(R.string.select_photo), ::onButtonSelectPhoto)
.show()
}

private fun ViewDialogRepeat()
{
MaterialAlertDialogBuilder(this)
.setTitle(resources.getString(R.string.attention))
.setMessage(resources.getString(R.string.message_text))
.setPositiveButton(resources.getString(R.string.give_access), ::onButtonGiveACCESS)
.setNegativeButton(resources.getString(R.string.cancel), ::onButtonCancel)
.show()
}

private fun ViewDialogSettings()
{
MaterialAlertDialogBuilder(this)
.setTitle(resources.getString(R.string.title))
.setPositiveButton(resources.getString(R.string.open_settings), ::onButtonOpenSettings)
.show()
}


override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Expand All @@ -28,17 +132,57 @@ class EditProfileActivity : AppCompatActivity() {
}
}
}

imageView.setOnClickListener {
ViewDialog()
}

editProfileButton = findViewById(R.id.button4)
editProfileButton.setOnClickListener {
launchFillUserInfo.launch()
}

}

private val launchSelectPhoto = registerForActivityResult(
ActivityResultContracts.PickVisualMedia()
) { result ->
result?.let { populateImage(it) }
}

private val launchFillUserInfo = registerForActivityResult(ProfileContract()){ userInfo ->
userInfo?.firstName?.let { findViewById<TextView>(R.id.textview_name).text = it }
userInfo?.lastName?.let { findViewById<TextView>(R.id.textview_surname).text = it }
userInfo?.age?.let { findViewById<TextView>(R.id.textview_age).text = it.toString() }
}

/**
* Используйте этот метод чтобы отобразить картинку полученную из медиатеки в ImageView
*/
private fun populateImage(uri: Uri) {
val bitmap = BitmapFactory.decodeStream(contentResolver.openInputStream(uri))
imageView.setImageBitmap(bitmap)
imageView.tag = uri
}

private fun openSenderApp() {
TODO("В качестве реализации метода отправьте неявный Intent чтобы поделиться профилем. В качестве extras передайте заполненные строки и картинку")
val intent = Intent().apply {
action = Intent.ACTION_SEND
type = "image/*"
setPackage("org.telegram.messenger")

val imgUri = imageView.tag as? Uri
if (imgUri != null) putExtra(Intent.EXTRA_STREAM, imgUri)
var firstName = findViewById<TextView>(R.id.textview_name).text

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Используйте val вместо var для переменных firstName, lastName и age, так как они не изменяются. Это соответствует best practices и делает код более безопасным.

var lastName = findViewById<TextView>(R.id.textview_surname).text
var age = findViewById<TextView>(R.id.textview_age).text

putExtra(Intent.EXTRA_TEXT,
"Имя : ${firstName}\n" +
"Фамилия : ${lastName}\n" +
"Возраст : ${age}\n")
}

runCatching {
startActivity(intent)
}
}

}
41 changes: 41 additions & 0 deletions app/src/main/java/otus/gpb/homework/activities/FillFormActivity.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package otus.gpb.homework.activities

import android.content.Intent
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat

class FillFormActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_fill_form)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}

findViewById<Button>(R.id.button)?.setOnClickListener {
val firstName = findViewById<EditText>(R.id.editFirstName).text.toString()
val lastName = findViewById<EditText>(R.id.editLastName).text.toString()
val age = findViewById<EditText>(R.id.editAge).text.toString().toIntOrNull() ?: 0

if (firstName.isNotBlank() && lastName.isNotBlank() && age > 0) {
val user = User(firstName, lastName, age)
val intent = Intent().putExtra(PROFILE_RESULT_KEY, user)
setResult(RESULT_OK, intent)
} else {
setResult(RESULT_CANCELED)
}
finish()
}
}

companion object {
const val PROFILE_RESULT_KEY = "ResultKey"
}
}
10 changes: 10 additions & 0 deletions app/src/main/java/otus/gpb/homework/activities/Profile.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package otus.gpb.homework.activities
import android.os.Parcelable
import kotlinx.parcelize.Parcelize

@Parcelize
data class User(
val firstName: String? = null,
val lastName: String? = null,
val age: Int? = null
) : Parcelable
35 changes: 35 additions & 0 deletions app/src/main/java/otus/gpb/homework/activities/ProfileContract.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package otus.gpb.homework.activities

import android.content.Context
import android.content.Intent
import androidx.activity.result.contract.ActivityResultContract
import androidx.appcompat.app.AppCompatActivity.RESULT_CANCELED
import androidx.appcompat.app.AppCompatActivity.RESULT_OK
import androidx.core.content.IntentCompat

class ProfileContract : ActivityResultContract<Unit, User?>() {

override fun createIntent(
context: Context,
input: Unit
): Intent {
return Intent(context, FillFormActivity::class.java)
}

override fun parseResult(
resultCode: Int,
intent: Intent?
): User? {
if (
intent == null
|| resultCode == RESULT_CANCELED
|| resultCode != RESULT_OK
) return null

return IntentCompat.getParcelableExtra(
intent,
FillFormActivity.PROFILE_RESULT_KEY,
User::class.java
)
}
}
59 changes: 59 additions & 0 deletions app/src/main/res/layout/activity_fill_form.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?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"
android:id="@+id/main"
tools:context=".EditProfileActivity">

<EditText
android:id="@+id/editFirstName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="100dp"
android:autofillHints="Имя"
android:ems="15"
android:hint="@string/FirstName"
android:inputType="text|textCapWords"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<EditText
android:id="@+id/editLastName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="100dp"
android:ems="15"
android:hint="@string/LastName"
android:inputType="text|textCapWords"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/editFirstName" />

<EditText
android:id="@+id/editAge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="100dp"
android:ems="15"
android:hint="@string/Age"
android:inputType="number"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/editLastName" />

<Button
android:id="@+id/button"
android:layout_width="200dp"
android:layout_height="80dp"
android:layout_marginTop="200dp"
android:text="@string/Apply"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/editAge" />
</androidx.constraintlayout.widget.ConstraintLayout>
12 changes: 12 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
<resources>
<string name="app_name">Activities</string>
<string name="title_send">Отправить</string>
<string name="title">Сделайте выбор</string>
<string name="select_photo">Выбрать фото</string>
<string name="make_photo">Сделать фото</string>
<string name="cancel">Отмена</string>
<string name="give_access">Дать доступ</string>
<string name="attention">Внимание</string>
<string name="message_text">Без доступа к камере работа программы не возможна</string>
<string name="open_settings">Открыть настройки</string>
<string name="FirstName">Имя</string>
<string name="LastName">Фамилия</string>
<string name="Age">Возраст</string>
<string name="Apply">Применить</string>
</resources>