Android – Resim Çekme ve Galeriden Resim Seçme (Kotlin)

Merhaba sevgili android geliştiricileri. Bu yazımda sizlere galeriden resim seçmeyi ve yeni resim çekip kaydetmeyi anlatacağım. Öncelikle eski android sürümleri ile yeni android sürümleri arasındaki dosya yolu farkını öğrenelim.

Android Studio – Kameradan Görüntü Alma, İşleme ve Galeriden Resim Seçme
Android Resim Çekme/Seçme
Android Resim Çekme/Seçme

FileProvider

FileProvider, bir içerik oluşturarak bir uygulama ile ilişkili dosyaların güvenli paylaşımını kolaylaştıran özel bir ContentProvider alt sınıfıdır.

Eskiden : file:///
Şimdi : content://

Bu özellik Nougat(API 24) ile geldi. Api 24 öncesi ve sonrası için ayrı kod yazıyoruz. Şimdi kodlara geçelim.

Önce Tasarım! 

Önce resim çekme, galeriden seçme butonlarımızı ve çekilen/seçilen resmin gösterileceği imageView görünümü ekleyelim. activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    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:orientation="vertical"
    tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:onClick="takePhoto"
            android:text="Resim Çek"/>

        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:onClick="chooseGallery"
            android:text="Galeriden Seç"/>

    </LinearLayout>

    <ImageView
        android:id="@+id/activity_main_imgView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="fitCenter"/>

</LinearLayout>

İzinler ve FileProvider

İzinleri bildiğimiz üzere manifest dosyasına ekliyoruz. Aynı şekilde FileProvider manifest dosyasına ekleniyor.

<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.iamkurtgoz.androidimagetakeandchooseexample">

    <uses-permission android:name="android.permission.CAMERA"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-feature android:name="android.hardware.camera"
        android:required="true" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

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

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

</manifest>

Unutmadan.. provider_paths.xml isimli bir dosya oluşturup içerisine dosya izinlerini yazmalıyız.

Dosya yolu: /app/src/main/res/xml/provider_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path
        name="external_files"
        path="." />
    <external-files-path
        name="external_files"
        path="." />
    <!-- FOR SD CARD-->
    <root-path
        name="sdcard1"
        path="." />
</paths>

Şimdi Kod Zamanı!

Kod yazarken dosya yazma, okuma ve kamera izinlerini daha hızlı kullanmak için Dexter kütüphanesini kullanacağız.

Resim Çekme:

Dexter.withActivity(this).withPermissions(Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE)
        .withListener(object: MultiplePermissionsListener{
            override fun onPermissionRationaleShouldBeShown(permissions: MutableList<PermissionRequest>?, token: PermissionToken?) {
                token?.continuePermissionRequest()
            }

            override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
                if (report == null) return
                if (report.areAllPermissionsGranted()) { //İzinler tamam ise
                    val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE) //Resim çekme intent
                    takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, getImagePath()) //Dosyayı uri olarak ekliyoruz
                    if (takePictureIntent.resolveActivity(packageManager) != null) { //Eğer resim çekmemiz için bir uygulama yoksa hata vermesin diye kontrol ediyoruz
                        startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE) //Başlatıyoruz
                    }
                }
            }
        }).check()

Galeriden Resim Seçme:

Dexter.withActivity(this).withPermissions(Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE)
        .withListener(object: MultiplePermissionsListener{
            override fun onPermissionRationaleShouldBeShown(permissions: MutableList<PermissionRequest>?, token: PermissionToken?) {
                token?.continuePermissionRequest()
            }

            override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
                if (report == null) return
                if (report.areAllPermissionsGranted()) {//İzinler tamam ise
                    val pickPhoto: Intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI) //Galeriden resim seçme intenti
                    if (pickPhoto.resolveActivity(packageManager) != null) { //Eğer resim çekmemiz için bir uygulama yoksa hata vermesin diye kontrol ediyoruz
                        startActivityForResult(pickPhoto, REQUEST_GALLERY_IMAGE) //Başlatıyoruz
                    }
                }
            }
        }).check()

onActivityResult ile seçilen/çekilen resmin sonucunu aldık ve imageViewde gösterdik

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    when(requestCode){
        REQUEST_IMAGE_CAPTURE -> {
            imgView.setImageBitmap(BitmapFactory.decodeFile(filePath))
        }
        REQUEST_GALLERY_IMAGE -> {
            val imageUri: Uri? = data?.data
            if (imageUri == null) return
            imgView.setImageURI(imageUri)
        }
    }
}

 

