sharing image on sdcard using ACTION_SEND. The image deletes!
<p>I have a strange problem in my android app. I have an activity which shows an image. The image is saved on the SD card. The user can choose share from the context menu which is coded with the standard ACTION_SEND code. Please see below    </p>

<p><code>public void shareImage(){
        Intent emailShare = new Intent(android.content.Intent.ACTION_SEND);
        emailShare.setType("image/jpeg");
        emailShare.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        emailShare.putExtra(Intent.EXTRA_STREAM,uriId);
        startActivity(Intent.createChooser(emailShare,"Send picture using:"));
    }</code>   </p>

<p>Where uriId is the uri of the image.</p>

<p>This works and the image can be sent to facebook or whatever. But if I then exit my app, rotate the screen the image is missing. I get a file io error in the log when i try and retrieve the image. I have used Astro to search for the image but it is nowhere to be found!</p>

<p>I will post the entire class below. If anyone has any ideas I would be very appreciative.</p>

<p>Stephen</p>

<pre><code>'package com.pengilleys.fishingsnapz;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.graphics.RectF;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.FloatMath;
import android.util.Log;
import android.view.Display;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageView;
import android.widget.TextView;

public class ImagePreview extends Activity implements OnTouchListener{
    protected Context mContext;
    static final String TAG = "ImagePreview";
    static final int SHARE_ID = 0;
    static final int EDIT_ID = 1;
    static final int PROGRESS_DIALOG = 0;
ProgressDialog progressDialog;
    private Bundle extras;
protected static Bitmap bm;
protected DBAdapter db = new DBAdapter(ImagePreview.this);
Long id;
private FacebookManager fb;
private Uri uriId;


//Touch gesture related variables
Matrix matrix = new Matrix();
Matrix savedMatrix = new Matrix();

// Remember some things for zooming
PointF start = new PointF();
PointF mid = new PointF();

float oldDist = 0;

// We can be in one of these 3 states
static final int NONE = 0;
static final int DRAG = 1;
static final int ZOOM = 2;
int mode = NONE;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.image_view);
    mContext = this;


    try{
        extras = getIntent().getExtras();
        id = (Long) extras.get(DBAdapter.KEY_ROWID);    
        Log.d(TAG,"id="+id);

        ImageView imageV = (ImageView)findViewById(R.id.image_preview);
        imageV.setOnTouchListener(this);

        //get image
        bm = getImage(id);
        imageV.setImageBitmap(bm);
        imageV.setImageMatrix(matrix);

        //get snap details for text overlay
        ArrayList&lt;String&gt; details = new ArrayList&lt;String&gt;();
        details = getSnapDetails(id);

        prepareSnapDetails(details);                  



    }catch(Exception e){
        Log.e(TAG,e.toString());
    }finally{

    }

}

private ArrayList&lt;String&gt; getSnapDetails(long id){
    ArrayList&lt;String&gt; fishDetails = new ArrayList&lt;String&gt;();
    Cursor cursor;

    //open the database and grab the snap details
    db.open();
    cursor = db.fetchNote(id);
    db.close();

    //loop through cursor results and put into our arraylist&lt;string&gt;
    try{
        startManagingCursor(cursor);
        cursor.moveToFirst();
        //only one row but multiple columns, manually assign columns
        String value = cursor.getString(cursor.getColumnIndexOrThrow("date"));
        value = checkValue(value);
        fishDetails.add(value);
        value = cursor.getString(cursor.getColumnIndexOrThrow("type"));
        value = checkValue(value);
        fishDetails.add(value);
        value = cursor.getString(cursor.getColumnIndexOrThrow("weight"));
        value = checkValue(value);
        fishDetails.add(value);
        value = cursor.getString(cursor.getColumnIndexOrThrow("place"));
        value = checkValue(value);
        fishDetails.add(value);


    }catch(Exception e){
        Log.e(TAG,e.toString());
    }
    db.close();
    return fishDetails;
}

    private String checkValue(String value){
        if(value==""){value="-";};
        return value;
    }

private boolean prepareSnapDetails(ArrayList&lt;String&gt; details){
    TextView tx = (TextView)findViewById(R.id.details_overlay);
    tx.setText("");
    String detail="";
    String[] labels = new String[]{"Date: ","Type: ","Weight: ","Place: "};
    try{        
        for(int i=0;i&lt;4;i++){
            //add text details to textview
            detail = labels[i] + details.get(i) + '\n';
            Log.d(TAG,detail);
            CharSequence ch = detail.subSequence(0,detail.length());
            tx.append(ch);
        }
    }catch(Exception e){
        Log.e(TAG,e.toString());

    }
    return true;
}

