Получение файлов с другого устройства

Передача файлов Android Beam копирует файлы в отдельный каталог на принимающем устройстве. Он также сканирует скопированные файлы с помощью Анализатора Медиа-файлов Android, и добавляет записи для медиа-файлов в MediaStore . Этот урок покажет вам, как реагировать, когда копирование файла будет завершено, и, как найти скопированные файлы на принимающем устройстве.

Ответить на запрос отображения данных

Когда передача файлов Android Beam заканчивает копирование файлов на принимающем устройстве, она посылает уведомление, содержащее Intent с действием ACTION_VIEW, MIME-типом первого файла, передача которого завершилась, и URI, который указывает на первый файл. Когда пользователь нажимает на уведомление, это намерение посылается в систему. Чтобы ваше приложение могло ответить на это намерение, добавьте <intent-filter> элемент для <activity> элемента Activity , которая должна реагировать. В <intent-filter> элемент, добавьте следующие дочерние элементы:

<action android:name="android.intent.action.VIEW" />
Соответствует ACTION_VIEW намерению, отправленному уведомлением.
<category android:name="android.intent.category.CATEGORY_DEFAULT" />
Соответствует Intent , который не имеет явной категории.
<data android:mimeType="mime-type" />
Соответствует MIME-типу. Укажите только те типы, которые ваше приложение может обрабатывать.

Например, следующий фрагмент показывает, как добавить фильтр намерений, который запускает деятельность com.example.android.nfctransfer.ViewActivity:

    <activity
        android:name="com.example.android.nfctransfer.ViewActivity"
        android:label="Android Beam Viewer" >
        ...
        <intent-filter>
            <action android:name="android.intent.action.VIEW"/>
            <category android:name="android.intent.category.DEFAULT"/>
            ...
        </intent-filter>
    </activity>

Примечание: Передача файлов Android Beam не единственный источник ACTION_VIEW намерения. Другие приложения на принимающем устройстве могут также отправлять Intent с этим действием. Обработка этой ситуации обсуждается в разделе Получить каталог из URI контента.

Запросить права доступа

Чтобы прочитать файлы, которые передача файлов Android Beam копирует на устройство, запросите разрешение READ_EXTERNAL_STORAGE. Например:

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

Если вы хотите скопировать переданные файлы в собственное хранилище вашего приложения, запросите вместо этого разрешение WRITE_EXTERNAL_STORAGE . WRITE_EXTERNAL_STORAGE включает в себя READ_EXTERNAL_STORAGE.

Примечание: В Android 4.2.2 (API уровень 17), разрешение READ_EXTERNAL_STORAGE проверяется только если пользователь хочет это делать. Будущие версии платформы возможно будут требовать данное разрешение для всех случаев. Для обеспечения прямой совместимости, запросите разрешения сейчас, прежде чем оно будет требоваться.

Поскольку ваше приложение контролирует свою областью внутреннего хранилища, вы не должны просить разрешение на запись для копирования переданного файла в вашу область внутреннего хранилища.

Получить каталог со скопированными файлами

Передача файлов Android Beam копирует все файлы внутри одной передачи в один каталог на принимающем устройстве. URI в содержании Intent , присланном уведомлением передачи файлов Android Beam, указывает на первый переданный файл. Тем не менее, ваше приложение может также получить ACTION_VIEW намерение из другого источника, а не от передачи файлов Android Beam. Чтобы определить, как следует обрабатывать входящий Intent, вам необходимо проверить схему и авторитетный источник.

Чтобы получить схему для URI, вызовите Uri.getScheme(). Следующий фрагмент кода показывает, как определить схему и обработать URI соответственно:

public class MainActivity extends Activity {
    ...
    // A File object containing the path to the transferred files
    private File mParentPath;
    // Incoming Intent
    private Intent mIntent;
    ...
    /*
     * Called from onNewIntent() for a SINGLE_TOP Activity
     * or onCreate() for a new Activity. For onNewIntent(),
     * remember to call setIntent() to store the most
     * current Intent
     *
     */
    private void handleViewIntent() {
        ...
        // Get the Intent action
        mIntent = getIntent();
        String action = mIntent.getAction();
        /*
         * For ACTION_VIEW, the Activity is being asked to display data.
         * Get the URI.
         */
        if (TextUtils.equals(action, Intent.ACTION_VIEW)) {
            // Get the URI from the Intent
            Uri beamUri = mIntent.getData();
            /*
             * Test for the type of URI, by getting its scheme value
             */
            if (TextUtils.equals(beamUri.getScheme(), "file")) {
                mParentPath = handleFileUri(beamUri);
            } else if (TextUtils.equals(
                    beamUri.getScheme(), "content")) {
                mParentPath = handleContentUri(beamUri);
            }
        }
        ...
    }
    ...
}

