我正在尝试通过蓝牙发送纯文本,但它会在某处转换为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文件资源管理器”)通过蓝牙成功发送纯文本文件。
如何将数据作为我问过的纯文本发送?
答案 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
解决方案成为不完整的。