简体   繁体   中英

Android Sending image from assets folder using Content Provider?

Hello~ I'm trying to send an image from the assets folder in an application via a general intent (so the user can send an image to any other application which accepts such an intent, including SMS, Facebook, and Twitter).

After looking around for a while, I found this StackOverflow question . It seemed to work quite well, and after following the comments for a bit, the method doesn't seem to be deprecated. My issue, however, is that I can't get it to work. What occurs is that I successfully choose an application from the intent chooser dialogue, but once the application, I get a toast that says "Can't find photo."

Here is my current code...

AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.mdstudios.diabeticons" >

<provider
    android:name="com.mdstudios.diabeticons.Utils.AssetsProvider"
    android:authorities="com.mdstudios.diabeticons"
    android:grantUriPermissions="true"
    android:exported="true" />

<application
...

AssetsProvider.java:

package com.mdstudios.diabeticons.Utils;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.res.AssetFileDescriptor;
import android.content.res.AssetManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.CancellationSignal;
import android.util.Log;

import java.io.FileNotFoundException;
import java.io.IOException;

/**
 * Created by jawad on 06/04/15.
 */
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;
  }

  @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;
  }
}

SendActivity.java:

// Sends an intent to share the image that was passed to this Activity
private void sendImage() {
    Log.d(LOGTAG, mFilePath);
    Uri theUri = Uri.parse("content://com.mdstudios.diabeticons/" + mFilePath);
    // Tried file path with subfolder and non-subfolder images

    Intent theIntent = new Intent(Intent.ACTION_SEND);
    theIntent.setType("image/*");
    theIntent.putExtra(Intent.EXTRA_STREAM,theUri);
    theIntent.putExtra(android.content.Intent.EXTRA_SUBJECT,"Subject for message");
    theIntent.putExtra(android.content.Intent.EXTRA_TEXT, "Body for message");
    startActivity(theIntent);
}

I'm not sure what I'm doing wrong. The images I'm trying to send are in subfolders (ie, "folder/image1.png"). However, I've tried using an image outside of any subfolders (ie, simply "image1.png" for the file path after copying the image to be outside of any asset subfolders). Furthermore, in the comments in the original SO question, it seemed I had to use a different way to get the file path from the Uri. Neither the original nor the new method (pointed out in the comments in the AssetsProvider class) worked.

Thank you for any and all help!

Edit: After looking around some more, I found a similar posting of the issue here with no replies. I then looked at my logcat more in depth, and found an error:

04-06 14:30:54.773  18883-19532/? E/Babel﹕ java.io.FileNotFoundException: No content provider: content://com.mdstudios.diabeticons/Banana.png
        at android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:1060)
        at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:914)
        at android.content.ContentResolver.openInputStream(ContentResolver.java:639)
        at ajz.a(SourceFile:5280)
        at ajz.doInBackgroundTimed(SourceFile:5066)
        at dsn.doInBackground(SourceFile:65)
        at android.os.AsyncTask$2.call(AsyncTask.java:288)
        at java.util.concurrent.FutureTask.run(FutureTask.java:237)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
        at java.lang.Thread.run(Thread.java:841)

I'm still not sure how to fix this (although I'm still continuing to tinker with it), so any help would still be appreciated! Thanks!

Thanks to CommonsWare, I realized the issue here. The problem is where the provider is supposed to be declared within the manifest- specifically, between the application tags.

So, the manifest should look like this...

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.mdstudios.diabeticons" >

    <application>
        <provider
            android:name="com.mdstudios.diabeticons.Utils.AssetsProvider"
            android:authorities="com.mdstudios.diabeticons"
            android:grantUriPermissions="true"
            android:exported="true" />
    </application>

</manifest>

Notice that in the code I posted within the question, the provider was between the manifest tags yet outside the application tags (similar to where permissions are declared). Instead, the provider declaration must be between the application tags, just like where Activities are declared.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM