安卓传感器json文件

3

我有一个简单的活动,它启动文件选择器,然后通过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);
    }
}

这个功能能够正确地传输图片和txt文件。然而,当我尝试传输json文件时,会出现“传输未完成”的错误提示。

我认为原因是接收方没有可以查看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并将接收方的MIME类型设置为"application/json"时,仍然会收到“Beam未完成”的消息。有任何想法吗?
谢谢!

好奇... JSON文件的URI是什么样子? - unrulygnu
@unrulygnu - URI为:file:///storage/sdcard0/Android/data/com.test.nfctest/files/test.json - Stralo
我认为没有任何应用程序明确说明它们接受JSON文件。你应该只是将它们作为文本发送。你可能可以保留.json,只需确保MIME类型为“text / *”。 - gatlingxyz
@kentarosu - 当我使用文件浏览器查看.json文件的属性时,我没有看到任何mimetype。我该如何确保json文件具有text/* mimetype? - Stralo
我几乎可以确定所有的 .json 文件只是在结尾处使用了不同的扩展名的 .txt 文件。就是这样。 - gatlingxyz
1个回答

6

有任何想法吗?

Android Beam 使用 Beam Uri 数组中的第一个文件的文件扩展名在内部映射表中查找相应的 MIME 类型,然后将其与通过蓝牙对象推送配置文件(OPP)启动文件传输的 Intent 一起发送。

如果未找到文件扩展名或匹配的 MIME 类型,则 Intent 的 MIME 类型将设置为null,并且根本不会启动蓝牙 OPP 文件传输。

解决方法

当发送一个扩展名不在MimeUtils列表中的文件时,请使用一个包含两个元素的Beam Uri数组: uris[0]:一个带有.txt扩展名的虚拟文本文件(稍后将被删除) uris[1]:您要传输的文件(具有不被识别的扩展名)
在您的特定情况下:
        adapter.setBeamPushUris(
                new Uri[] { dummyTxtFileUri, data.getData() },
                this);

Android Beam会向蓝牙发送一个MIME类型为text/plain的意图,同时传递两个文件的 Uri以及蓝牙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”:

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();
}

在继续之前,请注意仅将数组中的第一个Uri的MIME类型发送到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;
            }
        // ...

因此,如果它无法识别扩展名,则会将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 包含 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时,其他两个条件块都会返回,因此似乎这个条件块在Log.d()调用后缺少一个return可能是一个bug。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接