25 Ocak 2018 Perşembe

Android Nougat Sürümünde Uygulamalar Arası Dosya Paylaşırken Karşılaşılan Sorun ve Çözümü

Android 7.0 Nougat, güvenliği arttırmak için  dosya sistemi için izin değişikliği getirdi. Uygulamanızda Hedef Sdk versiyonu 24 ve sonrası için intent yoluyla paket alanınızın dışındaki bir uygulamaya dosya Uri iletiyorsanız çökme yaşanır. FileUriExposedException ile karşılaşılır. Çalışma zamanı denetimi uygulamanın devam etmesine izin vermez.


Örneğin; uygulama içindeki bir dosyayı pdf okuyucuya göndermek için Android 7 öncesi sürümlerde şu kod bloğu sorunsuz çalışmaktaydı:


/** * path'i verilen pdf dosyasını cihazda bulunan pdf görüntüleyicisinde açar */

public static void pdfDosyasiniOkuyucudaAc(String dosyaPath) {

    File pdfFile = new File(dosyaPath);

    Uri path = Uri.fromFile(pdfFile);

    Intent pdfIntent = new Intent(Intent.ACTION_VIEW);

    pdfIntent.setDataAndType(path, "application/pdf");

    pdfIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

    getActivity().startActivity(pdfIntent);

}

 Bu sorunu aşmak için iki yöntem vardır. İlki şöyledir:

FileProvider kullanmak :

1.AndroidMAnifest.xml dosyasına şunu ekliyoruz :

<manifest>
<application>
<provider
android:name="android.support.v4.content.FileProvider"android:authorities="@string/file_provider_authority"
android:exported="false"
android:grantUriPermissions="true"><meta-data
android:name="android.support.FILE_PROVIDER_PATHS"android:resource="@xml/file_provider_paths" />
</provider>
</application>
</manifest>

2. Bu içerik sağlayıcı bu sorunu aşmamızı sağlayacaktır. Fakat FileProvider benzersiz olmalıdır. Bu yüzden uygulama id ile şu şekilde yazıyoruz ;

<string name="file_provider_authority"translatable="false">com.deneme.fileproviderexample.fileprovider</string>

3.Ardından res/xml klasöründe file_provider_path oluşturmamız gerekiyor. Güvenli şekilde paylaşıma izin verilecek dosyaları içeren klasörleri tanımlayan dosya budur:

<?xml version="1.0" encoding="UTF-8"?> <paths> <external-path name="external_files" path="." /> </paths>

ve son olarak ilk önce yazdığımız kodda şu şekilde değişiklik yapıyoruz : 

public static void pdfDosyasiniOkuyucudaAc(String dosyaPath) {
    File pdfFile = new File(dosyaPath);
    Uri path = FileProvider.getUriForFile(getActivity(), getString(R.string.file_provider_authority), pdfFile);
    Intent pdfIntent = new Intent(Intent.ACTION_VIEW);
    pdfIntent.setDataAndType(path, "application/pdf");
    pdfIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    getActivity().startActivity(pdfIntent);

}


İkinci yöntem ise çalışma zamanında denetimi geçersiz kılmaktır.

public static void pdfDosyasiniOkuyucudaAc(String dosyaPath) {
    File pdfFile = new File(dosyaPath);
    Uri path = Uri.fromFile(pdfFile);
    Intent pdfIntent = new Intent(Intent.ACTION_VIEW);
    pdfIntent.setDataAndType(path, "application/pdf");
    pdfIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    try {
        if (Build.VERSION.SDK_INT >= 24) {
            try {
                Method m = StrictMode.class.getMethod("disableDeathOnFileUriExposure");
                m.invoke(null);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        ExtActivity.currentActivity.startActivity(pdfIntent);
    } catch (ActivityNotFoundException e) {
        EkranFayda.customToastGoster("Cihazınızda PDF görüntüleyici bulunamadı.",
            UYARI_TIPI.ERROR);
    }
}

Hiç yorum yok:

Yorum Gönder