MainActivity.kt
import android.Manifest
import android.content.Intent
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Environment
import android.provider.MediaStore
import android.view.View
import android.widget.ImageView
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.FileProvider
import com.karumi.dexter.Dexter
import com.karumi.dexter.MultiplePermissionsReport
import com.karumi.dexter.PermissionToken
import com.karumi.dexter.listener.PermissionRequest
import com.karumi.dexter.listener.multi.MultiplePermissionsListener
import java.io.File
import java.io.IOException

class MainActivity : AppCompatActivity() {

    private val REQUEST_IMAGE_CAPTURE = 0
    private val REQUEST_GALLERY_IMAGE = 1
    private var filePath: String = ""

    private lateinit var imgView: ImageView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        imgView = findViewById(R.id.activity_main_imgView)
    }

    fun takePhoto(view: View){
        Dexter.withActivity(this).withPermissions(Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE)
                .withListener(object: MultiplePermissionsListener{
                    override fun onPermissionRationaleShouldBeShown(permissions: MutableList<PermissionRequest>?, token: PermissionToken?) {
                        token?.continuePermissionRequest()
                    }

                    override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
                        if (report == null) return
                        if (report.areAllPermissionsGranted()) { //İzinler tamam ise
                            val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE) //Resim çekme intent
                            takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, getImagePath()) //Dosyayı uri olarak ekliyorz
                            if (takePictureIntent.resolveActivity(packageManager) != null) { //Eğer resim çekmemiz için bir uygulama yoksa hata vermesin diye kontrol ediyorız
                                startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE) //Başlatıyoruz
                            }
                        }
                    }
                }).check()
    }

    fun chooseGallery(view: View){
        Dexter.withActivity(this).withPermissions(Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE)
                .withListener(object: MultiplePermissionsListener{
                    override fun onPermissionRationaleShouldBeShown(permissions: MutableList<PermissionRequest>?, token: PermissionToken?) {
                        token?.continuePermissionRequest()
                    }

                    override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
                        if (report == null) return
                        if (report.areAllPermissionsGranted()) {//İzinler tamam ise
                            val pickPhoto: Intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI) //Galeriden resim seçme intenti
                            if (pickPhoto.resolveActivity(packageManager) != null) { //Eğer resim çekmemiz için bir uygulama yoksa hata vermesin diye kontrol ediyorız
                                startActivityForResult(pickPhoto, REQUEST_GALLERY_IMAGE) //Başlatıyoruz
                            }
                        }
                    }
                }).check()
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        when(requestCode){
            REQUEST_IMAGE_CAPTURE -> {
                imgView.setImageBitmap(BitmapFactory.decodeFile(filePath))
            }
            REQUEST_GALLERY_IMAGE -> {
                val imageUri: Uri? = data?.data
                if (imageUri == null) return
                imgView.setImageURI(imageUri)
            }
        }
    }

    fun getImagePath(): Uri{
        try {
            createImageFile()  //Yeni dosyayı oluşturduk
        } catch (e: Exception) {
            e.printStackTrace()
        }
        val imageFile: File = File(filePath) //Dcim klasörüne resim dosyasını ekliyoruz

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //Nougat ve sonrası için
            return FileProvider.getUriForFile(this, applicationContext.packageName + ".provider", imageFile)
        } else {
            return Uri.fromFile(imageFile) //Öncesi için
        }
    }

    @Throws(IOException::class)
    private fun createImageFile(): File {
        val storageDir: File = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM) //Dcim klasörünün yolunu aldık
        return File.createTempFile(
            System.currentTimeMillis().toString(), /* prefix */
            ".jpg", /* suffix */
            storageDir /* directory */
        ).apply {
            // Save a file: path for use with ACTION_VIEW intents
            filePath = absolutePath
        }
    }
}

 

Şimdi kodları test edelim.

 

Android Resim Çekme/Seçme
Android Resim Çekme/Seçme
Android Resim Çekme/Seçme
Android Resim Çekme/Seçme
Android Resim Çekme/Seçme
Android Resim Çekme/Seçme

 

 

 

 

 

 

 

 

Bu yazıda android Resim Çekme ve Galeriden Seçme konusuna yer verdik. Proje kodlarına buradan ulaşabilirsiniz. Soru, görüş ve önerileriniz için lütfen yorum yapmayı unutmayın.

Photo of author

Mehmet Kurtgöz

Android Developer.

Yorum yapın