Android 光束 json 文件
Android Beam json file
我有一个简单的 activity 启动文件选择器,然后通过 Android beam 发送文件,如下所示:
@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);
}
}
activity能够正确投射
图像和 .txt 文件。但是,当我发送 .json 文件时,我得到 "Beam did not complete"。
我认为这是因为接收器上没有查看 json 文件的应用程序,所以我创建了另一个版本来查看收到的 txt 文件。清单有
<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 did not complete" 消息。
知道为什么吗?
谢谢!
Any ideas why?
Android Beam uses the file extension of the first file in the Beam Uri
s array to look up a corresponding MIME type in an internal map, which is then sent with the Intent
通过蓝牙对象推送配置文件 (OPP) 启动文件传输。
如果找不到文件扩展名或匹配的 MIME 类型,Intent
的 MIME 类型将设置为 null
,并且根本不会启动蓝牙 OPP 文件传输。
解决方法
发送扩展名未在 MimeUtils
, use a two-element Beam Uri
s 数组中列出的文件时:
uris[0]
:扩展名为.txt
的虚拟文本文件,(稍后删除)
uris[1]
:您要传输的文件(扩展名无法识别)
在您的具体情况下:
adapter.setBeamPushUris(
new Uri[] { dummyTxtFileUri, data.getData() },
this);
Android Beam 将向蓝牙发送 MIME 类型为 text/plain
的意图,以及两个文件的 Uri
s,蓝牙 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 中搜索 "Handing off outging transfer to BT":
platform/packages/apps/Nfc/src/com/android/nfc/handover/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()
:
platform/packages/apps/Nfc/src/com/android/nfc/handover/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;
}
// ...
因此,如果它不识别扩展名,它将 returns null
作为 MIME 类型。正在关注 MimeTypeMap.getSingleton().getMimeTypeFromExtension()
...
frameworks/base/core/java/android/webkit/MimeTypeMap.java
public String getMimeTypeFromExtension(String extension) {
return MimeUtils.guessMimeTypeFromExtension(extension);
}
platform/libcore/luni/src/main/java/libcore/net/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
class 包含 Android 可识别的 MIME 类型列表。很好的参考。
我们已经到达堆栈的末尾 extensionToMimeTypeMap.get()
:
platform/libcore/luni/src/main/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
。多一点挖掘表明这很重要:
platform/packages/apps/Bluetooth/src/com/android/bluetooth/opp/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 类型进行了空检查,因此蓝牙 OPP 文件传输永远不会启动。请注意,当存在 null
时,其他两个条件块 return
,所以看起来这个在 Log.d()
调用之后缺少 return
的事实可能是一个错误.
我有一个简单的 activity 启动文件选择器,然后通过 Android beam 发送文件,如下所示:
@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);
}
}
activity能够正确投射 图像和 .txt 文件。但是,当我发送 .json 文件时,我得到 "Beam did not complete"。
我认为这是因为接收器上没有查看 json 文件的应用程序,所以我创建了另一个版本来查看收到的 txt 文件。清单有
<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 did not complete" 消息。
知道为什么吗?
谢谢!
Any ideas why?
Android Beam uses the file extension of the first file in the Beam Uri
s array to look up a corresponding MIME type in an internal map, which is then sent with the Intent
通过蓝牙对象推送配置文件 (OPP) 启动文件传输。
如果找不到文件扩展名或匹配的 MIME 类型,Intent
的 MIME 类型将设置为 null
,并且根本不会启动蓝牙 OPP 文件传输。
解决方法
发送扩展名未在 MimeUtils
, use a two-element Beam Uri
s 数组中列出的文件时:
uris[0]
:扩展名为.txt
的虚拟文本文件,(稍后删除)
uris[1]
:您要传输的文件(扩展名无法识别)
在您的具体情况下:
adapter.setBeamPushUris(
new Uri[] { dummyTxtFileUri, data.getData() },
this);
Android Beam 将向蓝牙发送 MIME 类型为 text/plain
的意图,以及两个文件的 Uri
s,蓝牙 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 中搜索 "Handing off outging transfer to BT":
platform/packages/apps/Nfc/src/com/android/nfc/handover/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()
:
platform/packages/apps/Nfc/src/com/android/nfc/handover/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;
}
// ...
因此,如果它不识别扩展名,它将 returns null
作为 MIME 类型。正在关注 MimeTypeMap.getSingleton().getMimeTypeFromExtension()
...
frameworks/base/core/java/android/webkit/MimeTypeMap.java
public String getMimeTypeFromExtension(String extension) {
return MimeUtils.guessMimeTypeFromExtension(extension);
}
platform/libcore/luni/src/main/java/libcore/net/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
class 包含 Android 可识别的 MIME 类型列表。很好的参考。
我们已经到达堆栈的末尾 extensionToMimeTypeMap.get()
:
platform/libcore/luni/src/main/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
。多一点挖掘表明这很重要:
platform/packages/apps/Bluetooth/src/com/android/bluetooth/opp/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 类型进行了空检查,因此蓝牙 OPP 文件传输永远不会启动。请注意,当存在 null
时,其他两个条件块 return
,所以看起来这个在 Log.d()
调用之后缺少 return
的事实可能是一个错误.