28

I want to share an image using the code:

Intent sharingIntent = new Intent(Intent.ACTION_SEND);
Uri imageUri = Uri.parse("http://stacktoheap.com/images/stackoverflow.png");
sharingIntent.setType("image/png");
sharingIntent.putExtra(Intent.EXTRA_STREAM, imageUri);
startActivity(sharingIntent);

I made a button that call the code above. The share intent open but I got if I click on "Share by MMS": "cannot add this picture to your message". If Facebook I got only a text area without my picture.

Alexander Farber
  • 21,519
  • 75
  • 241
  • 416
Coder Php
  • 281
  • 1
  • 3
  • 3

9 Answers9

46

An adapted version of @eclass's answer which doesn't require use of an ImageView:

Use Picasso to load the url into a Bitmap

public void shareItem(String url) {
    Picasso.with(getApplicationContext()).load(url).into(new Target() {
        @Override public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
            Intent i = new Intent(Intent.ACTION_SEND);
            i.setType("image/*");
            i.putExtra(Intent.EXTRA_STREAM, getLocalBitmapUri(bitmap));
            startActivity(Intent.createChooser(i, "Share Image"));
        }
        @Override public void onBitmapFailed(Drawable errorDrawable) { }
        @Override public void onPrepareLoad(Drawable placeHolderDrawable) { }
    });
}

Convert Bitmap into Uri

public Uri getLocalBitmapUri(Bitmap bmp) {
    Uri bmpUri = null;
    try {
        File file =  new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), "share_image_" + System.currentTimeMillis() + ".png");
        FileOutputStream out = new FileOutputStream(file);
        bmp.compress(Bitmap.CompressFormat.PNG, 90, out);
        out.close();
        bmpUri = Uri.fromFile(file);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return bmpUri;
}
Aaron Shaw
  • 711
  • 5
  • 9
  • 1
    got it.. getExternalFilesDir is a context method so if you want to use it in some adapter class, just get the context from base class in constructor and use it like this `_context.getExternalFilesDir()`.. thanks. – deejay Apr 11 '17 at 08:12
  • 2
    2 minor notes: You might want to put getLocalBitmapUri in a Thread in case of saving a bigger image Compressing png will ignore the quality level of 90. – endevour Jul 24 '17 at 12:02
  • 1
    It take more time for large image.. Any possible to reduce this duration? – Ranjithkumar Aug 30 '17 at 10:21
  • In you "shareItem" method, I get the following error for each override: Method does not override from its superClass – Isabelle Sep 01 '17 at 09:51
  • @Aaron Shaw, I get this error, android.os.FileUriExposedException: file:///storage/emulated/0/Android/data/...../files/Pictures/share_image_1536422301331.png exposed beyond app through ClipData.Item.getUri() – eawedat Sep 08 '18 at 15:59
  • 2
    `bmpUri` should be `FileProvider.getUriForFile(context, context.getPackageName() + ".provider", file);` – Pratik Butani Sep 29 '18 at 04:56
23

I use these codes from this tutorial

        final ImageView imgview= (ImageView)findViewById(R.id.feedImage1);

                Uri bmpUri = getLocalBitmapUri(imgview);
                if (bmpUri != null) {
                    // Construct a ShareIntent with link to image
                    Intent shareIntent = new Intent();
                    shareIntent.setAction(Intent.ACTION_SEND);
                    shareIntent.putExtra(Intent.EXTRA_STREAM, bmpUri);
                    shareIntent.setType("image/*");
                    // Launch sharing dialog for image
                    startActivity(Intent.createChooser(shareIntent, "Share Image"));    
                } else {
                    // ...sharing failed, handle error
                }

then add this to your activity

 public Uri getLocalBitmapUri(ImageView imageView) {
    // Extract Bitmap from ImageView drawable
    Drawable drawable = imageView.getDrawable();
    Bitmap bmp = null;
    if (drawable instanceof BitmapDrawable){
       bmp = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
    } else {
       return null;
    }
    // Store image to default external storage directory
    Uri bmpUri = null;
    try {
        File file =  new File(Environment.getExternalStoragePublicDirectory(  
            Environment.DIRECTORY_DOWNLOADS), "share_image_" + System.currentTimeMillis() + ".png");
        file.getParentFile().mkdirs();
        FileOutputStream out = new FileOutputStream(file);
        bmp.compress(Bitmap.CompressFormat.PNG, 90, out);
        out.close();
        bmpUri = Uri.fromFile(file);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return bmpUri;
}

then add your application manifest

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

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
eclass
  • 231
  • 2
  • 4
  • 1
    If you are allowing for Write do you need to ask for Read permission as well? – Lion789 Aug 06 '15 at 23:33
  • 1
    @Lion789 no, one of them is enough. In fact, if you use `Context.getExternalFilesDir()` you need no permission :) – Jemshit Feb 24 '17 at 11:33
4

