Solution 1:

I found 2 variants of the solution. Both involve saving Bitmap to storage, but the image will not appear in the gallery.

First variant:

Saving to external storage

  • but to private folder of the app.
  • for API <= 18 it requires permission, for newer it does not.

1. Setting permissions

Add into AndroidManifest.xml before tag

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="18"/>

2. Saving method:

 /**
 * 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;
}

3. Checking storage accesibility

External storage might not be accessible, so you should check it before trying to save: 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;
}

Second variant

Saving to cacheDir using FileProvider. It does not require any permissions.

1. Setup FileProvider in AndroidManifest.xml

<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>

2. Add path to the 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>

3. Saving method:

 /**
 * 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;
}

More info about file provider - https://developer.android.com/reference/android/support/v4/content/FileProvider

Compressing and saving can be time-consuming, therefore this should be done in a different thread

Actual sharing

/**
 * 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);
}

Solution 2:

As CommonsWare stated you need to get the URI to the bitmap and pass that as your Extra.

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

Solution 3:

Finally, I got the solution:

Step 1 : Share Intent handling Block. This will Pop Up your window with list of Applications in you phone

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();
    }
}

Step 2 : Converting your view to 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;
}

Step 3 : To get The URI from Bitmap Image

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);
}

Solution 4:

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"));
  }
});

Solution 5:

Quoting the documentation:

A content: URI holding a stream of data associated with the Intent, used with ACTION_SEND to supply the data being sent.

b, therefore, is not supposed to be a Bitmap, but rather a Uri pointing to a Bitmap, served by a ContentProvider. For example, you could write the Bitmap to a file, then use FileProvider to serve it.