beastlyCoder
beastlyCoder

Reputation: 2401

Image not being shared to Apps

I want my users to be able to share an image and select an app to share it to whether its something like their native messenger app, or twitter. Whenever I go to select the app I want to share the image to, I get a message saying "This media can't be loaded" or something like that. Here is the sharing code in BitmapUtils.java

static void shareImage(Context context, String imagePath) {
    // Create the share intent and start the share activity
    File imageFile = new File(imagePath);
    Intent shareIntent = new Intent(Intent.ACTION_SEND);
    shareIntent.setType("image/*");
    Uri photoURI = FileProvider.getUriForFile(context, FILE_PROVIDER_AUTHORITY, imageFile);
    shareIntent.putExtra(Intent.EXTRA_STREAM, photoURI);
    context.startActivity(shareIntent);
}

Here is my file provider code in my Manifest file:

    <provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="com.aaronapp.hideme.fileprovider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths" />

Here is the file_paths file which contains the file paths.

<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-cache-path name="my_cache" path="." />
    <external-path name="my_images" path="Pictures/" />
</paths>

Here is the share method that is invoked inside the MainActivity class.

/**
 * OnClick method for the share button, saves and shares the new bitmap.
 */
@OnClick(R.id.share_button)
public void shareMe() {
    // Delete the temporary image file
    BitmapUtils.deleteImageFile(this, mTempPhotoPath);

    // Share the image
    BitmapUtils.shareImage(this, mTempPhotoPath);
}

If you need anymore information that I forgot to show I'll be happy to supply it. I'm trying to fix this issue and get my images to share to different apps(I know Facebook has a certain way of sharing images, but I will tackle that later)

You can also replicate this issue by downloading the Hide me, Emoji App on the google play store, taking a picture and trying to share it across your apps.https://play.google.com/store/apps/details?id=com.aaronapp.hideme

Upvotes: 0

Views: 149

Answers (5)

Sachin Varma
Sachin Varma

Reputation: 2235

Make use of Picasso, sharing you a working code from my project.

Put this in your App level gradle,

implementation 'com.squareup.picasso:picasso:2.71828'

Code used is given below,

static void shareImage(Context context, String imagePath) {
    // Create the share intent and start the share activity
    Picasso.with(getApplicationContext())
                .load(imagePath)
                .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));
                    if (!TextUtils.isEmpty(des)) {
                      i.putExtra(Intent.EXTRA_TEXT, des);
                    }
                    startActivity(Intent.createChooser(i, "Share Image"));
                  }

                  @Override
                  public void onBitmapFailed(Drawable errorDrawable) {

                  }

                  @Override
                  public void onPrepareLoad(Drawable placeHolderDrawable) {
                  }
                });
      }


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

Hope it may help you.

Upvotes: 1

Jaspreet Kaur
Jaspreet Kaur

Reputation: 1720

I have done following changes in your code, i had tested app after changes and able to share image now. Please check and let me know.

  1. in MainActivity, shareMe method you have delete the temp file before sharing that why the error was occured. now i have delete the Temp file after sharing.

    Modified code in MainActivity.java

public static final int REQUEST_CODE_SHARE_FILE = 100;
public void shareMe()
{
       // BitmapUtils.deleteImageFile(this, mTempPhotoPath); delete temp file in on activity result.
        BitmapUtils.shareImage(MainActivity.this, mTempPhotoPath);
}   

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data)
    {
        //If the image capture activity was called and was successful
        if(requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK)
        {
            processAndSetImage();
        }
        else if(requestCode == REQUEST_CODE_SHARE_FILE)
        {
            BitmapUtils.deleteImageFile(this, mTempPhotoPath);
        }else {
            BitmapUtils.deleteImageFile(this, mTempPhotoPath);
        }
    }

