通过蓝牙共享text / plain String将数据转换为HTML

时间:2015-04-27 22:23:32

标签: android android-intent bluetooth

我正在尝试通过蓝牙发送纯文本,但它会在某处转换为HTML。

我正在使用的代码基本上是这样的:

String content = "This is just a test";
Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, content);
sendIntent.setType("text/plain");
String title = "Share with…";
startActivity(Intent.createChooser(sendIntent, title));

当我运行此代码并选择蓝牙选项时,文件将被推送到名为“bluetooth_content_share.html”的远程系统,并包含以下内容:

<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/></head><body>This is just a test</body></html>

我在添加setType之前尝试调用EXTRA_TEXT,但症状没有变化。其他共享操作(例如,“添加到Dropbox”)将数据作为纯文本获取。我已经能够使用其他应用程序(例如“ES文件资源管理器”)通过蓝牙成功发送纯文本文件。

如何将数据作为我问过的纯文本发送?

2 个答案:

答案 0 :(得分:2)

我无法入睡,所以我决定看看stackoverflow,看看android标签中是否有任何有趣的东西。这个问题似乎很简单,但事实证明它非常有趣,因为正如你在问题中提到的那样,它只是创建了一个该字符串作为内容的该死的html文件。

我认为蓝牙通信想要使用文件,并且即使你明确说明了纯文本,Android也推断我们的文本是html。

我提出的解决方案基本上是强制应用程序共享文本文件,因为它标记为共享测试String。我已经能够测试这个和你的代码了,我能够复制html文件的神奇创造。这应该对你有帮助。

<强>更新 由于操作系统担心将文件保留在存储中,并且无法使用临时文件,因此我已更新代码以向文件中添加FileObserver,以便我们监控文件何时正在被修改以及它正在经历什么类型的行动。在这种情况下,我们需要监控的是FileObserver.CLOSE_NOWRITE操作,只有在访问文件时才会触发该操作, 后完成操作。消除后的文件。

try {
    //Create a file and write the String to it
    BufferedWriter out;
    final String filePath = Environment.getExternalStorageDirectory().getPath() + "/wadus.txt";
    FileWriter fileWriter = new FileWriter(filePath);
    out = new BufferedWriter(fileWriter);
    out.write("I know you'll love me for finding the solution");
    out.close();

    //Access the file and share it through the original intent
    File file = new File(filePath);
    Intent sendIntent = new Intent(Intent.ACTION_SEND);
    sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file));
    sendIntent.setType("text/plain");
    String title = "Share with…";

    //Create a file observer to monitor the access to the file
    FileObserver fobsv = new FileObserver(filePath) {
        @Override
        public void onEvent(int event, String path) {
            if (event == FileObserver.CLOSE_NOWRITE) {
                //The file was previously written to, now it's been sent and closed
                //we can safely delete it.
                File file = new File(filePath);
                file.delete();
            }
        }
    };
    fobsv.startWatching();

    //Launch sharing intent
    startActivity(Intent.createChooser(sendIntent, title));
} catch (FileNotFoundException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
}

如果有人想知道为什么我们设置代码远远的FileObserver,那就是避免在创建和编辑文件本身时触发它。由于我们在文件写入后添加,我们只会触发通过蓝牙发送它所需的事件(在这种情况下)。

答案 1 :(得分:2)

TL; DR:您必须创建文件或实施ContentProvider并将其作为EXTRA_STREAM发送,但这会打破其他想要通过{文本接收数据的应用程序{1}}。可以使用EXTRA_TEXT为“蓝牙共享”应用实现例外。

我能够在Android蓝牙应用(com/android/bluetooth/opp/BluetoothOppLauncherActivity.java)的源代码中找到此代码:

EXTRA_REPLACEMENT_EXTRAS

