Search code examples
androidandroid-actionbarsharescreenshotshareactionprovider

Share screenshot using ShareActionProvider of my apps current view


I've looked at all relevant similar post and not one answers my question.

My program sets up a ShareActionProvider to take a screenshot of the current view and share it with any app that can interact with .png images.

Problem: The shared screenshot is always the previous screenshot meaning that I have to click the share button in the action bar twice to get a screenshot of the current page or fragment view. I want the user to be able to just press the button once. Additionally, is it possible to not have screenshot taken when the activity is first created but wait until the share button is pressed.

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);

    // Find the MenuItem that we know has the ShareActionProvider
    MenuItem shareItem = menu.findItem(R.id.menu_item_share);

    // Get its ShareActionProvider
    mShareActionProvider = (ShareActionProvider) shareItem.getActionProvider();

    setShareIntent(getDefaultScreenshotShareIntent());

    mShareActionProvider.setOnShareTargetSelectedListener(MainActivity.this);

    // Return true so Android will know we want to display the menu
    return true;
}

public boolean onShareTargetSelected (ShareActionProvider source, Intent intent) {

    setShareIntent(getDefaultScreenshotShareIntent());

    return false;
}

// Call to update the share intent
// Connect the dots: give the ShareActionProvider its Share Intent
private void setShareIntent(Intent shareIntent) {
    if (mShareActionProvider != null) {
        mShareActionProvider.setShareIntent(shareIntent);
    }
}

private Uri saveScreenShotDirectoryLocation() {
    ContentValues values = new ContentValues();
    values.put(MediaStore.Images.Media.TITLE, "Some Title");
    values.put(MediaStore.Images.Media.MIME_TYPE, "image/png");
    Uri uri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
            values);

    return uri;
}

private void screenShotHandler(Uri uri) {
    Bitmap screenShot = takeScreenShot(MainActivity.this);

    OutputStream outstream;
    try {
        outstream = getContentResolver().openOutputStream(uri);
        screenShot.compress(Bitmap.CompressFormat.PNG, 100, outstream);
        outstream.flush();
        outstream.close();
    } catch (Exception e) {
        System.err.println(e.toString());
    }
}

private Intent getDefaultScreenshotShareIntent() {

    Uri uri = saveScreenShotDirectoryLocation();

    Intent intent = new Intent(Intent.ACTION_SEND);

    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
    intent.setType("image/png");

    long currenttime = System.currentTimeMillis();

    intent.putExtra(Intent.EXTRA_SUBJECT, "Some Title" + currenttime);

    File path = Environment.getDataDirectory();
    long usablePartitionSpace = path.getUsableSpace();

    if (usablePartitionSpace >= SCREENSHOT_FILE_SIZE_IN_BYTES ) {
        screenShotHandler(uri);
        intent.putExtra(Intent.EXTRA_STREAM, uri);
    } else {
        Toast.makeText(this, "Not enough freespace for screenshot", Toast.LENGTH_SHORT).show();
    }

    intent.putExtra(Intent.EXTRA_TEXT, "Some Title");

    File file = new File(uri.getPath());
    file.delete();

    return intent;
}

private static Bitmap takeScreenShot(Activity activity)
{
    View view = activity.getWindow().getDecorView();
    //View view = (View) MainActivity.viewPager.getChildAt(MainActivity.viewPager.getCurrentItem());
    view.setDrawingCacheEnabled(true);
    view.buildDrawingCache();
    Bitmap b1 = view.getDrawingCache();
    Rect frame = new Rect();
    activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
    int statusBarHeight = frame.top;
    int width = activity.getWindowManager().getDefaultDisplay().getWidth();
    int height = activity.getWindowManager().getDefaultDisplay().getHeight();

    Bitmap b = Bitmap.createBitmap(b1, 0, statusBarHeight, width, height  - statusBarHeight);
    view.destroyDrawingCache();
    return b;
}

My edited code:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);

    // Find the MenuItem that we know has the ShareActionProvider
    MenuItem shareItem = menu.findItem(R.id.menu_item_share);

    // Get its ShareActionProvider
    mShareActionProvider = (ShareActionProvider) shareItem.getActionProvider();

    Uri uri = saveScreenShotDirectoryLocation();
    screenShotHandler(uri);

    mShareActionProvider.setOnShareTargetSelectedListener(MainActivity.this);

    // Return true so Android will know we want to display the menu
    return true;
}

public boolean onShareTargetSelected (ShareActionProvider source, Intent intent) {

    Uri uri = saveScreenShotDirectoryLocation();
    screenShotHandler(uri);
    setShareIntent(getDefaultScreenshotShareIntent());

    return false;
}

private void screenShotHandler(Uri uri) {

    File path = Environment.getDataDirectory();
    long usablePartitionSpace = path.getUsableSpace();

   // if (usablePartitionSpace >= SCREENSHOT_FILE_SIZE_IN_BYTES ) {

        Bitmap screenShot = takeScreenShot(MainActivity.this);

        OutputStream outstream;
        try {
            outstream = getContentResolver().openOutputStream(uri);
            screenShot.compress(Bitmap.CompressFormat.PNG, 100, outstream);
            outstream.flush();
            outstream.close();
        } catch (Exception e) {
            System.err.println(e.toString());
        }
   // } else {
  //      Toast.makeText(this, "Not enough freespace for screenshot", Toast.LENGTH_SHORT).show();
  //  }
    setShareIntent(getDefaultScreenshotShareIntent());
}

 private Intent getDefaultScreenshotShareIntent() {

    Uri uri = saveScreenShotDirectoryLocation();

    Intent intent = new Intent(Intent.ACTION_SEND);

    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
    intent.setType("image/png");

    long currenttime = System.currentTimeMillis();

    intent.putExtra(Intent.EXTRA_SUBJECT, "Some Title" + currenttime);

    File path = Environment.getDataDirectory();
    long usablePartitionSpace = path.getUsableSpace();

   // if (usablePartitionSpace >= SCREENSHOT_FILE_SIZE_IN_BYTES ) {
        intent.putExtra(Intent.EXTRA_STREAM, uri);
    //}

    intent.putExtra(Intent.EXTRA_TEXT, "Some Title");

    return intent;
}

Answer: Then perhaps ShareActionProvider is not the right tool. Have an action bar item that takes the screenshot, then just use Intent.createChooser() and startActivity() to let the user share the screenshot.


Solution

  • Call setShareIntent() when you take the screenshot (e.g., somewhere in and around screenShotHandler()). Right now, you are calling setShareIntent() after the user has already chosen what to do, based on the previous Intent (onShareTargetSelected()).