发送图像以响应 android.intent.action.GET_CONTENT

Send image in response to android.intent.action.GET_CONTENT

我愿意创建一个应用程序来发送图片以回复 android.intent.action.GET_CONTENT 意图。我的用例是来自 Play 商店的 Messenger 应用程序,我猜是最常见的 SMS/MMS 应用程序。

我尝试发送图片,但效果不佳。将彩信发送到 Android 手机时,他们可以正确接收,但 iPhone 似乎将其显示为从不播放的虚假视频。
我知道可能是我的或者国外运营商的MMSC服务器自以为聪明,把数据转码成它认为好的格式。

但是,当对另一个应用程序使用相同的意图时(尝试了 Google 的照片应用程序和 Solid Explorer),它在 Android 和 iPhone 上都能很好地工作。

我的猜测是 Photos 和 Solid Explorer 以正确的格式发回数据,MMS 应用程序正确地发送到 MMSC,从而按原样传送图片。

这是我尝试过的:

  1. 在缓存中发送我的文件的简单 Uri(通过 Content#getExternalCacheDir():不工作
  2. 使用 StreamProvider 发送我文件的 Uri,使用 CommonWare's CWAC lib,通过设置 LocalPathStrategyContext#getExternalCacheDir() 作为根路径:不工作

这两种策略最终都会将图像正确发送回 MMS 应用程序,然后显示图像并且按钮变为 "Send MMS";然后在 Android 上收到的是图片,在 iOS 上收到的是假视频,无法播放。

我应该如何将数据发送回调用应用程序?

为了实际解释我所做的,这里是第一个策略:

Intent result = new Intent();
result.setData(Uri.fromFile(localImage));
setResult(Activity.RESULT_OK, result);
finish();

这是第二个:

Intent result = new Intent();
result.setData(PROVIDER
        .buildUpon()
        .appendPath(StreamProvider.getUriPrefix(AUTHORITY))
        .appendPath(localImage.getName())
        .build());
result.setFlags(FLAG_GRANT_READ_URI_PERMISSION);
setResult(Activity.RESULT_OK, result);
finish();

我想我可以在意图中将位图字节作为数据传递,但我没有想出办法做到这一点。

是的,看起来 setResult() 还需要 IntentFLAG_GRANT_READ_URI_PERMISSION and/or FLAG_GRANT_WRITE_URI_PERMISSION,如果您使用的是 ContentProvider结果 Uri.

addFlags() 可以将这些标志添加到 Intent,至少回到 API 级别 19。我没有测试过比这更早的版本,所以可能有你的版本必须使用 ClipData 技巧:

if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.KITKAT) {
  i.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
}
else if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.JELLY_BEAN) {
  ClipData clip=
    ClipData.newUri(getContentResolver(), "A photo", outputUri);

  i.setClipData(clip);
  i.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
}
else {
  List<ResolveInfo> resInfoList=
    getPackageManager()
      .queryIntentActivities(i, PackageManager.MATCH_DEFAULT_ONLY);

  for (ResolveInfo resolveInfo : resInfoList) {
    String packageName = resolveInfo.activityInfo.packageName;
    grantUriPermission(packageName, outputUri,
      Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
  }
}