After a lot of pondering, here is the code that I found to be working for me! I think this is one of the simplest versions of code to achieve the given task using Picasso. There is no need to create an ImageView object.

            Target target = new Target() {
            @Override
            public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
                bmp = bitmap;
                String path = MediaStore.Images.Media.insertImage(getContentResolver(), bmp, "SomeText", null);
                Log.d("Path", path);
                Intent intent = new Intent(Intent.ACTION_SEND);
                intent.putExtra(Intent.EXTRA_TEXT, "Hey view/download this image");
                Uri screenshotUri = Uri.parse(path);
                intent.putExtra(Intent.EXTRA_STREAM, screenshotUri);
                intent.setType("image/*");
                startActivity(Intent.createChooser(intent, "Share image via..."));
            }

            @Override
            public void onBitmapFailed(Drawable errorDrawable) {

            }

            @Override
            public void onPrepareLoad(Drawable placeHolderDrawable) {

            }
        };
        String url = "http://efdreams.com/data_images/dreams/face/face-03.jpg";
        Picasso.with(getApplicationContext()).load(url).into(target);

Here, bmp is a class level Bitmap variable and url will be the dynamic Internet url to your image for sharing. Also, instead of keeping the code to share inside the onBitmapLoaded() function, it can also be kept inside another handler function and later called from the onBitmapLoaded() function. Hope this helps!

Yash Vanzara
  • 51
  • 1
  • 4
3

Try this:

new OmegaIntentBuilder(context)
                .share()
                .filesUrls("http://stacktoheap.com/images/stackoverflow.png")
                .download(new DownloadCallback() {
                    @Override
                    public void onDownloaded(boolean success, @NotNull ContextIntentHandler contextIntentHandler) {
                        contextIntentHandler.startActivity();
                    }
                });

https://github.com/Omega-R/OmegaIntentBuilder

  • Awesome library, but if you want to get all available apps to show up in the chooser intent you need to specify: contextIntentHandler.getIntent().type = MimeTypes.IMAGE_JPEG // Or PNG, based on your needs – Ro Ra Mar 07 '20 at 00:44
1

First you need to load image in the glide. Then you can share it to anywhere. Code to load image from glide (image is being saved to storage, you can delete it later).

Glide.with(getApplicationContext())
 .load(imagelink)\\ link of your image file(url)
 .asBitmap().skipMemoryCache(true).diskCacheStrategy(DiskCacheStrategy.NONE)

 .into(new SimpleTarget < Bitmap > (250, 250) {
  @Override
  public void onResourceReady(Bitmap resource, GlideAnimation glideAnimation) {


   Intent intent = new Intent(Intent.ACTION_SEND);
   intent.putExtra(Intent.EXTRA_TEXT, "Hey view/download this image");
   String path = MediaStore.Images.Media.insertImage(getContentResolver(), resource, "", null);
   Log.i("quoteswahttodo", "is onresoursereddy" + path);

   Uri screenshotUri = Uri.parse(path);

   Log.i("quoteswahttodo", "is onresoursereddy" + screenshotUri);

   intent.putExtra(Intent.EXTRA_STREAM, screenshotUri);
   intent.setType("image/*");

   startActivity(Intent.createChooser(intent, "Share image via..."));
  }

  @Override
  public void onLoadFailed(Exception e, Drawable errorDrawable) {
   Toast.makeText(getApplicationContext(), "Something went wrong", Toast.LENGTH_SHORT).show();


   super.onLoadFailed(e, errorDrawable);
  }

  @Override
  public void onLoadStarted(Drawable placeholder) {
   Toast.makeText(getApplicationContext(), "Starting", Toast.LENGTH_SHORT).show();

   super.onLoadStarted(placeholder);
  }
 });
ssuperczynski
  • 3,190
  • 3
  • 44
  • 61
ashad
  • 351
  • 4
  • 13
0
   share.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                int permissionCheck = ContextCompat.checkSelfPermission(SingleProduct.this,
                        Manifest.permission.READ_EXTERNAL_STORAGE);

                if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
                    Log.e("MainActivity ", "P granted");

                    bmpUri = getLocalBitmapUri(imageView);

                } else {
                    ActivityCompat.requestPermissions(SingleProduct.this,
                            new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
                }
            } else {
                Log.e("MainActivity", "Lower Than MarshMallow");
                bmpUri = getLocalBitmapUri(imageView);
            }

            if (bmpUri != null) {
                // Construct a ShareIntent with link to image
                Intent shareIntent = new Intent();
                shareIntent.setAction(Intent.ACTION_SEND);
                shareIntent.putExtra(Intent.EXTRA_STREAM, bmpUri);
                shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                shareIntent.setType("image/*");
                startActivity(Intent.createChooser(shareIntent, "Share Image"));
            } else {
                Toast.makeText(SingleProduct.this, "Sharing Failed !!", Toast.LENGTH_SHORT).show();
            }
        }
    });

 public Uri getLocalBitmapUri(ImageView imageView) {
    Drawable drawable = imageView.getDrawable();
    Bitmap bmp = null;
    if (drawable instanceof BitmapDrawable) {
        bmp = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
    } else {
        return null;
    }
    Uri bmpUri = null;
    try {
        File file = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), "share_image_" + System.currentTimeMillis() + ".png");
        FileOutputStream out = new FileOutputStream(file);
        bmp.compress(Bitmap.CompressFormat.PNG, 90, out);
        out.close();

       bmpUri = Uri.fromFile(file);


    } catch (IOException e) {
        e.printStackTrace();
    }
    return bmpUri;
}

