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
4 changes: 3 additions & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id("io.gitlab.arturbosch.detekt")
id("org.jetbrains.kotlin.plugin.parcelize")
}

android {
compileSdk 34
compileSdk 36

defaultConfig {
applicationId "otus.gpb.homework.activities"
Expand Down Expand Up @@ -60,4 +61,5 @@ dependencies {
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:1.11.0'
}
10 changes: 9 additions & 1 deletion 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" />

<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
Expand All @@ -12,7 +18,9 @@
android:supportsRtl="true"
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: 151 additions & 1 deletion app/src/main/java/otus/gpb/homework/activities/EditProfileActivity.kt
Original file line number Diff line number Diff line change
@@ -1,15 +1,145 @@
package otus.gpb.homework.activities

import android.Manifest
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Bundle
import android.provider.MediaStore
import android.provider.Settings
import android.util.Log
import android.widget.Button
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.activity.result.PickVisualMediaRequest
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.result.launch
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import androidx.core.content.ContextCompat
import androidx.core.content.res.ResourcesCompat
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import java.io.ByteArrayOutputStream
import androidx.core.net.toUri

class EditProfileActivity : AppCompatActivity() {

private lateinit var imageView: ImageView
private var isSecondCameraAccessAttempt: Boolean = false

private val choosePhotoDialog
get() = MaterialAlertDialogBuilder(this)
.setItems(
arrayOf(
resources.getString(R.string.take_photo),
resources.getString(R.string.choose_photo),
)
) { d, w ->
when (w) {
0 -> {
Log.i("TAG", "Take photo")
requestCameraAccess()
if (ContextCompat.checkSelfPermission(
this,
Manifest.permission.CAMERA
) == PackageManager.PERMISSION_GRANTED
) {
takePhoto()
}
}

1 -> {
Log.i("TAG", "Choose photo")
selectPhoto()
}
}
}.create()

private val requestCameraPermissionDialog
get() = MaterialAlertDialogBuilder(this)
.setMessage("Камера нужна для создания аватара")
.setPositiveButton(resources.getString(R.string.allow_access)) { d, w ->
Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
data = Uri.fromParts("package", packageName, null)
}.let { startActivity(it) }
}
.setNegativeButton(resources.getString(R.string.cancel)) { d, w ->
Log.i("TAG", "no access")
}
.create()

private val requestCameraAccessLauncher = registerForActivityResult(
ActivityResultContracts.RequestPermission()
) { isGranted ->
when {
isGranted -> setCatToImageView()
!shouldShowRequestPermissionRationale(Manifest.permission.CAMERA) -> {
if (!isSecondCameraAccessAttempt) {
isSecondCameraAccessAttempt = true
requestCameraPermissionDialog.show()
} else {
MaterialAlertDialogBuilder(this)
.setPositiveButton(resources.getString(R.string.to_app_settings)) { d, w ->
Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
data = Uri.fromParts("package", packageName, null)
}.let { startActivity(it) }
}.show()

}
}

}
}

private fun requestCameraAccess() {
requestCameraAccessLauncher.launch(Manifest.permission.CAMERA)
}

private fun setCatToImageView() {
imageView.setImageDrawable(
ResourcesCompat.getDrawable(resources, R.drawable.cat, null)
)
}

fun getImageUriFromBitmap(context: Context, bitmap: Bitmap): Uri? {
val bytes = ByteArrayOutputStream()
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bytes) // Compress the bitmap to JPEG format
val path = MediaStore.Images.Media.insertImage(context.contentResolver, bitmap, "Image Title", null)
return path?.toUri()
}

private val takePhoneLauncher = registerForActivityResult(
ActivityResultContracts.TakePicturePreview()
) { picture ->
imageView.setImageBitmap(picture)
picture?.let {
imageView.tag = getImageUriFromBitmap(this,it)
}
}

private fun takePhoto() = takePhoneLauncher.launch()

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

private fun selectPhoto() = selectPictureLauncher.launch(
PickVisualMediaRequest(
ActivityResultContracts.PickVisualMedia.ImageOnly
)
)

private val fillUserDataLauncher = registerForActivityResult(FillFormContract()) { userInfo ->
userInfo?.name?.let { findViewById<TextView>(R.id.textview_name).text = it }
userInfo?.surName?.let { findViewById<TextView>(R.id.textview_surname).text = it }
userInfo?.age?.let { findViewById<TextView>(R.id.textview_age).text = it.toString() }
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Expand All @@ -28,6 +158,14 @@ class EditProfileActivity : AppCompatActivity() {
}
}
}

findViewById<ImageView>(R.id.imageview_photo).setOnClickListener {
choosePhotoDialog.show()
}

findViewById<Button>(R.id.button4).setOnClickListener {
fillUserDataLauncher.launch()
}
}

/**
Expand All @@ -36,9 +174,21 @@ class EditProfileActivity : AppCompatActivity() {
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(Intent.ACTION_SEND).apply {
setPackage("org.telegram.messenger")
setType("image/*")
val imgUri = imageView.tag as? Uri
if (imgUri != null) putExtra(Intent.EXTRA_STREAM, imgUri)
putExtra(Intent.EXTRA_TEXT, "Имя : ${ findViewById<TextView>(R.id.textview_name).text}\nФамилия: ${ findViewById<TextView>(R.id.textview_surname).text}\nВозраст: ${ findViewById<TextView>(R.id.textview_age).text}")
}
try {
startActivity(intent)
} catch (e: Throwable) {
Toast.makeText(this, e.message, Toast.LENGTH_LONG).show()
}
}
}
40 changes: 40 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,40 @@
package otus.gpb.homework.activities

import android.content.Intent
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import androidx.activity.enableEdgeToEdge
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)
enableEdgeToEdge()
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.appy).setOnClickListener {
UserInfo(
name = findViewById<EditText>(R.id.editName).text.toString(),
surName = findViewById<EditText>(R.id.editSurname).text.toString(),
age = findViewById<EditText>(R.id.editAge).text.toString().toIntOrNull()
).let { userInfo ->
Intent().putExtra(RESULT_KEY, userInfo).let { intent ->
setResult(RESULT_OK, intent)
finish()
}
}
}
}

companion object {
const val RESULT_KEY = "fillFormKey"
}
}
34 changes: 34 additions & 0 deletions app/src/main/java/otus/gpb/homework/activities/FillFormContract.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package otus.gpb.homework.activities

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

class FillFormContract : ActivityResultContract<Unit, UserInfo?>() {
override fun createIntent(
context: Context,
input: Unit
): Intent {
return Intent(context, FillFormActivity::class.java)
}

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

return IntentCompat.getParcelableExtra(
intent,
FillFormActivity.RESULT_KEY,
UserInfo::class.java
)

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

import android.os.Parcelable
import kotlinx.parcelize.Parcelize

@Parcelize
data class UserInfo(
val name: String? = null,
val surName: String? = null,
val age: Int? = null
) : Parcelable
60 changes: 60 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,60 @@
<?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:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".FillFormActivity">

<EditText
android:id="@+id/editName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:autofillHints="Имя"
android:hint="Иван"
android:inputType="text"
app:flow_horizontalAlign="center"
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/editSurname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:autofillHints="Фамилия"
android:hint="Иванов"
android:inputType="text"
app:flow_horizontalAlign="center"
app:layout_constraintEnd_toEndOf="@id/editName"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="@id/editName"
app:layout_constraintTop_toBottomOf="@id/editName" />

<EditText
android:id="@+id/editAge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:autofillHints="21"
android:hint="21"
android:inputType="number"
app:flow_horizontalAlign="center"
app:layout_constraintEnd_toEndOf="@id/editSurname"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="@id/editSurname"
app:layout_constraintTop_toBottomOf="@id/editSurname" />

<Button
android:id="@+id/appy"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/editAge"
android:text="Применить"
/>

</androidx.constraintlayout.widget.ConstraintLayout>
5 changes: 5 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
<resources>
<string name="app_name">Activities</string>
<string name="title_send">Отправить</string>
<string name="take_photo">Сделать фото</string>
<string name="choose_photo">Выбрать фото</string>
<string name="allow_access">Дать доступ</string>
<string name="cancel">Отмена</string>
<string name="to_app_settings">Открыть настройки</string>
</resources>
Loading