通过ContentProvider导出图片

发布于 2024-10-07 07:15:52 字数 3662 浏览 8 评论 0原文

我正在尝试将图像从我的应用程序导出到其他应用程序,例如 Twitter、Facebook 或其他接受图像的应用程序。 我正在执行以下操作:


private void exportImage()
{
    storeBitmapOnDisk(this.bitmap);
    Intent i = new Intent(Intent.ACTION_SEND);
    i.addCategory(Intent.CATEGORY_LAUNCHER);
    i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
    | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
    File imgFile = context.getFileStreamPath("export.png");
    Uri uri = Uri.fromFile(imgFile);
    i.putExtra(Intent.EXTRA_STREAM, uri);
    i.setType("image/png");
    i.setComponent(componentName);
    context.startActivity(i);
}
private void storeBitmapOnDisk(Bitmap bitmap)
{
    try
    {
        FileOutputStream outStream = context.openFileOutput("export.png",
        Context.MODE_WORLD_READABLE);
        bitmap.compress(Bitmap.CompressFormat.PNG, 50, outStream);
        outStream.close();
    }
    catch (IOException e)
    {
        Log.d(TAG, e.getMessage());
    }
}

这不起作用,因为我正在编写其他应用程序无法访问的内部存储。由于我不想使用外部存储(SD 卡),我认为我需要的是 ContentProvider,但我看到的所有示例都是关于自定义 ContentPovider 的,它们都使用 SQlite 数据库来存储数据。我不知道如何将位图存储在内部存储中,并通过 ContentProvider 将其提供给其他应用程序,而不将我的位图存储在数据库中。 MatrixCursor似乎不太适应...

解决方案我创建了一个自定义内容提供程序,并将内容提供程序中的文件路径设置为意图的Uri EXTRA_STREAM额外参数:

首先是我的提供程序类我只需要覆盖 openFile ,这在文档中并不清楚...


public class ExportContentProvider extends ContentProvider
{
  public static Uri CONTENT_URI = Uri
                                    .parse("content://com.path.to.my.provider");

  @Override
  public int delete(Uri uri, String selection, String[] selectionArgs)
  {
    return 0;
  }

  @Override
  public String getType(Uri uri)
  {
    return null;
  }

  @Override
  public Uri insert(Uri uri, ContentValues values)
  {
    return null;
  }

  @Override
  public boolean onCreate()
  {
    return false;
  }

  @Override
  public ParcelFileDescriptor openFile(Uri uri, String mode)
  {
    int imode = 0;
    if (mode.contains("w"))
      imode |= ParcelFileDescriptor.MODE_WRITE_ONLY;
    if (mode.contains("r"))
      imode |= ParcelFileDescriptor.MODE_READ_ONLY;
    if (mode.contains("+"))
      imode |= ParcelFileDescriptor.MODE_APPEND;
    try
    {
      return ParcelFileDescriptor.open(new File(uri.getEncodedPath()), imode);
    }
    catch (FileNotFoundException e)
    {
      e.printStackTrace();
    }
    return null;
  }

  @Override
  public Cursor query(Uri uri, String[] projection, String selection,
      String[] selectionArgs, String sortOrder)
  {
    return null;
  }

  @Override
  public int update(Uri uri, ContentValues values, String selection,
      String[] selectionArgs)
  {
      return 0;
  }
}

然后我的导出功能:


private void exportImage()
{
    storeBitmapOnDisk();
    Intent i = new Intent(Intent.ACTION_SEND);
    i.addCategory(Intent.CATEGORY_LAUNCHER);
    i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
        | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
    i.putExtra(Intent.EXTRA_STREAM, Uri.withAppendedPath(
        ExportContentProvider.CONTENT_URI, context.getFileStreamPath(
            "export.png").getAbsolutePath()));
    i.setType("image/png");
    i.setComponent(componentName);
    if (exportFileObserver == null)
    {
      this.bitmapPath = context.getFileStreamPath("export.png")
          .getAbsolutePath();
      exportFileObserver = new ExportFileObserver(this.bitmapPath);
      exportFileObserver.startWatching();
    }
    listener.launchExportActivity(Dms.ACT_IMAGE_EXPORT, i);
  }

