更新时间:2023-02-03 08:15:59
TL; DR::您必须创建文件或实现ContentProvider并将其作为EXTRA_STREAM
发送,但这会中断其他想要通过EXTRA_TEXT
以文本形式接收数据的应用程序.通过使用EXTRA_REPLACEMENT_EXTRAS
,可以为蓝牙共享"应用实现例外.
TL;DR: You either have to create a file or implement a ContentProvider and send it as EXTRA_STREAM
, but this breaks other apps that want to receive the data as text via EXTRA_TEXT
. It's possible to implement an exception for the "Bluetooth Share" app by using EXTRA_REPLACEMENT_EXTRAS
.
I was able to find this code in the source for the Android Bluetooth app (com/android/bluetooth/opp/BluetoothOppLauncherActivity.java):
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()
,该文件又包含以下内容:
So if there's EXTRA_TEXT
and no EXTRA_STREAM
, then send it to creatFileForSharedContent()
, which, in turn contains this:
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!
In other words, the Bluetooth app explicitly converts anything sent as text to HTML. Thanks, Android!
蓝牙应用程序将接受为EXTRA_STREAM
的仅有两件事是内容:和文件:URI(
The only two things that the Bluetooth app will accept as an EXTRA_STREAM
are content: and file: 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不起作用.
So trying to send a data: URI doesn't work.
这意味着您必须创建文件或实现ContentProvider. 只发送一些该死的纯文本!
This means you either have to create a file or implement a ContentProvider. Just to send some damned plain text!
但这可能会中断与其他希望通过EXTRA_TEXT
方法接收数据的应用程序的共享.幸运的是,可以使用EXTRA_REPLACEMENT_EXTRAS
创建一个仅提供给Bluetooth Share应用程序的EXTRA_STREAM
:
But this has the potential to break sharing with other apps that want to receive the data via the EXTRA_TEXT
method. Fortunately, it's possible to create an EXTRA_STREAM
that is only provided to the Bluetooth Share app by using 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
解决方案变得不完整.
You still have to handle deleting the file, though, which becomes more complicated when the user chooses something other than Bluetooth to share with, since the file will never be opened, making the FileObserver
solution in Juan's answer become incomplete.