安卓使用内容提供商从资产文件夹发送图像



你好~我正试图通过通用意向从应用程序中的assets文件夹发送图像(这样用户就可以将图像发送到接受此类意向的任何其他应用程序,包括SMS、Facebook和Twitter)。

环顾四周,我发现了这个StackOverflow问题。它似乎运行得很好,在遵循了评论一段时间后,该方法似乎没有被否决。然而,我的问题是,我无法让它发挥作用。发生的情况是,我成功地从意向选择器对话框中选择了一个应用程序,但一旦应用程序,我就会收到一个祝酒词,上面写着"找不到照片"

这是我当前的代码。。。

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

我不确定我做错了什么。我尝试发送的图像在子文件夹中(即"folder/image1.png")。但是,我尝试在任何子文件夹之外使用图像(即,在将图像复制到任何资产子文件夹之外后,文件路径仅为"image1.pnng")。此外,在最初SO问题的注释中,我似乎不得不使用不同的方法从Uri获取文件路径。原始方法和新方法(在AssetsProvider类的注释中指出)都不起作用。

感谢您的帮助!

编辑:在看了更多之后,我在这里发现了一个类似的问题帖子,但没有回复。然后我更深入地查看了我的logcat,发现了一个错误:

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)

我仍然不确定如何解决这个问题(尽管我仍在继续修补它),所以任何帮助都将不胜感激!谢谢

多亏了CommonsWare,我在这里意识到了这个问题。问题是提供者应该在清单中声明的位置,特别是在应用程序标记之间。

所以,清单应该是这样的。。。

<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>

请注意,在我在问题中发布的代码中,提供者位于清单标记之间,但在应用程序标记之外(类似于声明权限的地方)。相反,提供者声明必须在应用程序标记之间,就像声明Activities一样。

最新更新