1

I've been trying and trying to get this to work. I've gone through many examples with no luck. The problem is that the image is not attached when I try to share it, for example, using an email client. I managed to get this to work when using external storage but internal storage suits my needs better.

I click a button and then the image is saved to internal storage and right after that it is shared but there's no image.

This is from the Activity class:

int width              = size.x;
int height             = size.y;
Bitmap shareBmp        = Bitmap.createBitmap(screenBmp, 0, 0, width, height);
ContextWrapper wrapper = new ContextWrapper(getApplicationContext());
File directory         = wrapper.getDir("images", Context.MODE_PRIVATE);
File filePath          = new File(directory, "share.png");

FileOutputStream fos;

try
{
    fos = new FileOutputStream(filePath);
    shareBmp.compress(Bitmap.CompressFormat.PNG, 90, fos);
    fos.close();
}
catch (Exception aE){}

Uri uri       = Uri.parse("content://com.example.Test/share.png");
Intent intent = new Intent();

intent.setAction(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_STREAM, uri);
intent.setType("image/png");
startActivity(Intent.createChooser(intent, "Share Image"));

Here's the ImageProvider class:

public class ImageProvider extends ContentProvider
{
    @Override
    public ParcelFileDescriptor openFile(Uri aUri, String aMode) throwsFileNotFoundException
    {
        File file = new File(getContext().getFilesDir(), aUri.getPath());

        if (file.exists())
        {
            return (ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY));
        }

        throw new FileNotFoundException(aUri.getPath());
    }

    @Override
    public boolean onCreate()
    {
        return false;
    }

    @Override
    public int delete(Uri aUri, String aSelection, String[] aSelectionArgs)
    {
        return 0;
    }

    @Override
    public String getType(Uri aUri)
    {
        return null;
    }

    @Override
    public Uri insert(Uri aUri, ContentValues aValues)
    {
        return null;
    }

    @Override
    public Cursor query(Uri aUri, String[] aProjection, String aSelection, String[] aSelectionArgs, String aSortOrder)
    {
        return null;
    }

    @Override
    public int update(Uri aUri, ContentValues aValues, String aSelection, String[] aSelectionArgs)
    {
        return 0;
    }
}

This is from the manifest:

<provider
        android:name=".ImageProvider"
        android:authorities="com.example.Test"
        android:exported="true"/>
Yurii
  • 4,811
  • 7
  • 32
  • 41
Deeds
  • 125
  • 1
  • 12
  • see my answer here: http://stackoverflow.com/questions/15377373/how-to-put-a-video-file-in-android-custom-content-provider – dangalg Jan 26 '15 at 12:13

1 Answers1

0

Only your app can see/read/write files in it's app specific -private- storage. So you cannot ask other app to share from it as they cannot even 'see' those files there.

greenapps
  • 11,154
  • 2
  • 16
  • 19
  • But isn't Content Provider just the thing to use in this situation? From the developer guide: "You don't need to develop your own provider if you don't intend to share your data with other applications." – Deeds Jun 28 '14 at 18:06
  • You are right. I didn't see that you used one. Sorry for beeing to quick in this way. Now i have to look again... You said that you are saving to internal memory. But what is actually `filePath.getAbsolutePath()`? – greenapps Jun 28 '14 at 18:14
  • 1
    And compare that path with `file.getAbsolutePath()`. – greenapps Jun 28 '14 at 18:34
  • Good point. filePath: /data/data/com.example.Test/app_images/share.png and file: /data/data/com.example.Test/files/app_images/share.png. No wonder the image is not attached. How can I omit the "files" folder or is it obligatory? – Deeds Jun 29 '14 at 08:47
  • Just remove it like `file.getParentFile().getAbsolutePath();`. But maybe it is better to use the files folder on both places. – greenapps Jun 29 '14 at 08:54
  • I agree, preserving the natural folder structure is better than breaking it. How can I add the "files" folder to this: /data/data/com.example.Test/app_images/share.png? – Deeds Jun 29 '14 at 10:48
  • Your `wrapper.getDir()` delivers a path without `/files/`. So you have to manupilate `File directory` a bit before you use it in `File filePath`. You could alternatively just do a textual replace in the final path. Or adapt `wrapper.getDir()`. – greenapps Jun 29 '14 at 10:59
  • I did try to do it like this: wrapper.getDir("files/images", Context.MODE_PRIVATE) but this didn't work: File app_files/images contains a path separator. I'd rather manipulate this than the final path. – Deeds Jun 29 '14 at 11:48
  • Why not adapt `getDir()` instead, as you tried now, calling with a different parameter? – greenapps Jun 29 '14 at 11:51
  • I don't know what you mean. Like wrapper.getDir("files", Context.MODE_PRIVATE)? It always adds the prefix "app_". In this case it would be "app_files". – Deeds Jun 29 '14 at 12:08
  • 1
    I supposed that you wrote the ContextWrapper class. So then you can adapt the implementation of getDir(). Or if it has a getDir(), does it have a getFilesDir() too? – greenapps Jun 29 '14 at 12:24
  • It works when using getFilesDir() but now I can't define Context.MODE_PRIVATE. But I guess there's no need because I'm not creating a new folder and the "files" folder is private by default? – Deeds Jun 29 '14 at 12:51
  • Yes it is private by default and cannot be changed so no need for a specifier. I'm not sure though if it exists by default on all devices so mayby you better check with File.exists() first and if not use File.mkdirs(). Well as you have to create 'app_images' all can be done in one. – greenapps Jun 29 '14 at 12:57
  • OK. That finally solved the problem, then! Thank you for your constructive comments. I'll grade the best ones. – Deeds Jun 29 '14 at 13:04