0

So I have a Share button that will share an image and a body of text.

On Nougat (API 25) and Oreo (API 26), it works absolutely perfectly. But when it comes to a couple older version it doesn't work as expected.

Marshmallow (API 23): Inserts the image just fine but no body of text. Lollipop (API 22): Crashes when you push the Share button with popup error "Unfortunately, Messaging has stopped." LOGCAT isn't showing me any errors when this happens.

Here is my share button code:

if (id == R.id.action_shareWine) {
        Intent intentShare = new Intent(Intent.ACTION_SEND);
        intentShare.putExtra(intentShare.EXTRA_STREAM, imageURI);
        intentShare.setType("image/*");
        intentShare.putExtra(Intent.EXTRA_TEXT, "body of text goes here");
        if (intentShare.resolveActivity(getPackageManager()) != null) {
            startActivity(intentShare);
        }
        return true;
    }

Here is a picture to give a visual idea of whats going on:

enter image description here

Anyone have any ideas what could be going on here?


UPDATE 1

Here is the crash log for the Lollipop emulator:

FATAL EXCEPTION: Mms-1
Process: com.android.mms, PID: 7570

java.lang.IllegalStateException: Couldn't read row 0, col 0 from CursorWindow.  Make sure the Cursor is initialized correctly before accessing data from it.

Which I'm not sure why it is happening because the cursor is loading the image just fine in an ImageView in that same activity.

andrdoiddev
  • 349
  • 1
  • 3
  • 15
  • What is the value of `imageURI`? Also, since it is your image and you know what the MIME type is, why are you using a wildcard? – CommonsWare Oct 13 '17 at 19:46
  • 'imageURI = Uri.parse(cursor.getString(cursor.getColumnIndexOrThrow(WineContract.WineEntry.COLUMN_WINE_IMAGE)));' I know the cursor does have the correct URI because that same code is able to set an imageview in the activity. – andrdoiddev Oct 13 '17 at 19:48
  • Like the previous comment said, I'm pretty sure that "image/*" is not supported by all manufacturer and devices. You need to specify the exact mine type "image/jpeg" or "image/png" – AlonsoFloo Oct 13 '17 at 19:49
  • That is how you retrieved the value for `imageURI`. What is *the value* of `imageURI`? – CommonsWare Oct 13 '17 at 19:50
  • The wildcard seemed to work for me so I figure it would work. I have since changed the * to png. But nonetheless, I'm still having the same issue. – andrdoiddev Oct 13 '17 at 19:51
  • @CommonsWare The value of imageURI: content://jeremy.com.wineofmine.fileprovider/test/Android/data/jeremy.com.wineofmine/files/Pictures/JPEG_20171013_134645_1091817932.jpg – andrdoiddev Oct 13 '17 at 19:53

2 Answers2

1

Call addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) on the ACTION_SEND Intent, to allow third parties the ability to read the content identified by the Uri.