因此,如果有if (action.equals(Intent.ACTION_SEND)) { final String type = intent.getType(); final Uri stream = (Uri)intent.getParcelableExtra(Intent.EXTRA_STREAM); CharSequence extra_text = intent.getCharSequenceExtra(Intent.EXTRA_TEXT); if (stream != null && type != null) { // clipped } else if (extra_text != null && type != null) { if (V) Log.v(TAG, "Get ACTION_SEND intent with Extra_text = " + extra_text.toString() + "; mimetype = " + type); final Uri fileUri = creatFileForSharedContent(this, extra_text); // clipped } else { Log.e(TAG, "type is null; or sending file URI is null"); finish(); return; } 而没有EXTRA_TEXT,请将其发送至EXTRA_STREAM,而creatFileForSharedContent()又包含此内容:

String fileName = getString(R.string.bluetooth_share_file_name) + ".html";
context.deleteFile(fileName);

/*
 * Convert the plain text to HTML
 */
StringBuffer sb = new StringBuffer("<html><head><meta http-equiv=\"Content-Type\""
        + " content=\"text/html; charset=UTF-8\"/></head><body>");
// Escape any inadvertent HTML in the text message
String text = escapeCharacterToDisplay(shareContent.toString());

// Regex that matches Web URL protocol part as case insensitive.
Pattern webUrlProtocol = Pattern.compile("(?i)(http|https)://");

Pattern pattern = Pattern.compile("("
        + Patterns.WEB_URL.pattern() + ")|("
        + Patterns.EMAIL_ADDRESS.pattern() + ")|("
        + Patterns.PHONE.pattern() + ")");
// Find any embedded URL's and linkify
Matcher m = pattern.matcher(text);
while (m.find()) {
    //clipped
}
m.appendTail(sb);
sb.append("</body></html>");

换句话说,蓝牙应用程序显式将任何以文本形式发送的内容转换为HTML。谢谢,Android!

蓝牙应用只能接受EXTRA_STREAM作为内容的两件事:和文件:URIs(com/android/bluetooth/opp/BluetoothOppSendFileInfo.java):

if ("content".equals(scheme)) {
    //clipped
} else if ("file".equals(scheme)) {
    //clipped
} else {
    // currently don't accept other scheme
    return SEND_FILE_INFO_ERROR;
}

因此尝试发送数据:URI不起作用。

这意味着您必须创建文件或实现ContentProvider。 只是发送一些该死的纯文本!

但是,这有可能会破坏与希望通过EXTRA_TEXT方法接收数据的其他应用的共享。幸运的是,可以使用EXTRA_STREAM创建仅提供给蓝牙共享应用的EXTRA_REPLACEMENT_EXTRAS

String content = "This is just a test";
Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, content);
sendIntent.setType("text/plain");
String title = "Share with…";

Intent shareChooser = Intent.createChooser(sendIntent, title);

// Add Bluetooth Share-specific data
try {
    // Create file with text to share
    final File contentFile = new File(getActivity().getExternalCacheDir(), "plain.txt");
    FileWriter contentFileWriter = new FileWriter(contentFile, false);
    BufferedWriter contentWriter = new BufferedWriter(contentFileWriter);
    contentWriter.write(content);
    contentWriter.close();
    Uri contentUri = Uri.fromFile(contentFile);

    Bundle replacements = new Bundle();
    shareChooser.putExtra(Intent.EXTRA_REPLACEMENT_EXTRAS, replacements);

    // Create Extras Bundle just for Bluetooth Share
    Bundle bluetoothExtra = new Bundle(sendIntent.getExtras());
    replacements.putBundle("com.android.bluetooth", bluetoothExtra);

    // Add file to Bluetooth Share's Extras
    bluetoothExtra.putParcelable(Intent.EXTRA_STREAM, contentUri);
} catch (IOException e) {
    // Handle file creation error
}

startActivity(shareChooser);

然而,你仍然需要处理删除文件,当用户选择蓝牙以外的东西来共享时,这会变得更加复杂,因为永远不会打开文件,使得Juan的答案中的FileObserver解决方案成为不完整的。