2011-05-04 130 views
17

我試圖從我的資產文件夾共享圖像。我的代碼是:Android從資產文件夾共享圖像

Intent share = new Intent(Intent.ACTION_SEND); 
share.setType("image/jpg"); 
share.putExtra(Intent.EXTRA_STREAM, Uri.parse("file:///assets/myImage.jpg")); 
startActivity(Intent.createChooser(share, "Share This Image")); 

但它不起作用。你有什麼想法?

回答

2

AFAIK,無法共享assets文件夾中的圖像。但是可以共享res文件夾中的資源。

+0

你能給我一個例子如何從資源共享可繪製文件夾中的圖像? – 2011-05-04 19:30:46

+3

格式爲:'android.resource:// [package]/[type]/[id]'。所以,一個URI例子是:''android.resource://com.your.app/drawable/「+ Integer.toStrng(R.drawable.some_resource)'。 – Michael 2011-05-04 19:37:16

+0

我試過使用 share.putExtra(Intent.EXTRA_STREAM,Uri.parse(「android.resource://com.packake.myapp/drawable/」+ Integer.toString(R.drawable.myimage)));它可以與gmail共享,但當試圖與yahoo郵件共享時,我會收到消息「讀訪問被拒絕,資源無法讀取」。你有什麼想法爲什麼? – 2011-05-04 19:49:36

14

它可以共享文件(包括圖片)的資產通過定製ContentProvider

您需要延長ContentProvider,在你的清單中註冊並實現openAssetFile方法文件夾。然後,您可以通過Uri小號

@Override 
    public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException { 
     AssetManager am = getContext().getAssets(); 
     String file_name = uri.getLastPathSegment(); 

     if(file_name == null) 
      throw new FileNotFoundException(); 
     AssetFileDescriptor afd = null; 
     try { 
      afd = am.openFd(file_name); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     return afd; 
    } 
+0

你可以添加一些更多的細節,我們如何從另一個應用程序調用這個? – 2012-09-24 17:59:05

8

本博客評估資產可以解釋這一切:
http://nowherenearithaca.blogspot.co.uk/2012/03/too-easy-using-contentprovider-to-send.html

基本上,這正好在清單:

<provider android:name="yourclass.that.extendsContentProvider"    android:authorities="com.yourdomain.whatever"/> 

內容提供商類有這:

@Override 
public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException { 
    AssetManager am = getContext().getAssets(); 
    String file_name = uri.getLastPathSegment(); 
    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); 
} 

並調用代碼做到這一點:

Uri theUri = Uri.parse("content://com.yourdomain.whatever/someFileInAssetsFolder"); 
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); 
+0

我無法使用您的解決方案,請檢查此:http://stackoverflow.com/questions/21929721/contentprovider-dont-working-for-sharing-images-from-assets-folder – NullPointerException 2014-02-21 09:04:23

+0

確保URI始於「內容://」 – 2014-02-22 08:43:57

+0

我得到「java.io.FileNotFoundException:此文件不能打開的文件描述符;它可能是壓縮」關於am.openFd(FILE_NAME) – GozzoMan 2017-12-01 16:43:38

9

補充什麼@Cris Nash回答:

你需要覆蓋的方法,如上面的例子類:

package com.android.example; 

import android.content.ContentProvider; 
import android.net.Uri; 
import android.content.res.AssetFileDescriptor; 
import android.content.res.AssetManager; 
import java.io.FileNotFoundException; 
import android.content.ContentValues; 
import android.database.Cursor; 
import java.io.IOException; 
import android.os.CancellationSignal; 

public class AssetsProvider extends ContentProvider 
{ 

     @Override 
     public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException 
     { 
       Log.v(TAG, "AssetsGetter: Open asset file"); 
       AssetManager am = getContext().getAssets(); 
       String file_name = uri.getLastPathSegment(); 
       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; 
     } 
} 

我需要重寫兩次查詢方法。 而在你的AndroidManifest.xml中添加上述代碼中添加以下行:

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

而與此,有魅力的所有工作:d

+0

能有人幫我,我從資產---->文件夾----> image1.png獲取圖像,我沒能得到資產的子文件夾請圖像建議我此行的代碼編輯字符串FILE_NAME = uri.getLastPathSegment (); – user3233280 2014-06-06 18:10:40

+0

http://pastie.org/9265206 – user3233280 2014-06-06 18:12:55

+1

對不起,我遲到了。你如何將文件發送到意圖?我認爲代碼是可以的。您需要通過這樣的ADDRES來電圖片:文件:///android_asset/folder/image1.png 如果你需要分享這一點,你需要使用這個代碼: 字符串文件=「文件夾/ image1.png」; Uri theUri = Uri.parse(「content://com.example.yourproject/」+ file); Intent theIntent = new Intent(Intent.ACTION_SEND); theIntent.setType(「image/*」); theIntent.putExtra(Intent.EXTRA_STREAM,theUri); (Intent.createChooser(theIntent,「Send to:」); – Kikuto 2014-08-04 16:23:24

3

許多應用程序要求您提供姓名和圖像的大小。因此,這裏是一種改進的代碼(使用谷歌的FileProvider代碼爲例):

public class AssetsProvider extends ContentProvider { 

    private final static String LOG_TAG = AssetsProvider.class.getName(); 

    private static final String[] COLUMNS = { 
      OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE }; 

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

    @Override 
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { 
     /** 
     * Source: {@link FileProvider#query(Uri, String[], String, String[], String)} . 
     */ 
     if (projection == null) { 
      projection = COLUMNS; 
     } 

     final AssetManager am = getContext().getAssets(); 
     final String path = getRelativePath(uri); 
     long fileSize = 0; 
     try { 
      final AssetFileDescriptor afd = am.openFd(path); 
      fileSize = afd.getLength(); 
      afd.close(); 
     } catch(IOException e) { 
      Log.e(LOG_TAG, "Can't open asset file", e); 
     } 

     final String[] cols = new String[projection.length]; 
     final Object[] values = new Object[projection.length]; 
     int i = 0; 
     for (String col : projection) { 
      if (OpenableColumns.DISPLAY_NAME.equals(col)) { 
       cols[i] = OpenableColumns.DISPLAY_NAME; 
       values[i++] = uri.getLastPathSegment(); 
      } else if (OpenableColumns.SIZE.equals(col)) { 
       cols[i] = OpenableColumns.SIZE; 
       values[i++] = fileSize; 
      } 
     } 

     final MatrixCursor cursor = new MatrixCursor(cols, 1); 
     cursor.addRow(values); 
     return cursor; 
    } 

    @Override 
    public String getType(Uri uri) { 
     /** 
     * Source: {@link FileProvider#getType(Uri)} . 
     */ 
     final String file_name = uri.getLastPathSegment(); 
     final int lastDot = file_name.lastIndexOf('.'); 
     if (lastDot >= 0) { 
      final String extension = file_name.substring(lastDot + 1); 
      final String mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension); 
      if (mime != null) { 
       return mime; 
      } 
     } 

     return "application/octet-stream"; 
    } 

    @Override 
    public Uri insert(Uri uri, ContentValues values) { 
     return null; 
    } 

    @Override 
    public int delete(Uri uri, String selection, String[] selectionArgs) { 
     return 0; 
    } 

    @Override 
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 
     return 0; 
    } 

    @Override 
    public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException { 
     final AssetManager am = getContext().getAssets(); 
     final String path = getRelativePath(uri); 
     if(path == null) { 
      throw new FileNotFoundException(); 
     } 
     AssetFileDescriptor afd = null; 
     try { 
      afd = am.openFd(path); 
     } catch(IOException e) { 
      Log.e(LOG_TAG, "Can't open asset file", e); 
     } 
     return afd; 
    } 

    private String getRelativePath(Uri uri) { 
     String path = uri.getPath(); 
     if (path.charAt(0) == '/') { 
      path = path.substring(1); 
     } 
     return path; 
    } 
} 
2

從資產文件夾共享,我只能建議cwac-provider庫(StreamProvider)。

在避免開發自己的內容提供商時,它爲反覆無常的傳統應用程序增加了一些支持(請查詢USE_LEGACY_CURSOR_WRAPPER)。