通过Android Intent共享位图

Jhi*_*jee 27 android bitmap intentfilter android-intent

在我的Android应用程序中,我有一个位图(比如说b)和一个按钮.现在当我点击按钮时,我想分享位图.我在我的内部使用下面的代码onClick()来实现这个目的: -

Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("image/png");
intent.putExtra(Intent.EXTRA_STREAM, b);
startActivity(Intent.createChooser(intent , "Share"));
Run Code Online (Sandbox Code Playgroud)

我期待一个能够处理这个意图的所有应用程序列表,但我什么都没得到.没有应用程序列表也没有android studio中的任何错误.我的应用程序暂停了一段时间然后退出.

我检查了位图,它很好(它不是空的).

我哪里出错了?

小智 31

我找到了解决方案的2个变种.两者都将Bitmap保存到存储中,但图像未显示在库中.

第一个变种:

保存到外部存储 - 但保存到应用程序的私人文件夹. - 对于API <= 18,它需要许可,而对于较新的则不需要.

1.设置权限

在标记之前添加到AndroidManifest.xml中

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="18"/>
Run Code Online (Sandbox Code Playgroud)

2.保存方法:

 /**
 * Saves the image as PNG to the app's private external storage folder.
 * @param image Bitmap to save.
 * @return Uri of the saved file or null
 */
private Uri saveImageExternal(Bitmap image) {
    //TODO - Should be processed in another thread
    Uri uri = null;
    try {
        File file = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), "to-share.png");
        FileOutputStream stream = new FileOutputStream(file);
        image.compress(Bitmap.CompressFormat.PNG, 90, stream);
        stream.close();
        uri = Uri.fromFile(file);
    } catch (IOException e) {
        Log.d(TAG, "IOException while trying to write file for sharing: " + e.getMessage());
    }
    return uri;
}
Run Code Online (Sandbox Code Playgroud)

3.检查存储可访问性

外部存储可能无法访问,因此您应该在尝试保存之前进行检查 - https://developer.android.com/training/data-storage/files

/**
 * Checks if the external storage is writable.
 * @return true if storage is writable, false otherwise
 */
public boolean isExternalStorageWritable() {
    String state = Environment.getExternalStorageState();
    if (Environment.MEDIA_MOUNTED.equals(state)) {
        return true;
    }
    return false;
}
Run Code Online (Sandbox Code Playgroud)

第二个变种

使用FileProvider保存到cacheDir.它不需要任何许可.

1.在AndroidManifest.xml中设置FileProvider

<manifest>
    ...
    <application>
        ...
        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="com.mydomain.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
                <meta-data
                    android:name="android.support.FILE_PROVIDER_PATHS"
                    android:resource="@xml/file_paths" />
        </provider>
        ...
    </application>
</manifest>
Run Code Online (Sandbox Code Playgroud)

2.添加res/xml/file_paths.xml的路径

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <paths xmlns:android="http://schemas.android.com/apk/res/android">
         <cache-path name="shared_images" path="images/"/>
    </paths>
</resources>
Run Code Online (Sandbox Code Playgroud)

3.保存方法:

 /**
 * Saves the image as PNG to the app's cache directory.
 * @param image Bitmap to save.
 * @return Uri of the saved file or null
 */
private Uri saveImage(Bitmap image) {
    //TODO - Should be processed in another thread
    File imagesFolder = new File(getCacheDir(), "images");
    Uri uri = null;
    try {
        imagesFolder.mkdirs();
        File file = new File(imagesFolder, "shared_image.png");

        FileOutputStream stream = new FileOutputStream(file);
        image.compress(Bitmap.CompressFormat.PNG, 90, stream);
        stream.flush();
        stream.close();
        uri = FileProvider.getUriForFile(this, "com.mydomain.fileprovider", file);

    } catch (IOException e) {
        Log.d(TAG, "IOException while trying to write file for sharing: " + e.getMessage());
    }
    return uri;
}
Run Code Online (Sandbox Code Playgroud)

有关文件提供程序的更多信息 - https://developer.android.com/reference/android/support/v4/content/FileProvider

压缩和保存可能非常耗时,应该在不同的线程中完成

实际分享

/**
 * Shares the PNG image from Uri.
 * @param uri Uri of image to share.
 */