private Bitmap getImage(Long id){
    try{
        db.open();
        Cursor c = db.fetchUri(id);
        uriId = Uri.parse(c.getString(c.getColumnIndexOrThrow(DBAdapter.KEY_URI)));

        ContentResolver cr = getContentResolver();

        Bitmap bitmap = MediaStore.Images.Media.getBitmap(cr,uriId);

        Display display = getWindowManager().getDefaultDisplay();
        int width = display.getWidth();
        int height = display.getHeight();

        if(bitmap.getWidth() &gt; width || bitmap.getHeight() &gt; height){
            float heightRatio = (float) height / bitmap.getHeight();
            float widthRatio = (float) width / bitmap.getWidth();
            Log.d(TAG,"height="+heightRatio + " width=" + widthRatio);
            matrix.setScale(widthRatio, heightRatio);
        }else{
            matrix.setTranslate(1f,1f);
            Log.d(TAG,"bitmap.getWidth="+bitmap.getWidth() + " vs width="+width);
            Log.d(TAG,"bitmap.getHeight="+bitmap.getHeight() + " vs height="+height);
        }

        db.close();
        return bitmap;

    } catch (FileNotFoundException e) {
        Log.e("GETIMAGE",e.toString());
        return null;
    } catch (IOException e) {
        Log.e("GETIMAGE",e.toString());
        return null;
    }catch(Exception e){
        Log.e("GETIMAGE",e.toString());
        return null;
    }
}

public void shareImage(){
    Intent emailShare = new Intent(android.content.Intent.ACTION_SEND);
    emailShare.setType("image/jpeg");
    emailShare.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    emailShare.putExtra(Intent.EXTRA_STREAM,uriId);
    startActivity(Intent.createChooser(emailShare,"Send picture using:"));
}

@Override
public boolean onTouch(View v, MotionEvent event) {
    ImageView view = (ImageView) v;
    final float MIN_ZOOM = 0.25f;
    final float MAX_ZOOM = 4;
    float height = view.getDrawable().getIntrinsicHeight();
    float width = view.getDrawable().getIntrinsicWidth();
    float[] matrixValues = new float[9];
    RectF viewRect = new RectF(0, 0, view.getWidth(), view.getHeight());

    dumpEvent(event);



    switch(event.getAction() &amp; MotionEvent.ACTION_MASK){
    case MotionEvent.ACTION_DOWN:
        savedMatrix.set(matrix);
        start.set(event.getX(), event.getY());
        Log.d(TAG,"mode=DRAG");
        mode=DRAG;
        break;
    case MotionEvent.ACTION_UP:
    case MotionEvent.ACTION_POINTER_DOWN:
        oldDist=spacing(event);
        Log.d(TAG, "oldDist=" + oldDist);
        if(oldDist&gt;10f){
            savedMatrix.set(matrix);
            midPoint(mid,event);
            mode=ZOOM;
            Log.d(TAG,"mode=ZOOM");
        }

        break;

    case MotionEvent.ACTION_MOVE:

        if(mode==DRAG){
            Log.d(TAG,"mode=MOVE");
            matrix.set(savedMatrix);
            // limit pan
            matrix.getValues(matrixValues);
            float currentY = matrixValues[Matrix.MTRANS_Y];
            float currentX = matrixValues[Matrix.MTRANS_X];
            float currentScale = matrixValues[Matrix.MSCALE_X];
            float currentHeight = height * currentScale;
            float currentWidth = width * currentScale;
            float dx = event.getX() - start.x;
            float dy = event.getY() - start.y;
            float newX = currentX+dx;
            float newY = currentY+dy;   

            RectF drawingRect = new RectF(newX, newY, newX+currentWidth, newY+currentHeight);
            float diffUp = Math.min(viewRect.bottom-drawingRect.bottom, viewRect.top-drawingRect.top);
            float diffDown = Math.max(viewRect.bottom-drawingRect.bottom, viewRect.top-drawingRect.top);
            float diffLeft = Math.min(viewRect.left-drawingRect.left, viewRect.right-drawingRect.right);
            float diffRight = Math.max(viewRect.left-drawingRect.left, viewRect.right-drawingRect.right);
            if(diffUp &gt; 0 ){
            dy +=diffUp;    
            }
            if(diffDown &lt; 0){
            dy +=diffDown;
            }   
            if( diffLeft&gt; 0){   
            dx += diffLeft;
            }
            if(diffRight &lt; 0){
            dx += diffRight;
            }
            matrix.postTranslate(dx, dy);
        }else if(mode==ZOOM){
            float newDist= spacing(event);

            if(newDist&gt;10f){
                matrix.set(savedMatrix);
                float scale = newDist / oldDist;
                Log.d(TAG,"Scale="+scale);
                matrix.getValues(matrixValues);
                float currentScale = matrixValues[Matrix.MSCALE_X];
                Log.d(TAG,"currentScale="+currentScale);
                // limit zoom
                if (scale * currentScale &gt; MAX_ZOOM) {
                scale = MAX_ZOOM / currentScale;
                } else if (scale * currentScale &lt; MIN_ZOOM) {
                scale = MIN_ZOOM / currentScale;
                }
                matrix.postScale(scale, scale, mid.x, mid.y);
            }
        }
        break;
    }
        //perform the transformation
        view.setImageMatrix(matrix);

    return true;
}