//for oreo add below code in manifest under application tag

 <provider
        android:name=".utility.GenericFileProvider"
        android:authorities="${applicationId}.your package 
     name.utility.GenericFileProvider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/provider_paths" />
    </provider>

create class that extends FileProvider

public class MyFileProvider extends FileProvider {

}

for oreo add this code

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            bmpUri = FileProvider.getUriForFile(this, 
      this.getApplicationContext().getPackageName() + 
    ".your package name.GenericFileProvider", file);
        } else {
            bmpUri = Uri.fromFile(file);
        }

finally add provider_paths.xml in res/xml 

   <paths xmlns:android="http://schemas.android.com/apk/res/android">
   <external-path name="external_files" path="."/>
   </paths>

thats all

Praveen
  • 946
  • 6
  • 14
  • Hi, I tried this but am getting an error: Failed to find configured root that contains /file:/storage/emulated/0/Pictures/Screenshots/MyScreenshot.jpg Just wondering if you'd any idea? Been stuck on it for a few hours now :( – user1898712 Nov 20 '18 at 23:46
0

Here, i convert the url into imageView using asyncTask and store that into a bitmap. dont forget to add internet permission in manifest.

public class MainActivity extends AppCompatActivity  {

    @SuppressLint("WrongThread")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button iv1 = findViewById(R.id.shreimage);
        final ImageView imgview= (ImageView)findViewById(R.id.content_image);
        new DownloadImageTask(imgview).execute("https://sample-videos.com/img/Sample-jpg-image-50kb.jpg");
        iv1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Drawable myDrawable = imgview.getDrawable();
                Bitmap bitmap = ((BitmapDrawable)myDrawable).getBitmap();
                try{
                    File file = new File(MainActivity.this.getExternalCacheDir(),"myImage.jpeg");
                    FileOutputStream fout = new FileOutputStream(file);
                    bitmap.compress(Bitmap.CompressFormat.JPEG,80,fout);
                    fout.flush();
                    fout.close();
                    file.setReadable(true,false);
                    Intent intent = new Intent(Intent.ACTION_SEND);
                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    intent.putExtra(Intent.EXTRA_STREAM,Uri.fromFile(file));
                    intent.setType("image/*");
                    startActivity(Intent.createChooser(intent,"Share Image Via"));
                }catch (FileNotFoundException e){
                    e.printStackTrace();
                    Toast.makeText(MainActivity.this,"File Nott Found",Toast.LENGTH_SHORT).show();
                }catch (IOException e){
                    e.printStackTrace();
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        });

     }


    private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
        ImageView bmImage;

        public DownloadImageTask(ImageView bmImage) {
            this.bmImage = bmImage;
        }

        protected Bitmap doInBackground(String... urls) {
            String urldisplay = urls[0];
            Bitmap mIcon11 = null;
            try {
                InputStream in = new java.net.URL(urldisplay).openStream();
                mIcon11 = BitmapFactory.decodeStream(in);
            } catch (Exception e) {
                Log.e("Error", e.getMessage());
                e.printStackTrace();
            }
            return mIcon11;
        }

        protected void onPostExecute(Bitmap result) {
            bmImage.setImageBitmap(result);
        }
    }
}
Udo E.
  • 2,665
  • 2
  • 21
  • 33
0
Picasso.with(applicationContext).load(url).into(object : Target {
            override fun onBitmapLoaded(bitmap: Bitmap, from: Picasso.LoadedFrom?) {
                val bitmapPath: String =
                    MediaStore.Images.Media.insertImage(contentResolver, bitmap, "ayurved", null)
                val bitmapUri = Uri.parse(bitmapPath)
                val shareIntent = Intent(Intent.ACTION_SEND)
                shareIntent.type = "image/jpeg";
                shareIntent.putExtra(Intent.EXTRA_STREAM, bitmapUri);
                startActivity(Intent.createChooser(shareIntent, "ayurved"))
            }
            override fun onBitmapFailed(errorDrawable: Drawable?) {}
            override fun onPrepareLoad(placeHolderDrawable: Drawable?) {}
        })
  • While this might answer the question, it is much more useful to provide information on why and how. – Michael Nov 10 '20 at 20:47
-1

By using createchooser you can achieve this,

Intent sharingIntent = new Intent(Intent.ACTION_SEND);
Uri screenshotUri = Uri.parse(path);

sharingIntent.setType("image/png");
sharingIntent.putExtra(Intent.EXTRA_STREAM, screenshotUri);
startActivity(Intent.createChooser(sharingIntent, "Share image using"));

Registering for the Intent

If you want your app to be listed when this Intent is called, then you have to add an intent filter in your manifest.xml file

 <intent-filter>
 <action android:name="android.intent.action.SEND" />
 <category android:name="android.intent.category.DEFAULT" />
 <data android:mimeType="image/*" />
 </intent-filter>