private void shareImageUri(Uri uri){
    Intent intent = new Intent(android.content.Intent.ACTION_SEND);
    intent.putExtra(Intent.EXTRA_STREAM, uri);
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    intent.setType("image/png");
    startActivity(intent);
}
Run Code Online (Sandbox Code Playgroud)

  • 自 Android X 起,FileProvider 的新包名称为:“androidx.core.content.FileProvider”。 (7认同)
  • 这是我认为最好的解决方案,一步一步的详细解释。如果出于安全考虑,与存储在缓存中的图像共享会更好。我错过了添加 xml 和提供程序的步骤,因此它无法正常工作,但最终按照这些步骤操作,现在可以使用了。 (2认同)

Ric*_*k S 24

正如CommonsWare所说,您需要获取位图的URI并将其作为您的Extra传递.

String bitmapPath = Images.Media.insertImage(getContentResolver(), bitmap,"title", null);
Uri bitmapUri = Uri.parse(bitmapPath);
...
intent.putExtra(Intent.EXTRA_STREAM, bitmapUri );
Run Code Online (Sandbox Code Playgroud)

  • 它的工作原理,但也存储图像.所以,图像也显示在gallary中.我怎样才能避免保存图像或将其显示为gallary. (4认同)

小智 14

**最后我得到了解决方案.**

第1步: 共享意图处理阻止.这将弹出您的窗口,其中包含您手机中的应用程序列表

public void share_bitMap_to_Apps() {

    Intent i = new Intent(Intent.ACTION_SEND);

    i.setType("image/*");
    ByteArrayOutputStream stream = new ByteArrayOutputStream();
    /*compress(Bitmap.CompressFormat.PNG, 100, stream);
    byte[] bytes = stream.toByteArray();*/


    i.putExtra(Intent.EXTRA_STREAM, getImageUri(mContext, getBitmapFromView(relative_me_other)));
    try {
        startActivity(Intent.createChooser(i, "My Profile ..."));
    } catch (android.content.ActivityNotFoundException ex) {

        ex.printStackTrace();
    }


}
Run Code Online (Sandbox Code Playgroud)

第2步: 将视图转换为BItmap

public static Bitmap getBitmapFromView(View view) {
    //Define a bitmap with the same size as the view
    Bitmap returnedBitmap = Bitmap.createBitmap(view.getWidth(),      view.getHeight(), Bitmap.Config.ARGB_8888);
    //Bind a canvas to it
    Canvas canvas = new Canvas(returnedBitmap);
    //Get the view's background
    Drawable bgDrawable = view.getBackground();
    if (bgDrawable != null)
        //has background drawable, then draw it on the canvas
        bgDrawable.draw(canvas);
    else
        //does not have background drawable, then draw white background on the canvas
        canvas.drawColor(Color.WHITE);
    // draw the view on the canvas
    view.draw(canvas);
    //return the bitmap
    return returnedBitmap;
}
Run Code Online (Sandbox Code Playgroud)

第3步:

从位图图像获取URI

public Uri getImageUri(Context inContext, Bitmap inImage) {
    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
    inImage.compress(Bitmap.CompressFormat.JPEG, 100, bytes);

    String path = MediaStore.Images.Media.insertImage(inContext.getContentResolver(), inImage, "Title", null);
    return Uri.parse(path);
}
Run Code Online (Sandbox Code Playgroud)

  • 不要忘记要求android.permission.WRITE_EXTERNAL_STORAGE (3认同)
  • 有什么解决方案可以在不写入外部存储的情况下执行此操作吗? (2认同)

Com*_*are 5

引用文档

内容:URI 持有与 Intent 关联的数据流,与 ACTION_SEND 一起使用以提供正在发送的数据。

b,因此,不应是 a Bitmap,而是Uri指向 a Bitmap,由 a 服务ContentProvider。例如,您可以将 写入Bitmap文件,然后使用FileProvider它来提供服务。


Lal*_*hel 5

嗨,编码员,请尝试我的官方博客

ImageButton capture_share = (ImageButton) findViewById(R.id.share);
capture_share.setOnClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View view) {

    String bitmapPath = MediaStore.Images.Media.insertImage(getContentResolver(), bitmap,"title", null);
    Uri bitmapUri = Uri.parse(bitmapPath);

        Intent intent = new Intent(Intent.ACTION_SEND);
        intent.setType("image/png");
        intent.putExtra(Intent.EXTRA_STREAM, bitmapUri);
        startActivity(Intent.createChooser(intent, "Share"));



  }
});
Run Code Online (Sandbox Code Playgroud)