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.
Konu Başlıkları
Android Studio – Kameradan Görüntü Alma, İşleme ve Galeriden Resim 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.
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.