Modified code in BitmapUtils.java

 static void shareImage(Activity activity, String imagePath) {
        // Create the share intent and start the share activity
        File imageFile = new File(imagePath);
        Intent shareIntent = new Intent(Intent.ACTION_SEND);
        shareIntent.setType("image/*");
        Uri photoURI = FileProvider.getUriForFile(activity, FILE_PROVIDER_AUTHORITY, imageFile);
        shareIntent.putExtra(Intent.EXTRA_STREAM, photoURI);
        activity.startActivityForResult(shareIntent,MainActivity.REQUEST_CODE_SHARE_FILE);
    }
  1. I am testing your app on the device with Android version 6.0 and app gets crashed every time. Inside detectFacesandOverlayEmoji method, on line number 32(SparseArray faces = detector.detect(frame);)

    a) Sometimes app remains open without showing anything in logcat. b) Sometimes app crashed with following error in logcat.

05-24 11:00:27.192 17880-17880/com.aaronapp.hideme E/AndroidRuntime: FATAL EXCEPTION: main
                                                                     Process: com.aaronapp.hideme, PID: 17880
                                                                     java.lang.OutOfMemoryError: Failed to allocate a 51916812 byte allocation with 16765168 free bytes and 36MB until OOM
                                                                         at com.google.android.gms.vision.Frame.zzTM(Unknown Source)
                                                                         at com.google.android.gms.vision.Frame.getGrayscaleImageData(Unknown Source)
                                                                         at com.google.android.gms.vision.face.FaceDetector.detect(Unknown Source)
                                                                         at com.aaronapp.hideme.HideMe.detectFacesandOverlayEmoji(HideMe.java:32)
                                                                         at com.aaronapp.hideme.MainActivity.processAndSetImage(MainActivity.java:153)
                                                                         at com.aaronapp.hideme.MainActivity.onActivityResult(MainActivity.java:133)
                                                                         at android.app.Activity.dispatchActivityResult(Activity.java:6428)
                                                                         at android.app.ActivityThread.deliverResults(ActivityThread.java:3695)
                                                                         at android.app.ActivityThread.handleSendResult(ActivityThread.java:3742)
                                                                         at android.app.ActivityThread.-wrap16(ActivityThread.java)
                                                                         at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1393)
                                                                         at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                         at android.os.Looper.loop(Looper.java:148)
                                                                         at android.app.ActivityThread.main(ActivityThread.java:5417)
                                                                         at java.lang.reflect.Method.invoke(Native Method)
                                                                         at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                                                                         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

Upvotes: 1

Jaspreet Kaur
Jaspreet Kaur

Reputation: 1720

Please try this code, this is working in my case

File filePath = new File(FIlePath);
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND_MULTIPLE);
ArrayList<Uri> uriArrayList = new ArrayList<>();
uriArrayList.add(getUriFromFilePath(filePath));
intent.setType("image/*");
intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uriArrayList);
startActivity(intent);



public Uri getUriFromFilePath(Context theCtx, File theSrcPath) {
        Uri requirdUri = null;
        // observation
        // SDKversion: 25 -- Uri.fromFile Not working, So we have to use Provider


        // FileProvider.getUriForFile will not work when the file is located in external Sdcard.
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            requirdUri = FileProvider.getUriForFile(theCtx,
                    theCtx.getApplicationContext().getPackageName() + PROVIDER_FILE_EXTENSION,
                    theSrcPath);
        } else {
            requirdUri = Uri.fromFile(theSrcPath);
        }

        return requirdUri;
    }

Upvotes: 1

Jaspreet Kaur
Jaspreet Kaur

Reputation: 1720

This will allow you to read files from Internal or external sdcard.

Add this in manifest.xml

<!-- this is For Access External file Storage -->
<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="com.demo.test.provider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths"/>
</provider>

file_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path
        name="external_files"
        path="." />
    <root-path
        name="external_files"
        path="/storage/"/>
</paths>

Upvotes: 1

Priyank Patel
Priyank Patel

Reputation: 12382

Try with adding flag Intent.FLAG_GRANT_READ_URI_PERMISSION to Intent

The file you want to share with another app, you need to allow the client app to access the file. To allow access, grant permissions to the client app by adding the content URI to an Intent and then setting permission flags on the Intent.

// Grant temporary read permission to the content URI
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

The permissions you grant are temporary and expire automatically when the receiving app's task stack is finished.

Upvotes: 1

Related Questions