Файл 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":
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
, Еще немного копаний показывает, где это важно:
@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()
вызов может быть ошибкой.