Also, since the image would appear to be a JPEG (based on the file extension), the MIME type is image/jpeg, not image/* or image/png.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • Oops. Not sure why I thought it was png. That has been changed to jpeg. But even with that permission flag, I'm having the same problems on both Lollipop and Marshmallow. – andrdoiddev Oct 13 '17 at 19:58
  • 1
    @andrdoiddev: Well, in terms of the no-text part, please understand that there is no requirement for any `ACTION_SEND` implementation to support both `EXTRA_TEXT` and `EXTRA_STREAM` on the same `Intent`. Some will, some won't, as that's beyond what the `ACTION_SEND` documentation calls for. In terms of Lollipop, make sure that you are checking LogCat for the entire device, not just for your app, as the crash is not coming from your app. – CommonsWare Oct 13 '17 at 20:02
  • I just found the crash log for the Lollipop error. I added it to the bottom of the original post. It says that it couldn't read from the cursor, even though the cursor is correctly putting an image from the URI into an ImageView into that same activity. – andrdoiddev Oct 13 '17 at 20:28
  • 2
    @andrdoiddev: If I had to guess, you are running into a variation on [this problem](https://stackoverflow.com/questions/24195674/image-share-intent-works-for-gmail-but-crashes-fb-and-twitter/25020642#25020642). – CommonsWare Oct 13 '17 at 20:51
0

For More Details

working in Oreo and Marshmallow Version Read this

https://developer.android.com/reference/android/support/v4/content/FileProvider.html

Source Code

https://drive.google.com/open?id=1vfO43dMSt096CMp6nrOJNl3fJAf6MPwG

create xml folder inside providers_path.xml

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



<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.holostik.sharescreenshotexample">

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.FLASHLIGHT" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-feature android:name="android.hardware.camera" />
    <uses-permission android:name="android.permission.CAMERA"></uses-permission>


    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>


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


    </application>

</manifest>

package com.holostik.sharescreenshotexample;

import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.FileProvider;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Toast;

import com.holostik.sharescreenshotexample.share.ScreenshotType;
import com.holostik.sharescreenshotexample.share.ScreenshotUtils;

import java.io.File;
import java.io.FileOutputStream;
import java.util.Random;

public class MainActivity extends AppCompatActivity {
    int n;
    String photoPath;

    LinearLayout rootContent;
    ImageView iv_share;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        rootContent = (LinearLayout) findViewById(R.id.rootContent);
        iv_share = (ImageView) findViewById(R.id.iv_share);

        iv_share.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

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

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

                        takeScreenshot(ScreenshotType.FULL);

                    } else {
                        ActivityCompat.requestPermissions(MainActivity.this,
                                new String[]{Manifest.permission.CAMERA,
                                        Manifest.permission.READ_EXTERNAL_STORAGE,
                                        Manifest.permission.WRITE_EXTERNAL_STORAGE
                                }, 1);
                    }
                } else {
                    Log.e("MainActivity", "Lower Than MarshMallow");
                    takeScreenshot(ScreenshotType.FULL);
                }

            }
        });

    }


    /*  Method which will take screenshot on Basis of Screenshot Type ENUM  */
    private void takeScreenshot(ScreenshotType screenshotType) {
        Bitmap b = null;
        switch (screenshotType) {
            case FULL:
                b = ScreenshotUtils.getScreenShot(rootContent);
                break;
            case CUSTOM:
                //If Screenshot type is CUSTOM
                break;
        }

        //If bitmap is not null
        if (b != null) {
//            showScreenShotImage(b);//show bitmap over imageview
            Log.e("keshav", "bitmap is -- > " + b);

            SaveImage(b);

            shareScreenshot();
      /*      File saveFile = ScreenshotUtils.getMainDirectoryName(MainActivity.this);//get the path to save screenshot
            File file = ScreenshotUtils.store(b, "screenshot" + screenshotType + ".jpg", saveFile);//save the screenshot to selected path
            shareScreenshot(file);//finally share screenshot
            Log.e("file Path", String.valueOf(file));
*/

        } else
            //If bitmap is null show toast message
            Toast.makeText(MainActivity.this, R.string.screenshot_take_failed, Toast.LENGTH_SHORT).show();

    }

    private void SaveImage(Bitmap finalBitmap)
    {
        String root = Environment.getExternalStorageDirectory().toString();
        File myDir = new File(root + "/saved_images");
        myDir.mkdirs();
        Random generator = new Random();
        n = 10000;
        n = generator.nextInt(n);
        String fname = "Image-" + n + ".jpg";
        File file = new File(myDir, fname);
        if (file.exists()) file.delete();
        try {
            FileOutputStream out = new FileOutputStream(file);
            finalBitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
            out.flush();
            out.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /* TODO  Show screenshot Bitmap */
//    private void showScreenShotImage(Bitmap b) {
//        imageView.setImageBitmap(b);
//    }

    private void shareScreenshot()
    {
        photoPath = Environment.getExternalStorageDirectory() + "/saved_images" + "/Image-" + n + ".jpg";
        File F = new File(photoPath);
        //Uri U = Uri.fromFile(F);
        //  Uri U = FileProvider.getUriForFile(getActivity(), getActivity().getApplicationContext().getPackageName() + ".my.package.name.provider", F);

        // TODO your package name as well add .fileprovider
        Uri U = FileProvider.getUriForFile(MainActivity.this.getApplicationContext(), "com.holostik.sharescreenshotexample.fileprovider", F);
        Intent i = new Intent(Intent.ACTION_SEND);
        i.setType("image/png");
        i.putExtra(Intent.EXTRA_STREAM, U);
        startActivityForResult(Intent.createChooser(i, "Email:"), 1);
    }

    // TODO Share Screen SHOT End ..............
}
Community
  • 1
  • 1
Keshav Gera
  • 10,807
  • 1
  • 75
  • 53