Файл Android Jam Beam

У меня есть простое действие, которое запускает средство выбора файлов, а затем отправляет файл через Android луч, например:

@Override
protected void onActivityResult(int requestCode, int resultCode,
                                Intent data) {
    if (requestCode==0 && resultCode==RESULT_OK) {
        adapter.setBeamPushUris(new Uri[] {data.getData()}, this);
        Button btn=new Button(this);
        btn.setText("Done");
        btn.setOnClickListener(this);
        setContentView(btn);
    }
}

Деятельность может правильно передавать изображения и файлы.txt. Тем не менее, я получаю "Beam не завершен", когда я посылаю файлы.json.

Я думал, что это потому, что на приемнике нет приложения, которое просматривает файлы json, поэтому я создал другую версию для просмотра полученных текстовых файлов. Манифест имеет

<intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <data android:mimeType="text/*" />
</intent-filter>

Когда я изменяю расширение моих файлов json на.txt, файл отправляется правильно, и приложение-получатель запускается. Но когда я изменяю расширение обратно на.json, а mimetype получателя на "application / json", я все равно получаю сообщение "Beam not complete".

Есть идеи почему?

Спасибо!

1 ответ

Решение

Есть идеи почему?

Android Beam использует расширение первого файла в Beam Uri s массив для поиска соответствующего типа MIME на внутренней карте, которая затем отправляется с Intent который инициирует передачу файла через Bluetooth Object Push Profile (OPP).

Если расширение файла или соответствующий тип MIME не найдены, Intent тип MIME установлен в null и передача файла Bluetooth OPP вообще не инициируется.

Временное решение

При отправке файла с расширением, которое не указано в MimeUtils, используйте двухэлементный луч Uri массив s:

uris[0]: фиктивный текстовый файл с .txt расширение, (будет удалено позже)
uris[1]: файл (с нераспознанным расширением), который вы хотите передать

В вашем конкретном случае:

        adapter.setBeamPushUris(
                new Uri[] { dummyTxtFileUri, data.getData() },
                this);

Android Beam отправит сообщение о намерении Bluetooth с типом MIME text/plain, вместе с Uri s для обоих файлов, и передача файлов Bluetooth OPP будет происходить нормально. Обратите внимание, что при одновременной передаче нескольких файлов принимающее устройство будет сохранять файлы в подкаталоге в beam/ обычно называется beam-YYYY-MM-DD/,

ФОН

Я сравнил журналы на отправляющем устройстве между отправкой файла с .json расширение, и копия этого файла с .txt расширение. Первое заметное отличие здесь:

журнал: сияющий test.json

03-02 13:19:34.665: D/BluetoothOppHandover(32332): Handing off outging transfer to BT

журнал: сияющий test.txt

03-02 15:32:19.437: D/BluetoothOppHandover(3268): Handing off outging transfer to BT
03-02 15:32:19.445: D/BluetoothOppUtility(3309): putSendFileInfo: uri=file:///storage/emulated/0/Download/test.txt@2cb672fa sendFileInfo=com.android.bluetooth.opp.BluetoothOppSendFileInfo@2cb672fa

Поиск AOSP для "Передача передачи исходящих данных в BT":

Платформа / пакеты / приложения / Nfc / SRC / COM / Android / НФК / передачи / BluetoothOppHandover.java

void sendIntent() {
    Intent intent = new Intent();
    intent.setPackage("com.android.bluetooth");
    String mimeType = MimeTypeUtil.getMimeTypeForUri(mContext, mUris[0]);
    intent.setType(mimeType);
    // ...
    if (DBG) Log.d(TAG, "Handing off outging transfer to BT");
    mContext.sendBroadcast(intent);

    complete();
}

Прежде чем двигаться дальше, обратите внимание, что MIME-тип только для первого Uri в массиве отправляется в Intent, Следующий MimeTypeUtil.getMimeTypeForUri():

Платформа / пакеты / приложения / Nfc / SRC / COM / Android / НФК / передачи / MimeTypeUtil.java

    public static String getMimeTypeForUri(Context context, Uri uri) {
        // ...
            String extension = MimeTypeMap.getFileExtensionFromUrl(uri.getPath()).toLowerCase();
            if (extension != null) {
                return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
            } else {
                return null;
            }
        // ...

Так что, если он не идентифицирует расширение, он возвращает null как тип MIME. Следующий MimeTypeMap.getSingleton().getMimeTypeFromExtension()...

рамки / база / ядро / Java / Android / WebKit / MimeTypeMap.java

    public String getMimeTypeFromExtension(String extension) {
        return MimeUtils.guessMimeTypeFromExtension(extension);
    }

Платформа / libcore / лунно / SRC / главная / Java / libcore / сеть / MimeUtils.java

public final class MimeUtils {
    private static final Map<String, String> mimeTypeToExtensionMap = new HashMap<String, String>();

    private static final Map<String, String> extensionToMimeTypeMap = new HashMap<String, String>();

    // ...

    public static String guessMimeTypeFromExtension(String extension) {
        if (extension == null || extension.isEmpty()) {
            return null;
        }
        return extensionToMimeTypeMap.get(extension);
    }

Прежде чем двигаться дальше, обратите внимание, что это MimeUtils класс содержит список типов MIME, которые распознаются Android. Это хорошая ссылка.

Мы достигли конца стека с extensionToMimeTypeMap.get():

Платформа / libcore / лунно / SRC / главная / Java / Java / Util / HashMap.java

    /**
     * Returns the value of the mapping with the specified key.
     *
     * @param key
     *            the key.
     * @return the value of the mapping with the specified key, or {@code null}
     *         if no mapping for the specified key is found.
    */
    public V get(Object key) {

Таким образом, если совпадение не найдено, тип MIME в конечном итоге возвращается как null, Еще немного копаний показывает, где это важно:

Платформа / пакеты / приложения / Bluetooth / SRC / COM / Android / Bluetooth / ОПП / BluetoothOppHandoverReceiver.java

    @Override
    public void onReceive(Context context, Intent intent) {
        // ...
        if (action.equals(Constants.ACTION_HANDOVER_SEND)) {
            String type = intent.getType();
            Uri stream = (Uri)intent.getParcelableExtra(Intent.EXTRA_STREAM);
            if (stream != null && type != null) {
                // Save type/stream, will be used when adding transfer
                // session to DB.
            BluetoothOppManager.getInstance(context).saveSendingFileInfo(type,
                    stream.toString(), true);
            } else {
                if (D) Log.d(TAG, "No mimeType or stream attached to handover request");
            }
        // ...
        // we already know where to send to
        BluetoothOppManager.getInstance(context).startTransfer(device);

Так как перед сохранением информации о файле и началом передачи выполняется проверка на тип MIME, передача файла Bluetooth OPP никогда не начинается. Обратите внимание, что два других условных блока return когда есть null, так что кажется, что этот не хватает return после Log.d() вызов может быть ошибкой.

Другие вопросы по тегам