Uygulamanızı içerik URI'leri kullanarak dosya paylaşacak şekilde ayarladıktan sonra, diğer uygulamaların bu dosyalar için istek gönderebilir. Bu isteklere yanıt vermenin bir yolu da diğer uygulamaların çağırabileceği sunucu uygulamasından gelen bir arayüz oluşturur. Bu yaklaşım sayesinde kullanıcıların sunucu uygulamasından bir dosya seçmelerini ve daha sonra seçilen dosyanın içerik URI'si.
    Bu derste, uygulamanızda dosya seçimi (Activity) nasıl oluşturulacağı açıklanmaktadır.
    yanıt veren bir reklam öğesi ekler.
Dosya istekleri alma
    İstemci uygulamalarından dosya istekleri almak ve içerik URI'si ile yanıt vermek için uygulamanız
    bir dosya seçimi Activity sağlayın. İstemci uygulamaları bunu başlatır
    İşlemi içeren bir Intent ile startActivityForResult() çağrısı yaparak Activity
    ACTION_PICK. İstemci uygulaması aradığında
    startActivityForResult(), uygulamanız şunları yapabilir:
    istemci uygulamasına, kullanıcının seçtiği dosya için içerik URI'si biçiminde bir sonuç döndürür.
İstemci uygulamasında bir dosya isteğini nasıl uygulayacağınızı öğrenmek için Paylaşılan dosya isteğinde bulunma.
Dosya seçimi etkinliği oluşturma
    Activity dosya seçimini ayarlamak için öncelikle
    Manifest'inizde Activity ile birlikte bir intent filtresi
    ACTION_PICK ve
    CATEGORY_DEFAULT ve
    CATEGORY_OPENABLE.  MIME türü filtreleri de ekle
    diğer uygulamalara sunduğu dosyalar için Google Etiket Yöneticisi'ni kullanabilirsiniz. Aşağıdaki snippet,
    yeni Activity ve intent filtresi:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> ... <application> ... <activity android:name=".FileSelectActivity" android:label="@File Selector" > <intent-filter> <action android:name="android.intent.action.PICK"/> <category android:name="android.intent.category.DEFAULT"/> <category android:name="android.intent.category.OPENABLE"/> <data android:mimeType="text/plain"/> <data android:mimeType="image/*"/> </intent-filter> </activity>
Kodda dosya seçimi etkinliğini tanımlama
    Sonra, mevcut dosyaları gösteren bir Activity alt sınıfı tanımlayın
    dahili depolama alanındaki files/images/ dizinini destekler ve kullanıcının
    seçin. Aşağıdaki snippet, bunun nasıl tanımlanacağını gösterir
    Activity ve kullanıcının seçimine yanıt verin:
Kotlin
class MainActivity : Activity() { // The path to the root of this app's internal storage private lateinit var privateRootDir: File // The path to the "images" subdirectory private lateinit var imagesDir: File // Array of files in the images subdirectory private lateinit var imageFiles: Array<File> // Array of filenames corresponding to imageFiles private lateinit var imageFilenames: Array<String> // Initialize the Activity override fun onCreate(savedInstanceState: Bundle?) { ... // Set up an Intent to send back to apps that request a file resultIntent = Intent("com.example.myapp.ACTION_RETURN_FILE") // Get the files/ subdirectory of internal storage privateRootDir = filesDir // Get the files/images subdirectory; imagesDir = File(privateRootDir, "images") // Get the files in the images subdirectory imageFiles = imagesDir.listFiles() // Set the Activity's result to null to begin with setResult(Activity.RESULT_CANCELED, null) /* * Display the file names in the ListView fileListView. * Back the ListView with the array imageFilenames, which * you can create by iterating through imageFiles and * calling File.getAbsolutePath() for each File */ ... } ... }
Java
public class MainActivity extends Activity { // The path to the root of this app's internal storage private File privateRootDir; // The path to the "images" subdirectory private File imagesDir; // Array of files in the images subdirectory File[] imageFiles; // Array of filenames corresponding to imageFiles String[] imageFilenames; // Initialize the Activity @Override protected void onCreate(Bundle savedInstanceState) { ... // Set up an Intent to send back to apps that request a file resultIntent = new Intent("com.example.myapp.ACTION_RETURN_FILE"); // Get the files/ subdirectory of internal storage privateRootDir = getFilesDir(); // Get the files/images subdirectory; imagesDir = new File(privateRootDir, "images"); // Get the files in the images subdirectory imageFiles = imagesDir.listFiles(); // Set the Activity's result to null to begin with setResult(Activity.RESULT_CANCELED, null); /* * Display the file names in the ListView fileListView. * Back the ListView with the array imageFilenames, which * you can create by iterating through imageFiles and * calling File.getAbsolutePath() for each File */ ... } ... }
Dosya seçimine yanıt verme
    Uygulamanız, paylaşılan bir dosyayı seçtiğinde hangi dosyanın seçildiğini belirlemeli ve
    daha sonra dosya için bir içerik URI'si oluşturabilirsiniz. Activity,
    Kullanıcı bir dosya adını tıkladığında ListView içindeki kullanılabilir dosyaların listesi
    sistem, seçili dosyayı alabileceğiniz onItemClick() yöntemini çağırır.
Bir dosyanın URI'sini bir uygulamadan diğerine göndermek için bir intent kullanırken
başka birinin kullandığı URI'ları alırken
okuyabiliyor. Android 6.0 (API düzeyi 23) ve sonraki sürümleri çalıştıran cihazlarda bunu yapma
özel
Android'in bu sürümünde izin modelinde yapılan değişiklikler nedeniyle,
READ_EXTERNAL_STORAGE
olmak
tehlikeli izni kapsayan bir açık kaynak belirtin.
Bu noktaları göz önünde bulundurarak,
Uri.fromFile(),
bazı dezavantajlar içerir. Bu yöntem:
- Profiller arasında dosya paylaşımına izin vermez.
- Uygulamanızda
WRITE_EXTERNAL_STORAGE. izni.
- Alıcı uygulamaların
READ_EXTERNAL_STORAGEizni. Bu, Gmail gibi bu izne sahip olmayan önemli paylaşım hedeflerinde başarısız olur.
Uri.fromFile() yerine
diğer uygulamalara izin vermek için URI izinlerini kullanabilirsiniz
belirli URI'lere erişim. file:// URI'lerinde URI izinleri çalışmasa da
Uri.fromFile() tarafından oluşturulan
İçerik Sağlayıcılarla ilişkili URI'lar üzerinde çalışır. İlgili içeriği oluşturmak için kullanılan
FileProvider API şunları yapabilir:
bu tür URI'ler oluşturmanıza yardımcı olur. Bu yaklaşım,
bunu harici depolamada ancak niyeti gönderen uygulamanın yerel depolama alanında bulabilirsiniz.
    onItemClick() uygulamasında bir
    File nesnesini ayarlayın ve bunu bağımsız değişken olarak
    getUriForFile() ve
    ilgili yetki belgesinde belirttiğiniz
    FileProvider için <provider> öğesi.
    Sonuçta ortaya çıkan içerik URI'si; yetkiliyi, yani dosyanın
    dizinini (XML meta verilerinde belirtildiği şekliyle) ve
    uzantısına sahip olur. FileProvider, dizinleri yola nasıl eşler?
    XML meta verilerine dayalı segmentler başlıklı bölümde açıklanmıştır
    Paylaşılabilir dizinleri belirtin.
Aşağıdaki snippet, seçilen dosyanın nasıl algılanacağını ve dosya için içerik URI'sinin nasıl alınacağını gösterir:
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { ... // Define a listener that responds to clicks on a file in the ListView fileListView.onItemClickListener = AdapterView.OnItemClickListener { _, _, position, _ -> /* * Get a File for the selected file name. * Assume that the file names are in the * imageFilename array. */ val requestFile = File(imageFilenames[position]) /* * Most file-related method calls need to be in * try-catch blocks. */ // Use the FileProvider to get a content URI val fileUri: Uri? = try { FileProvider.getUriForFile( this@MainActivity, "com.example.myapp.fileprovider", requestFile) } catch (e: IllegalArgumentException) { Log.e("File Selector", "The selected file can't be shared: $requestFile") null } ... } ... }
Java
protected void onCreate(Bundle savedInstanceState) { ... // Define a listener that responds to clicks on a file in the ListView fileListView.setOnItemClickListener( new AdapterView.OnItemClickListener() { @Override /* * When a filename in the ListView is clicked, get its * content URI and send it to the requesting app */ public void onItemClick(AdapterView<?> adapterView, View view, int position, long rowId) { /* * Get a File for the selected file name. * Assume that the file names are in the * imageFilename array. */ File requestFile = new File(imageFilename[position]); /* * Most file-related method calls need to be in * try-catch blocks. */ // Use the FileProvider to get a content URI try { fileUri = FileProvider.getUriForFile( MainActivity.this, "com.example.myapp.fileprovider", requestFile); } catch (IllegalArgumentException e) { Log.e("File Selector", "The selected file can't be shared: " + requestFile.toString()); } ... } }); ... }
    Yalnızca dizinde bulunan dosyalar için içerik URI'leri oluşturabileceğinizi unutmayın.
    <paths> öğesini içeren meta veri dosyasında belirttiğiniz
    Paylaşılabilir dizinleri belirtme bölümünde açıklanmıştır. Arama yaptığınızda
    Şunun için getUriForFile():
    File belirtirken belirtmediğiniz bir yolda
    IllegalArgumentException.
Dosya için gerekli izinleri verme
    Artık başka bir uygulamayla paylaşmak istediğiniz dosyanın İçerik URI'sına sahip olduğunuza göre
    istemci uygulamasının dosyaya erişmesine izin vermelidir. Erişime izin vermek için aşağıdaki adımları uygulayarak istemci uygulamasına izin verin:
    içerik URI'sini bir Intent öğesine eklemek ve ardından
    Intent. Verdiğiniz izinler geçicidir ve süresi dolar.
    ve alıcı uygulamanın görev yığını tamamlandığında otomatik olarak oluşturulur.
Aşağıdaki kod snippet'i, dosya için okuma izninin nasıl ayarlanacağını gösterir:
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { ... // Define a listener that responds to clicks on a file in the ListView fileListView.onItemClickListener = AdapterView.OnItemClickListener { _, _, position, _ -> ... if (fileUri != null) { // Grant temporary read permission to the content URI resultIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) ... } ... } ... }
Java
protected void onCreate(Bundle savedInstanceState) { ... // Define a listener that responds to clicks in the ListView fileListView.setOnItemClickListener( new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapterView, View view, int position, long rowId) { ... if (fileUri != null) { // Grant temporary read permission to the content URI resultIntent.addFlags( Intent.FLAG_GRANT_READ_URI_PERMISSION); } ... } ... }); ... }
    Dikkat: Tek yapmanız gereken setFlags() numaralı telefonu aramak
    Bu da, geçici erişim izinlerini kullanarak dosyalarınıza güvenli bir şekilde erişim izni vermenin bir yoludur. Telefon etmekten kaçının
    Context.grantUriPermission() yöntem için
    dosyanın içerik URI'sini kullanın, çünkü bu yöntem yalnızca
    Context.revokeUriPermission() aranıyor.
Uri.fromFile() kullanmayın. Uygulamaları almayı zorunlu kılar
READ_EXTERNAL_STORAGE iznini almak için
kullanıcılar arasında ve farklı sürümlerde hiç çalışmayacaktır
Android 4.4'ten (API düzeyi 19) düşük bir sürüme sahip olmak için
uygulamanın WRITE_EXTERNAL_STORAGE olmasını sağlayın.
Gmail uygulaması gibi gerçekten önemli paylaşım hedeflerinde,
READ_EXTERNAL_STORAGE nedeniyle
çağrının başarısız olmasına neden olabilir.
Bunun yerine, diğer uygulamaların belirli URI'lere erişmesine izin vermek için URI izinlerini kullanabilirsiniz.
URI izinleri,
Uri.fromFile(), öyle
İçerik Sağlayıcılarla ilişkili Uris'te çalışma. Sırf bu amaçla kendi uygulamanızı uygulamak yerine,
FileProvider kullanabilirsiniz ve kullanmanız gerekir
Dosya paylaşımı bölümünde açıklandığı gibi.
Dosyayı, istekte bulunan uygulamayla paylaşın
    Dosyayı isteyen uygulamayla paylaşmak için Intent
    hem de içerik URI'sini ve setResult() izinlerini içerir. Tanımladığınız Activity tamamlandığında,
    sistem, içerik URI'sini içeren Intent öğesini istemci uygulamasına gönderir.
    Aşağıdaki kod snippet'inde bunu nasıl yapacağınız gösterilmektedir:
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { ... // Define a listener that responds to clicks on a file in the ListView fileListView.onItemClickListener = AdapterView.OnItemClickListener { _, _, position, _ -> ... if (fileUri != null) { ... // Put the Uri and MIME type in the result Intent resultIntent.setDataAndType(fileUri, contentResolver.getType(fileUri)) // Set the result setResult(Activity.RESULT_OK, resultIntent) } else { resultIntent.setDataAndType(null, "") setResult(RESULT_CANCELED, resultIntent) } } }
Java
protected void onCreate(Bundle savedInstanceState) { ... // Define a listener that responds to clicks on a file in the ListView fileListView.setOnItemClickListener( new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapterView, View view, int position, long rowId) { ... if (fileUri != null) { ... // Put the Uri and MIME type in the result Intent resultIntent.setDataAndType( fileUri, getContentResolver().getType(fileUri)); // Set the result MainActivity.this.setResult(Activity.RESULT_OK, resultIntent); } else { resultIntent.setDataAndType(null, ""); MainActivity.this.setResult(RESULT_CANCELED, resultIntent); } } });
    Kullanıcılara, dosya seçtiklerinde istemci uygulamasına hemen geri dönebilecekleri bir yol sunun.
    Bunu yapmanın bir yolu, onay işareti veya Bitti düğmesi sağlamaktır. Şununla bir yöntem ilişkilendir:
    düğmenin
    android:onClick özelliği için de kullanılmaktadır. Yöntemde
    finish() Örnek:
Kotlin
fun onDoneClick(v: View) { // Associate a method with the Done button finish() }
Java
public void onDoneClick(View v) { // Associate a method with the Done button finish(); }
Daha fazla ilgili bilgi için aşağıdaki kaynakları inceleyebilirsiniz:
