После того как вы настроили свое приложение для обмена файлами с использованием URI контента, вы можете отвечать на запросы других приложений об этих файлах. Один из способов ответа на эти запросы — предоставить интерфейс выбора файлов из серверного приложения, который могут вызывать другие приложения. Этот подход позволяет клиентскому приложению позволить пользователям выбирать файл из серверного приложения, а затем получать URI содержимого выбранного файла.
В этом уроке показано, как создать в приложении Activity
выбора файлов, которое отвечает на запросы файлов.
Получать запросы файлов
Чтобы получать запросы файлов от клиентских приложений и отвечать URI контента, ваше приложение должно предоставить Activity
выбора файла. Клиентские приложения запускают это Activity
, вызывая startActivityForResult()
с Intent
содержащим действие ACTION_PICK
. Когда клиентское приложение вызывает startActivityForResult()
, ваше приложение может вернуть результат клиентскому приложению в виде URI контента для файла, выбранного пользователем.
О том, как реализовать запрос файла в клиентском приложении, читайте в уроке Запрос общего файла .
Создание действия по выбору файлов
Чтобы настроить Activity
выбора файла, начните с указания Activity
в вашем манифесте вместе с фильтром намерений, соответствующим действию ACTION_PICK
и категориям CATEGORY_DEFAULT
и CATEGORY_OPENABLE
. Также добавьте фильтры типов MIME для файлов, которые ваше приложение передает другим приложениям. В следующем фрагменте показано, как указать новый фильтр Activity
и намерений:
<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>
Определите действие выбора файла в коде
Затем определите подкласс Activity
, который отображает файлы, доступные из каталога files/images/
вашего приложения во внутренней памяти, и позволяет пользователю выбрать нужный файл. В следующем фрагменте показано, как определить это Activity
и ответить на выбор пользователя:
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
*/
...
}
...
}
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
*/
...
}
...
}
Ответ на выбор файла
Как только пользователь выбирает общий файл, ваше приложение должно определить, какой файл был выбран, а затем сгенерировать URI контента для этого файла. Поскольку Activity
отображает список доступных файлов в ListView
, когда пользователь щелкает имя файла, система вызывает метод onItemClick()
, в котором вы можете получить выбранный файл.
При использовании намерения отправить URI файла из одного приложения в другое вы должны быть осторожны, чтобы получить URI, который смогут прочитать другие приложения. Выполнение этого на устройствах под управлением Android 6.0 (уровень API 23) и более поздних версий требует особой осторожности из-за изменений в модели разрешений в этой версии Android, в частности, READ_EXTERNAL_STORAGE
становится опасным разрешением , которого может не хватать принимающему приложению.
Учитывая эти соображения, мы рекомендуем избегать использования Uri.fromFile()
, которое имеет несколько недостатков. Этот метод:
- Не разрешает обмен файлами между профилями.
- Требуется, чтобы у вашего приложения было разрешение
WRITE_EXTERNAL_STORAGE
на устройствах под управлением Android 4.4 (уровень API 19) или ниже. - Требуется, чтобы принимающие приложения имели разрешение
READ_EXTERNAL_STORAGE
, которое не будет работать на важных объектах общего доступа, таких как Gmail, у которых нет такого разрешения.
Вместо использования Uri.fromFile()
вы можете использовать разрешения URI , чтобы предоставить другим приложениям доступ к определенным URI. Хотя разрешения URI не работают с file://
, созданными Uri.fromFile()
, они работают с URI, связанными с поставщиками контента. API FileProvider
может помочь вам создать такие URI. Этот подход также работает с файлами, которые находятся не во внешнем хранилище, а в локальном хранилище приложения, отправляющего намерение.
В onItemClick()
получите объект File
для имени выбранного файла и передайте его в качестве аргумента getUriForFile()
вместе с полномочиями, указанными в элементе <provider>
для FileProvider
. Результирующий URI контента содержит полномочия, сегмент пути, соответствующий каталогу файла (как указано в метаданных XML), и имя файла, включая его расширение. Как FileProvider
сопоставляет каталоги с сегментами пути на основе метаданных XML, описано в разделе «Указание общих каталогов» .
В следующем фрагменте показано, как обнаружить выбранный файл и получить для него URI содержимого:
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
}
...
}
...
}
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());
}
...
}
});
...
}
Помните, что вы можете генерировать URI контента только для файлов, которые находятся в каталоге, указанном вами в файле метаданных, содержащем элемент <paths>
, как описано в разделе «Указание общих каталогов» . Если вы вызываете getUriForFile()
для File
по пути, который вы не указали, вы получаете IllegalArgumentException
.
Предоставить разрешения для файла
Теперь, когда у вас есть URI контента для файла, которым вы хотите поделиться с другим приложением, вам нужно разрешить клиентскому приложению доступ к файлу. Чтобы разрешить доступ, предоставьте разрешения клиентскому приложению, добавив URI контента в Intent
, а затем установив флаги разрешений в Intent
. Предоставляемые вами разрешения являются временными и истекают автоматически после завершения стека задач принимающего приложения.
В следующем фрагменте кода показано, как установить разрешение на чтение для файла:
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)
...
}
...
}
...
}
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);
}
...
}
...
});
...
}
Внимание: вызов setFlags()
— единственный способ безопасно предоставить доступ к вашим файлам с использованием временных прав доступа. Избегайте вызова метода Context.grantUriPermission()
для URI содержимого файла, поскольку этот метод предоставляет доступ, который вы можете отозвать, только вызвав Context.revokeUriPermission()
.
Не используйте Uri.fromFile()
. Он заставляет получать приложения иметь разрешение READ_EXTERNAL_STORAGE
, вообще не будет работать, если вы пытаетесь поделиться информацией между пользователями, а в версиях Android ниже 4.4 (уровень API 19) вашему приложению потребуется WRITE_EXTERNAL_STORAGE
. А действительно важные цели общего доступа, такие как приложение Gmail, не имеют READ_EXTERNAL_STORAGE
, что приводит к сбою этого вызова. Вместо этого вы можете использовать разрешения URI, чтобы предоставить другим приложениям доступ к определенным URI. Хотя разрешения URI не работают с URI file://, генерируемыми Uri.fromFile()
, они работают с URI, связанными с поставщиками контента. Вместо того, чтобы реализовывать свой собственный только для этого, вы можете и должны использовать FileProvider
, как описано в разделе «Общий доступ к файлам» .
Поделитесь файлом с запрашивающим приложением
Чтобы поделиться файлом с приложением, которое его запросило, передайте Intent
, содержащий URI контента и разрешения, в setResult()
. Когда Activity
которое вы только что определили, завершено, система отправляет Intent
, содержащее URI контента, клиентскому приложению. Следующий фрагмент кода показывает, как это сделать:
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)
}
}
}
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);
}
}
});
Предоставьте пользователям возможность немедленно вернуться в клиентское приложение после выбора файла. Один из способов сделать это — поставить галочку или кнопку «Готово» . Свяжите метод с кнопкой, используя атрибут кнопки android:onClick
. В методе вызовите finish()
. Например:
fun onDoneClick(v: View) {
// Associate a method with the Done button
finish()
}
public void onDoneClick(View v) {
// Associate a method with the Done button
finish();
}
Для получения дополнительной информации см.:
- Проектирование URI контента
- Реализация разрешений поставщика контента
- Разрешения
- Намерения и фильтры намерений
После того как вы настроили свое приложение для обмена файлами с использованием URI контента, вы можете отвечать на запросы других приложений об этих файлах. Один из способов ответа на эти запросы — предоставить интерфейс выбора файлов из серверного приложения, который могут вызывать другие приложения. Этот подход позволяет клиентскому приложению разрешить пользователям выбирать файл из серверного приложения, а затем получать URI содержимого выбранного файла.
В этом уроке показано, как создать в приложении Activity
выбора файлов, которое отвечает на запросы файлов.
Получать запросы файлов
Чтобы получать запросы файлов от клиентских приложений и отвечать URI контента, ваше приложение должно предоставить Activity
выбора файла. Клиентские приложения запускают это Activity
, вызывая startActivityForResult()
с Intent
содержащим действие ACTION_PICK
. Когда клиентское приложение вызывает startActivityForResult()
, ваше приложение может вернуть результат клиентскому приложению в виде URI контента для файла, выбранного пользователем.
О том, как реализовать запрос файла в клиентском приложении, читайте в уроке Запрос общего файла .
Создание действия по выбору файлов
Чтобы настроить Activity
выбора файла, начните с указания Activity
в вашем манифесте вместе с фильтром намерений, соответствующим действию ACTION_PICK
и категориям CATEGORY_DEFAULT
и CATEGORY_OPENABLE
. Также добавьте фильтры типов MIME для файлов, которые ваше приложение передает другим приложениям. В следующем фрагменте показано, как указать новый фильтр Activity
и намерений:
<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>
Определить действие выбора файла в коде
Затем определите подкласс Activity
, который отображает файлы, доступные из каталога files/images/
вашего приложения во внутренней памяти, и позволяет пользователю выбрать нужный файл. В следующем фрагменте показано, как определить это Activity
и ответить на выбор пользователя:
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
*/
...
}
...
}
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
*/
...
}
...
}
Ответ на выбор файла
Как только пользователь выбирает общий файл, ваше приложение должно определить, какой файл был выбран, а затем сгенерировать URI контента для этого файла. Поскольку Activity
отображает список доступных файлов в ListView
, когда пользователь щелкает имя файла, система вызывает метод onItemClick()
, в котором вы можете получить выбранный файл.
При использовании намерения отправить URI файла из одного приложения в другое вы должны быть осторожны, чтобы получить URI, который смогут прочитать другие приложения. Выполнение этого на устройствах под управлением Android 6.0 (уровень API 23) и более поздних версий требует особой осторожности из-за изменений в модели разрешений в этой версии Android, в частности, READ_EXTERNAL_STORAGE
становится опасным разрешением , которого может не хватать принимающему приложению.
Учитывая эти соображения, мы рекомендуем избегать использования Uri.fromFile()
, которое имеет несколько недостатков. Этот метод:
- Не разрешает обмен файлами между профилями.
- Требуется, чтобы у вашего приложения было разрешение
WRITE_EXTERNAL_STORAGE
на устройствах под управлением Android 4.4 (уровень API 19) или ниже. - Требуется, чтобы принимающие приложения имели разрешение
READ_EXTERNAL_STORAGE
, которое не будет работать на важных объектах общего доступа, таких как Gmail, у которых нет такого разрешения.
Вместо использования Uri.fromFile()
вы можете использовать разрешения URI , чтобы предоставить другим приложениям доступ к определенным URI. Хотя разрешения URI не работают с file://
, созданными Uri.fromFile()
, они работают с URI, связанными с поставщиками контента. API FileProvider
может помочь вам создать такие URI. Этот подход также работает с файлами, которые находятся не во внешнем хранилище, а в локальном хранилище приложения, отправляющего намерение.
В onItemClick()
получите объект File
для имени выбранного файла и передайте его в качестве аргумента getUriForFile()
вместе с полномочиями, указанными в элементе <provider>
для FileProvider
. Результирующий URI контента содержит полномочия, сегмент пути, соответствующий каталогу файла (как указано в метаданных XML), и имя файла, включая его расширение. Как FileProvider
сопоставляет каталоги с сегментами пути на основе метаданных XML, описано в разделе «Указание общих каталогов» .
В следующем фрагменте показано, как обнаружить выбранный файл и получить для него URI содержимого:
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
}
...
}
...
}
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());
}
...
}
});
...
}
Помните, что вы можете генерировать URI контента только для файлов, которые находятся в каталоге, указанном вами в файле метаданных, содержащем элемент <paths>
, как описано в разделе «Указание общих каталогов» . Если вы вызываете getUriForFile()
для File
по пути, который вы не указали, вы получаете IllegalArgumentException
.
Предоставить разрешения для файла
Теперь, когда у вас есть URI контента для файла, которым вы хотите поделиться с другим приложением, вам нужно разрешить клиентскому приложению доступ к файлу. Чтобы разрешить доступ, предоставьте разрешения клиентскому приложению, добавив URI контента в Intent
, а затем установив флаги разрешений в Intent
. Предоставляемые вами разрешения являются временными и истекают автоматически после завершения стека задач принимающего приложения.
В следующем фрагменте кода показано, как установить разрешение на чтение для файла:
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)
...
}
...
}
...
}
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);
}
...
}
...
});
...
}
Внимание: вызов setFlags()
— единственный способ безопасно предоставить доступ к вашим файлам с использованием временных прав доступа. Избегайте вызова метода Context.grantUriPermission()
для URI содержимого файла, поскольку этот метод предоставляет доступ, который вы можете отозвать только путем вызова Context.revokeUriPermission()
.
Не используйте Uri.fromFile()
. Он заставляет получать приложения иметь разрешение READ_EXTERNAL_STORAGE
, вообще не будет работать, если вы пытаетесь поделиться информацией между пользователями, а в версиях Android ниже 4.4 (уровень API 19) вашему приложению потребуется WRITE_EXTERNAL_STORAGE
. А действительно важные цели общего доступа, такие как приложение Gmail, не имеют READ_EXTERNAL_STORAGE
, что приводит к сбою этого вызова. Вместо этого вы можете использовать разрешения URI, чтобы предоставить другим приложениям доступ к определенным URI. Хотя разрешения URI не работают с URI file://, генерируемыми Uri.fromFile()
, они работают с URI, связанными с поставщиками контента. Вместо того, чтобы реализовывать свой собственный только для этого, вы можете и должны использовать FileProvider
, как описано в разделе «Общий доступ к файлам» .
Поделитесь файлом с запрашивающим приложением
Чтобы поделиться файлом с приложением, которое его запросило, передайте Intent
, содержащий URI контента и разрешения, в setResult()
. Когда Activity
которое вы только что определили, завершено, система отправляет Intent
, содержащее URI контента, клиентскому приложению. Следующий фрагмент кода показывает, как это сделать:
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)
}
}
}
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);
}
}
});
Предоставьте пользователям возможность немедленно вернуться в клиентское приложение после выбора файла. Один из способов сделать это — поставить галочку или кнопку «Готово» . Свяжите метод с кнопкой, используя атрибут кнопки android:onClick
. В методе вызовите finish()
. Например:
fun onDoneClick(v: View) {
// Associate a method with the Done button
finish()
}
public void onDoneClick(View v) {
// Associate a method with the Done button
finish();
}
Для получения дополнительной информации см.:
- Проектирование URI контента
- Реализация разрешений поставщика контента
- Разрешения
- Намерения и фильтры намерений