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
6 changes: 4 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ plugins {
id("io.gitlab.arturbosch.detekt")
}


android {
compileSdk 34
compileSdk 36

defaultConfig {
applicationId "otus.gpb.homework.activities"
Expand Down Expand Up @@ -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'
}
Binary file added app/release/baselineProfiles/0/app-release.dm
Binary file not shown.
Binary file added app/release/baselineProfiles/1/app-release.dm
Binary file not shown.
24 changes: 22 additions & 2 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@
<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.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />

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

<activity
android:name=".EditProfileActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<activity
android:name=".FillFormActivity"
android:exported="false">
</activity>

<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
</application>

</manifest>
171 changes: 170 additions & 1 deletion app/src/main/java/otus/gpb/homework/activities/EditProfileActivity.kt
Original file line number Diff line number Diff line change
@@ -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<ImageView>(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<ImageView>(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<TextView>(R.id.textview_name).text = name
findViewById<TextView>(R.id.textview_surname).text = surname
findViewById<TextView>(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?) {
Expand All @@ -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<Button>(R.id.button4).setOnClickListener {
val intent = Intent(this, FillFormActivity::class.java)
launcherFillFormActivity.launch(intent)
}

}

/**
Expand All @@ -39,6 +162,52 @@ class EditProfileActivity : AppCompatActivity() {
}

private fun openSenderApp() {
TODO("В качестве реализации метода отправьте неявный Intent чтобы поделиться профилем. В качестве extras передайте заполненные строки и картинку")
val name = findViewById<TextView>(R.id.textview_name).text
val surname = findViewById<TextView>(R.id.textview_surname).text
val age = findViewById<TextView>(R.id.textview_age).text.toString()

val shareText = "Имя: $name\nФамилия: $surname\nВозраст: $age"
val bitmap = (imageView.drawable as? BitmapDrawable)?.bitmap

try {
val intent = Intent().apply {
action = Intent.ACTION_SEND
type = "image/*"
putExtra(Intent.EXTRA_TEXT, shareText)

// Добавляем изображение
bitmap?.let {
val imageUri = getImageUri(this@EditProfileActivity, it)
putExtra(Intent.EXTRA_STREAM, imageUri)
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
}

startActivity(Intent.createChooser(intent, "Поделиться профилем"))

} catch (e: ActivityNotFoundException) {
Toast.makeText(this, "Нет приложений для отправки", Toast.LENGTH_SHORT)
.show()
}
}

// Используем FileProvider, т.к. "MediaStore.Images.Media.insertImage" - deprecated.
private fun getImageUri(context: Context, bitmap: Bitmap): Uri {
// Создаем временный файл
val imagesDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES)
val imageFile = File.createTempFile("share_image_", ".jpg", imagesDir)

// Сохраняем bitmap в файл
FileOutputStream(imageFile).use { outputStream ->
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream)
}

// Получаем URI через FileProvider
return FileProvider.getUriForFile(
context,
"${context.packageName}.fileprovider",
imageFile
)
}

}
50 changes: 50 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,50 @@
package otus.gpb.homework.activities

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

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.button_apply).setOnClickListener {
try {
val name = findViewById<EditText>(R.id.edittext_name).text.toString()
val surname = findViewById<EditText>(R.id.edittext_surname).text.toString()
val age = findViewById<EditText>(R.id.edittext_age).text.toString().toInt()

if (name.isNotBlank() || surname.isNotBlank() || age <= 0) {
val intent = Intent()
.putExtra("name", name)
.putExtra("surname", surname)
.putExtra("age", age)
setResult(RESULT_OK, intent)
Toast.makeText(this, "Данные сохранены", Toast.LENGTH_LONG).show()
} else {
setResult(RESULT_CANCELED)
Toast.makeText(this, "Заполните все поля", Toast.LENGTH_SHORT).show()

}
} catch (e: Exception) {
setResult(RESULT_CANCELED)
}
finish()
}

}
}
20 changes: 10 additions & 10 deletions app/src/main/res/layout/activity_edit_profile.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,28 +35,28 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:hint="Имя"
android:textSize="18dp"
android:hint="@string/textview_name"
android:textSize="18sp"
app:layout_constraintStart_toEndOf="@+id/imageview_photo"
app:layout_constraintTop_toTopOf="@+id/imageview_photo" />

<TextView
android:id="@+id/textview_surname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:hint="Фамилия"
android:textSize="18dp"
android:layout_marginTop="10dp"
android:hint="@string/textview_surname"
android:textSize="18sp"
app:layout_constraintStart_toStartOf="@+id/textview_name"
app:layout_constraintTop_toBottomOf="@+id/textview_name" />

<TextView
android:id="@+id/textview_age"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:hint="Возраст"
android:textSize="18dp"
android:layout_marginTop="10dp"
android:hint="@string/textview_age"
android:textSize="18sp"
app:layout_constraintStart_toStartOf="@+id/textview_surname"
app:layout_constraintTop_toBottomOf="@+id/textview_surname" />

Expand All @@ -65,8 +65,8 @@
style="@style/Widget.MaterialComponents.Button.TextButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Редактировать профиль"
android:layout_marginTop="20dp"
android:text="@string/button_edit_profile"
app:layout_constraintStart_toStartOf="@+id/textview_age"
app:layout_constraintTop_toBottomOf="@+id/textview_age" />

Expand Down
Loading