4

There's a little documentation and support about how to send and share images (or files) from the assets folder for Android.

Basically, I've been supported by these links:

  1. android share images from assets folder
  2. http://www.nowherenearithaca.com/2012/03/too-easy-using-contentprovider-to-send.html

and many similar.

But anyway, the code I'm using is:

CONTENT PROVIDER

public class AssetsProvider extends ContentProvider {
private static final String LOGTAG = "MD/AssetsProvider";

@Override
public AssetFileDescriptor openAssetFile( Uri uri, String mode ) throws FileNotFoundException
{
    Log.v(LOGTAG, "AssetsGetter: Open asset file");

    AssetManager am = getContext( ).getAssets( );

    String file_name = uri.getPath().substring(1, uri.getPath().length());
    //String file_name = uri.getLastPathSegment();
    // Neither of the two lines above work for me

    if( file_name == null )
        throw new FileNotFoundException( );

    AssetFileDescriptor afd = null;

    try
    {
        afd = am.openFd( file_name );
    }
    catch(IOException e)
    {
        e.printStackTrace( );
    }

    return afd;//super.openAssetFile(uri, mode);
}

@Override
public String getType( Uri p1 )
{
    // TODO: Implement this method
    return null;
}

@Override
public int delete( Uri p1, String p2, String[] p3 )
{
    // TODO: Implement this method
    return 0;
}

@Override
public Cursor query( Uri p1, String[] p2, String p3, String[] p4, String p5 )
{
    // TODO: Implement this method
    return null;
}

@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
@Override
public Cursor query( Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder, CancellationSignal cancellationSignal )
{
    // TODO: Implement this method
    return super.query( uri, projection, selection, selectionArgs, sortOrder, cancellationSignal );
}

@Override
public Uri insert( Uri p1, ContentValues p2 )
{
    // TODO: Implement this method
    return null;
}

@Override
public boolean onCreate( )
{
    // TODO: Implement this method
    return false;
}

@Override
public int update( Uri p1, ContentValues p2, String p3, String[] p4 )
{
    // TODO: Implement this method
    return 0;
}
}

Which I don't like very much because it requires API 16.

ANDROID MANIFEST (inside <application> tag)

<provider
    android:name="package.name.utils.AssetsProvider"
    android:authorities="package.name"
    android:grantUriPermissions="true"
    android:exported="true" />

CODE TO SHARE IMAGE

Uri theUri = Uri.parse("content://package.name/share_picture.png");
Intent theIntent = new Intent(Intent.ACTION_SEND);
theIntent.setType("image/*");
theIntent.putExtra(Intent.EXTRA_STREAM,theUri);
theIntent.putExtra(android.content.Intent.EXTRA_SUBJECT,"");
theIntent.putExtra(android.content.Intent.EXTRA_TEXT, "");
startActivity(theIntent);

and I can see my chooser successfully.

MY MAIN PROBLEM IS

I can get my picture shared IN SOME APPS but not other apps. For example: Apps where I can share my picture:

  • Google Hangouts

  • Twitter

  • WhatsApp

  • Skype (it stucks in "sending")

  • Instagram

  • Dropbox

Apps where I can't share my picture:

  • Inbox by Gmail

  • Gmail

  • Any app for image editing

  • Messages

  • Slack

  • Linkedin

  • List item

  • Hipchat

  • Messenger (by Facebook)

  • Facebook

is there anything wrong with the apps where I can't share? or am I doing anything wrong on the code? maybe the setType function?

Thank you in advance.

Regards.

Rafael.


The problem also appears when sharing an image from File, so nothing related with Assets is the problem:

This morning I've done this test:

    Intent shareIntent = new Intent(Intent.ACTION_SEND);
    Uri phototUri = Uri.parse(folderToSaveFiles+relativeNameSharePicture);

    shareIntent.setData(phototUri);
    shareIntent.setType("image/png");
    shareIntent.putExtra(Intent.EXTRA_STREAM, phototUri);
    startActivity(Intent.createChooser(shareIntent, "Share Via"));

and the same happens!!

Community
  • 1
  • 1
Rafael Ruiz Muñoz
  • 5,333
  • 6
  • 46
  • 92

3 Answers3

4

The simplest answer is to use my StreamProvider, which handles all of this for you. If that does not work with certain of the apps that you cite, file issues with symptoms (e.g., stack traces from those apps). However, I am not using AssetFileDescriptor for assets (for compatible devices), and that's on my to-do list to change.

The next-simplest answer is to copy the asset to internal storage and use FileProvider, along with my LegacyCompatCursorWrapper, as seen in this sample app.

If you wish to stick with your code:

Step #1: Implement a real getType() method, to return the MIME type.

Step #2: Implement a real query() method, one that handles the OpenableColumns, and ideally either uses my LegacyCompatCursorWrapper or otherwise deals with poorly-written clients.

Step #3: Add FLAG_GRANT_READ_URI_PERMISSION to your Intent and change android:exported to false.

Step #4: Get rid of EXTRA_TEXT, as the ACTION_SEND protocol supports either EXTRA_TEXT or EXTRA_STREAM, not both.

Community
  • 1
  • 1
CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
0

Have you tried returning something different from null in the getType() method? It might happen that some applications check it and, if not recognized, they will not accept what you're sending. (You could easily log something there to see at least if other apps are calling it)

Sebastian
  • 1,076
  • 9
  • 24
0

The main problem is that the Uri has to be parsed from a Filewith Uri.fromFile(File file) then everything works ok!

Rafael Ruiz Muñoz
  • 5,333
  • 6
  • 46
  • 92