private static float spacing(MotionEvent event){
    float x = event.getX(0) - event.getX(1);
    float y = event.getY(0) - event.getY(1);
    return FloatMath.sqrt(x * x + y * y);
}

private static void midPoint(PointF point, MotionEvent event){
    float x = event.getX(0) + event.getX(1);
    float y = event.getY(0) + event.getY(1);
    point.set(x / 2, y / 2);
}

/** Show an event in the logcat view for debugging **/
private void dumpEvent(MotionEvent event){
    String names[] = {"DOWN","UP","MOVE","CANCEL","OUTSIDE","POINTER_DOWN","POINTER_UP","7?","8?","9?"};
    StringBuilder sb = new StringBuilder();
    int action = event.getAction();
    int actionCode = action &amp; MotionEvent.ACTION_MASK;
    sb.append("event ACTION_").append(names[actionCode]);
    if(actionCode==MotionEvent.ACTION_POINTER_DOWN 
            || actionCode==MotionEvent.ACTION_POINTER_UP){
        sb.append("pid ").append(
        action &gt;&gt; MotionEvent.ACTION_POINTER_ID_SHIFT);
        sb.append(")");
    };
    sb.append(" [");
    for(int i=0;i &lt; event.getPointerCount();i++){
        sb.append("#").append(i);
        sb.append("(pid ").append(event.getPointerId(i));
        sb.append(")=").append((int) event.getX(i));
        sb.append(",").append((int) event.getY(i));
        if(i+1 &lt; event.getPointerCount())
            sb.append(";");
    }
    sb.append("]");
    Log.d("DUMP", sb.toString());
}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    super.onCreateOptionsMenu(menu);
    menu.add(0, SHARE_ID, 0, R.string.share_id);
    menu.add(0,EDIT_ID,0,R.string.edit_details);
    return true;
}

@Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {
    switch(item.getItemId()) {
        case SHARE_ID:
            try{
                shareImage();

                }catch(Exception e){
                    Log.e(TAG,e.toString());
                }
            return true;

        case EDIT_ID:
            try{
                Intent intent = new Intent(mContext,SnapDetails.class);
                intent.putExtra(DBAdapter.KEY_ROWID,id);
                startActivityForResult(intent,FishingSnapz.SNAP_EDIT);

            }catch(Exception e){
                Log.e(TAG,e.toString());
            }

    }

    return super.onMenuItemSelected(featureId, item);
}

@Override
protected void onResume(){
    super.onResume();

}

@Override
protected void onActivityResult (int requestCode, int resultCode, Intent data){
    super.onActivityResult(requestCode, resultCode, data);

    //Required by facebook single sign on - check that we are returning to activity from FB
    if(data!=null){
        fb.authorizeCallback(requestCode, resultCode, data);
    }else{
        extras = getIntent().getExtras();
        id = (Long) extras.get(DBAdapter.KEY_ROWID); 

        //get snap details for text overlay
        ArrayList&lt;String&gt; details = new ArrayList&lt;String&gt;();
        details = getSnapDetails(id);

        prepareSnapDetails(details);      

    }
}
</code></pre>

<p>}
'</p>