Получить каталог из URI файла

Если входящий Intent содержит URI файла, URI содержит абсолютное имя файла, в том числе полный путь к каталогу и имя файла. Для передача файлов Android Beam, путь к каталогу указывает на расположение других передаваемых файлов, если таковые имеются. Чтобы получить путь к каталогу, получите часть URI относящуюся к пути, которая содержит весь URI, кроме file: префикса. Создайте File из это части, содержащей путь, а затем получите путь к каталогу из родительского File:

    ...
    public String handleFileUri(Uri beamUri) {
        // Get the path part of the URI
        String fileName = beamUri.getPath();
        // Create a File object for this filename
        File copiedFile = new File(fileName);
        // Get a string containing the file's parent directory
        return copiedFile.getParent();
    }
    ...

Получить каталог из URI контента

Если входящий Intent содержит URI контента, URI может указывать на каталог и имя файла, сохраненного в MediaStore поставщике контента. Вы можете определить URI контента для MediaStore путем проверки авторитетного источника данного URI. URI контента для MediaStore может прийти от передачи файлов Android Beam или из другого приложения, но в обоих случаях вы можете получить имя каталога и файла для этого URI.

Вы также можете принять входящее ACTION_VIEW намерение содержащее URI контента для другого контент-провайдера, а не только для MediaStore. В этом случае, URI контента не содержит MediaStore в имени авторитетного источника, и URI контента обычно не указывают на каталог.

Примечание: Для передачи файлов Android Beam, вы получаете URI контента в ACTION_VIEW намерении, если первый входящий файл имеет MIME-тип "audio/*", "image/*", или "video/*", указывая, что файл является медиафайлом. Передача файлов Android Beam индексирует медиафайлы, запуская Меди Анализатор для каталога, в котором он хранит передаваемые файлы. Сканер файлов записывает результаты в MediaStore контент-провайдер, а затем он передает URI контента первого файла обратно в передачу файлов Android Beam. Этот тот URI контента, который вы получите в уведомлении Intent. Для получения каталога первого файла, извлеките его из MediaStore используя URI контента.

Определить поставщика контента

Чтобы определить, можно ли получить каталог файла из содержимого URI, определите контент-провайдера, связанного с URI, вызвав Uri.getAuthority() для получения авторитетного источника. Есть два возможных значения:

MediaStore.AUTHORITY
URI для файла или файлов, отслеживаемого MediaStore. Получите полное имя файла из MediaStore, и получите каталог из имени файла.
Любое другое значение авторитетного источника
URI контента от другого провайдера контента. Отобразите данные, связанные с URI контента, но не получайте из него каталог.

Чтобы получить каталог для MediaStore URI контента, выполните запрос, который задает входящий URI контента в качестве Uri аргумента и столбец MediaColumns.DATA для отображения. Возвращенный Cursor содержит полный путь и имя файла, представленного URI. Этот путь также содержит все другие файлы, которые передача файлов Android Beam просто скопировала на устройство.

Следующий фрагмент показывает, как проверить авторитетный источник URI контента и получить путь и имя файла для перемещенного файла:

    ...
    public String handleContentUri(Uri beamUri) {
        // Position of the filename in the query Cursor
        int filenameIndex;
        // File object for the filename
        File copiedFile;
        // The filename stored in MediaStore
        String fileName;
        // Test the authority of the URI
        if (!TextUtils.equals(beamUri.getAuthority(), MediaStore.AUTHORITY)) {
            /*
             * Handle content URIs for other content providers
             */
        // For a MediaStore content URI
        } else {
            // Get the column that contains the file name
            String[] projection = { MediaStore.MediaColumns.DATA };
            Cursor pathCursor =
                    getContentResolver().query(beamUri, projection,
                    null, null, null);
            // Check for a valid cursor
            if (pathCursor != null &&
                    pathCursor.moveToFirst()) {
                // Get the column index in the Cursor
                filenameIndex = pathCursor.getColumnIndex(
                        MediaStore.MediaColumns.DATA);
                // Get the full file name including path
                fileName = pathCursor.getString(filenameIndex);
                // Create a File object for the filename
                copiedFile = new File(fileName);
                // Return the parent directory of the file
                return new File(copiedFile.getParent());
             } else {
                // The query didn't work; return null
                return null;
             }
        }
    }
    ...

Чтобы узнать больше о получении данных от поставщика информации, см. раздел Получение данных от поставщика.