Android Kotlin выбираем фото из галереи и рисуем в приложении | Android Studio | Kotlin ...
посмотрели 6126 раз
обновлено: 11 апреля 2024
Я написал приложение в котором есть кнопка
Load photo from Gallery и при нажатии я вызываю стандартную фунциональность чтобы выбирать фото из Галереи:
я нажмаю на кнопку Load photo from Gallery :
Система Android показывает папку с фото Я выбираю фото:
Мое приложение получает путь к фото и отображает выбранное фото:
Шаг 1. Создаем новый проект
Шаг 2. Поменяем код в файле MainActivity.kt
Цвет означает, что добавлен новый код.
Файл MainActivity.kt
package com.example.androidkotlinapp1
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import android.content.Intent
import android.content.Intent.ACTION_OPEN_DOCUMENT
import android.net.Uri
import android.widget.Button
import android.widget.ImageView
class MainActivity : AppCompatActivity() {
val MY_REQUEST_CODE1 = 100
override fun onCreate (savedInstanceState: Bundle?) {
super .onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val myButton = findViewById(R.id.button1) as Button
myButton.setOnClickListener {
val intent = Intent(ACTION_OPEN_DOCUMENT)
intent.addCategory(Intent.CATEGORY_OPENABLE)
intent.type = "*/*"
intent.putExtra(Intent.EXTRA_MIME_TYPES, arrayOf("image/*" , "video/*" ))
startActivityForResult(intent, MY_REQUEST_CODE1);
}
}
// I override system function
override fun onActivityResult (requestCode: Int, resultCode: Int, data: Intent?) {
super .onActivityResult(requestCode, resultCode, data)
if (resultCode == RESULT_OK && requestCode == MY_REQUEST_CODE1) {
val uriFilePath_to_gallery = data?.data
show_URI_in_ImageView(uriFilePath_to_gallery)
}
}
// my function for image view
fun show_URI_in_ImageView (uri: Uri?)
{
val myImageView = findViewById(R.id.imageView1) as ImageView
myImageView.setImageURI(uri)
}
}
Шаг 2. Поменяем код в файле activity_main.xml
В файл activity_main.xml добавим графические элементы:
LinearLayout
это слой в котором элементы отображаются друг за другом по вертикали или горизонтали (у меня по вертикали потому что установлен параметр android:orientation ="vertical )
ImageView
это для отображения картинки
Цвет означает, что добавлен новый код.
Xml
Файл activity_main.xml
<?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"
tools:context=".MainActivity" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:backgroundTint="#A0A000"
android:textColor="#000000"
android:text="Load photo from Gallery" />
<ImageView
android:id="@+id/imageView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:srcCompat="@tools:sample/avatars" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Объяснение
Интересно, какой путь увидим при выброре фото из галереи
При выброре фото из галереи мы увидим
uri :
content://com.android.providers.media.documents/document/image%3A16
Вопрос: Как получить путь к файлу из этого
uri ?
Ответ: Этот
uri , был сгенерирован системным
Provider . Преобразовывать
uri в путь к файлу я бы не советовал, потому что нет гарантий что всегда будет работать. Потому что на файл могут быть выделены только временные разрешения системой.
Проблема! Работать с
uri из галереи мне не очень удобно. Я когда сохраняю
uri в базу данных в проекте на работе, то потом этот
uri не всегда работает (через несколько дней) - картинка по этому
uri не отображается.
Решение:
Шаг 1. Я создаю пустой файл внутри папки моего приложения (есть функция
getExternalFilesDir в
Kotlin ).
Шаг 2. Читаю содержимое (content) из
uri галереи и сохраняю в мой пустой файл.
Шаг 3. Получаю
uri по месту нахождения моего файла
Скачать пример:
Изменения 1
Создал новый файл MyFileUtils.kt
package com.example.androidkotlinapp1
import android.content.ContentResolver
import android.content.Context
import android.net.Uri
import android.webkit.MimeTypeMap
import androidx.core.content.FileProvider
import java.io.File
import java.io.InputStream
class MyFileUtils {
fun copyUriContentToFileInsideApp (context: Context, uri: Uri, filenameWithoutExtension: String ): Uri?
{
val fileExtension = getFileExtensionFromUri (context, uri);
val folderApplication = context.getExternalFilesDir(android.os.Environment.DIRECTORY_PICTURES)
val fileDest = File(folderApplication, filenameWithoutExtension + '.' + fileExtension)
val uriDest = FileProvider.getUriForFile(
context, "${BuildConfig.APPLICATION_ID}.fileprovider " , fileDest
)
// get stream by uri
val streamSource = context.contentResolver.openInputStream(uri)
// store source stream to fileDest
if (fileDest!=null && streamSource!=null)
{
streamSource.use { input ->
fileDest.outputStream().use { output ->
input.copyTo(output)
return uriDest
}
}
}
return null
}
private fun getFileExtensionFromUri (context: Context, uri:Uri): String ? {
return if (uri.scheme == ContentResolver.SCHEME_CONTENT) {
val mime = MimeTypeMap.getSingleton()
mime.getExtensionFromMimeType(context.contentResolver.getType(uri))
} else {
MimeTypeMap.getFileExtensionFromUrl(Uri.fromFile(File(uri.path)).toString())
}
}
}
Изменения 2
Создал новый файл внутри папки:
D:\AndroidKotlinApp1
app
src
main
res
xml
Файл file_paths.xml
<?xml version="1.0" encoding="utf-8" ?>
<paths>
<external-path
name="pictures"
path="Android/data/com.example.androidkotlinapp1 /files/Pictures" />
<external-path
name="music"
path="Android/data/com.example.androidkotlinapp1 /files/Music" />
<external-path
name="docs"
path="Android/data/com.example.androidkotlinapp1 /files/Documents" />
<external-path
name="pdf"
path="." />
</paths>
Изменения 3
Файл AndroidManifest.xml
<?xml version="1.0" encoding="utf-8" ?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" >
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/Theme.AndroidKotlinApp1"
tools:targetApi="31" >
<activity
android:name=".MainActivity"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</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>
Изменения 4
Файл MainActivity.kt
package com.example.androidkotlinapp1
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.content.Intent
import android.content.Intent.ACTION_OPEN_DOCUMENT
import android.net.Uri
import android.widget.Button
import android.widget.ImageView
import androidx.core.content.ContentProviderCompat.requireContext
class MainActivity : AppCompatActivity() {
val MY_REQUEST_CODE1 = 100
override fun onCreate (savedInstanceState: Bundle?) {
super .onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val myButton = findViewById(R.id.button1) as Button
myButton.setOnClickListener {
val intent = Intent(ACTION_OPEN_DOCUMENT)
intent.addCategory(Intent.CATEGORY_OPENABLE)
intent.type = "*/*"
intent.putExtra(Intent.EXTRA_MIME_TYPES, arrayOf("image/*" , "video/*" ))
startActivityForResult(intent, MY_REQUEST_CODE1);
}
}
// I override system function
override fun onActivityResult (requestCode: Int, resultCode: Int, data: Intent?) {
super .onActivityResult(requestCode, resultCode, data)
if (resultCode == RESULT_OK && requestCode == MY_REQUEST_CODE1) {
val uriContent_selected_from_gallery = data?.data
val filenameWithoutExtension = "my_picture1"
val newUri = MyFileUtils().copyUriContentToFileInsideApp(baseContext!!, uriContent_selected_from_gallery!!, filenameWithoutExtension);
show_URI_in_ImageView(newUri)
}
}
// my function for image view
fun show_URI_in_ImageView (uriContent: Uri?)
{
val myImageView = findViewById(R.id.imageView1) as ImageView
myImageView.setImageURI(uriContent)
}
}
Запустим программу
Увидим новый uri для картинки:
content://com.example.androidkotlinapp1.fileprovider /pictures/my_picture1.jpg