ClipData.Item.getUri aracılığıyla uygulamanın ötesinde gösterildi


109

Android dosya sistemine eklenen yeni özellikten sonra bir sorunu çözmeye çalışıyorum ancak şu hatayı alıyorum:

android.os.FileUriExposedException: file:///storage/emulated/0/MyApp/Camera_20180105_172234.jpg exposed beyond app through ClipData.Item.getUri()

Umarım birileri bunu düzeltmeme yardım edebilir :)

Teşekkürler

private Uri getTempUri() {
    // Create an image file name
    SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss");
    String dt = sdf.format(new Date());
    imageFile = null;
    imageFile = new File(Environment.getExternalStorageDirectory()
            + "/MyApp/", "Camera_" + dt + ".jpg");
    AppLog.Log(
            TAG,
            "New Camera Image Path:- "
                    + Environment.getExternalStorageDirectory()
                    + "/MyApp/" + "Camera_" + dt + ".jpg");
    File file = new File(Environment.getExternalStorageDirectory() + "/MyApp");
    if (!file.exists()) {
        file.mkdir();
    }
    imagePath = Environment.getExternalStorageDirectory() + "/MyApp/"
            + "Camera_" + dt + ".jpg";
    imageUri = Uri.fromFile(imageFile);
    return imageUri;
}

Yanıtlar:


180

Sdk 24 ve üstü için, uygulama depolamanızın dışındaki bir dosyanın URI'sini almanız gerekiyorsa bu hatayı alırsınız.
@ eranda.del çözümleri buna izin vermek için politikayı değiştirmenize izin verir ve sorunsuz çalışır.

Bununla birlikte, uygulamanızın API politikasını değiştirmek zorunda kalmadan Google yönergesini takip etmek istiyorsanız, bir FileProvider kullanmanız gerekir.

İlk önce bir dosyanın URI'sini almak için FileProvider.getUriForFile () yöntemini kullanmanız gerekir:

Uri imageUri = FileProvider.getUriForFile(
            MainActivity.this,
            "com.example.homefolder.example.provider", //(use your app signature + ".provider" )
            imageFile);

Ardından, sağlayıcınızı android bildiriminizde yapılandırmanız gerekir:

<application>
  ...
     <provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="com.example.homefolder.example.provider"
        android:exported="false"
        android:grantUriPermissions="true">
        <!-- ressource file to create -->
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths">  
        </meta-data>
    </provider>
</application>

("Yetkililerde" getUriForFile () yönteminin ikinci bağımsız değişkeniyle aynı değeri kullanın (uygulama imzası + ".provider"))

Ve son olarak, "file_paths" adlı kaynak dosyasını oluşturmanız gerekir. Bu dosyanın res / xml dizini altında oluşturulması gerekir (muhtemelen bu dizini de oluşturmanız gerekir):

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="external_files" path="." />
</paths>

88
"Geliştiricilerin hayatını kolaylaştırın" - bu her yeni API'nin sloganı, değil mi Google?
Kirill Karmazin

14
Brendon tarafından sağlanan çözüm doğru çözüm ama kopyala-yapıştır için hazır değil, örneğin ihtiyaçlarınıza uygun olup olmadığını kontrol etmeniz gerekiyor. <external-path ...Environment.getExternalStorageDirectory () istediğinizde kullanılır. ve <files-path ...Context.getFilesDir () 'e ihtiyacınız varsa kullanın . Önce resmi belgeleri kontrol
etseniz

10
Androidx (yeni destek ad alanı) kullanıyorsanız bir hatırlatma, burada ( developer.android.com/reference/androidx/core/content/… ) uygun belgeleri bulabilirsiniz.
Rodrirokr

23
androidxandroid:name="androidx.core.content.FileProvider"
İçinde şunlar

151

Kameraya veya dosyaya göz atmaya başlamadan önce aşağıdaki kod bloğunu ekleyin

    StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
    StrictMode.setVmPolicy(builder.build());

Lütfen yönlendirme bağlantısı katı moduna ve açıkladığı tüm kullanım ve teknik ayrıntılara bakın.


25
Bunu çözmenin doğru yolu bu değil, bu temelde katı mod politikalarını ortadan kaldıracak. ve güvenlik uyarısını yok sayacak
Ahsan Zaheer

Bunun bazı artıları ve eksileri var. Daha fazla bilgi almak için lütfen aşağıdakilere bakın stackoverflow.com/questions/18100161/…
eranda.del

İşe yarıyor, eğer herhangi bir çekişme olursa lütfen bana bildirin :)
Hanan

Kod benim için istisnayı çözdü. Bununla birlikte, buradaki en iyi yorum, kodun bunu çözmenin doğru yolu olmadığını söylüyor. O zaman uygun yöntemin ne olacağını bilen var mı?
Shn_Android_Dev

1
Google programcılardan nefret eder.
Joubert Vasconcelos

0

AndroidManifest için gerekli hiçbir sağlayıcı yapılandırmasına yalnızca Kamera ve Depolama izni verilmemelidir. Kamerayı başlatmak için aşağıdaki kodu kullanın:

final int REQUEST_ACTION_CAMERA = 9;
void openCamra() {
Intent cameraImgIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

cameraImgIntent.putExtra(MediaStore.EXTRA_OUTPUT,
                FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID +".provider",
                new File("your_file_name_with_dir")));
startActivityForResult(cameraImgIntent, REQUEST_ACTION_CAMERA);
}

Görüntüyü çektikten sonra, çektiğiniz görüntüyü şurada bulabilirsiniz:

"your_file_name_with_dir"

Sağlayıcının yapılandırmasını AndroidManifest'te başka bir kod vermek yerine açıklamak daha iyidir.
fury.slay

0

içine bir kod ekle

onCreate(Budle savedInstancesState){
    if (Build.VERSION.SDK_INT >= 24) {
        try {
            Method m = StrictMode.class.getMethod("disableDeathOnFileUriExposure");
            m.invoke(null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.