尽管如此,仍然存在两个问题: - 当尝试使用活动结果删除内存上的临时 export.png 文件时,我在活动启动时收到了 onResult... - 它不适用于我的 2.3 模拟器中的邮件应用程序。我收到“文件到大”消息...

有人测试过吗?

I´m trying to export an image from my application to other applications like twitter, facebook or other apps accepting it images.
I'm doing the following:


private void exportImage()
{
    storeBitmapOnDisk(this.bitmap);
    Intent i = new Intent(Intent.ACTION_SEND);
    i.addCategory(Intent.CATEGORY_LAUNCHER);
    i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
    | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
    File imgFile = context.getFileStreamPath("export.png");
    Uri uri = Uri.fromFile(imgFile);
    i.putExtra(Intent.EXTRA_STREAM, uri);
    i.setType("image/png");
    i.setComponent(componentName);
    context.startActivity(i);
}
private void storeBitmapOnDisk(Bitmap bitmap)
{
    try
    {
        FileOutputStream outStream = context.openFileOutput("export.png",
        Context.MODE_WORLD_READABLE);
        bitmap.compress(Bitmap.CompressFormat.PNG, 50, outStream);
        outStream.close();
    }
    catch (IOException e)
    {
        Log.d(TAG, e.getMessage());
    }
}

This is not working because I'm writing internal storage with is not accessible by other applications. As I don't want to use external storage (SD card) I think what I need is a ContentProvider but all examples I saw is about custom ContentPovider are using a SQlite database to store the data. I can't figure out how I could store a bitmap in internal storage and make it available through a ContentProvider to other applications without storing my bitmap in a database. MatrixCursor seems not to be adapted too...

SOLUTION I create a custom Content Provider and set the path of the file in the the content provider as the Uri EXTRA_STREAM extra parameter of the intent:

First my provider class where I only needed to override openFile which is not clear in the doc...


public class ExportContentProvider extends ContentProvider
{
  public static Uri CONTENT_URI = Uri
                                    .parse("content://com.path.to.my.provider");

  @Override
  public int delete(Uri uri, String selection, String[] selectionArgs)
  {
    return 0;
  }

  @Override
  public String getType(Uri uri)
  {
    return null;
  }

  @Override
  public Uri insert(Uri uri, ContentValues values)
  {
    return null;
  }

  @Override
  public boolean onCreate()
  {
    return false;
  }

  @Override
  public ParcelFileDescriptor openFile(Uri uri, String mode)
  {
    int imode = 0;
    if (mode.contains("w"))
      imode |= ParcelFileDescriptor.MODE_WRITE_ONLY;
    if (mode.contains("r"))
      imode |= ParcelFileDescriptor.MODE_READ_ONLY;
    if (mode.contains("+"))
      imode |= ParcelFileDescriptor.MODE_APPEND;
    try
    {
      return ParcelFileDescriptor.open(new File(uri.getEncodedPath()), imode);
    }
    catch (FileNotFoundException e)
    {
      e.printStackTrace();
    }
    return null;
  }

  @Override
  public Cursor query(Uri uri, String[] projection, String selection,
      String[] selectionArgs, String sortOrder)
  {
    return null;
  }

  @Override
  public int update(Uri uri, ContentValues values, String selection,
      String[] selectionArgs)
  {
      return 0;
  }
}

And then my export function:


private void exportImage()
{
    storeBitmapOnDisk();
    Intent i = new Intent(Intent.ACTION_SEND);
    i.addCategory(Intent.CATEGORY_LAUNCHER);
    i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
        | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
    i.putExtra(Intent.EXTRA_STREAM, Uri.withAppendedPath(
        ExportContentProvider.CONTENT_URI, context.getFileStreamPath(
            "export.png").getAbsolutePath()));
    i.setType("image/png");
    i.setComponent(componentName);
    if (exportFileObserver == null)
    {
      this.bitmapPath = context.getFileStreamPath("export.png")
          .getAbsolutePath();
      exportFileObserver = new ExportFileObserver(this.bitmapPath);
      exportFileObserver.startWatching();
    }
    listener.launchExportActivity(Dms.ACT_IMAGE_EXPORT, i);
  }

Nevertheless there are 2 problems remaining:
- When trying to delete my temporary export.png file on my internal memory using result of the activity I received the onResult when the activity is launch...
- It s not working for mail app in my 2.3 emulator. I'm getting "File to large" message...

Somenone tested that ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文