2014-08-27 82 views
0

我有以下代碼的圖像正確地附着到電子郵件和發送:開放共享圖像意圖

Intent sharingIntent = new Intent(Intent.ACTION_SEND); 

sharingIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
// Set tht type to image/* and add the extra text field for the message to send 
sharingIntent.setType(Application2.instance().getResString(R.string.share_intent_type_text_image)); 
sharingIntent.putExtra(Intent.EXTRA_TEXT, String.format(Application2.instance().getResString(R.string.share_intent_body_question), question.question)); 

if (destFile != null) 
{ 
    Uri uri = Uri.fromFile(destFile); 
    sharingIntent.putExtra(Intent.EXTRA_STREAM, uri); 

    ((ActivityMain) getActivity()).startActivity(Intent.createChooser(sharingIntent, "Share via")); 
} 

R.string.share_intent_type_text_image被定義爲「圖像/ PNG」

destFile是圖像抓起從應用程序的外部緩存目錄中刪除,(((ActivityMain) getActivity()).getExternalCacheDir()

但是,當我嘗試在Gmail中打開該文件時,出現一個對話框,其中顯示:Info - 沒有應用程序可以打開此附件進行查看。我已經通過我的電腦下載了該文件,擴展名爲.File。我可以用油漆和其他圖像查看器打開它。

以前有人遇到過這個嗎?

+0

什麼是'destFile'的價值? – CommonsWare 2014-08-27 19:39:43

+0

我建議你看看https://developer.android.com/reference/android/support/v4/content/FileProvider.html – Simon 2014-08-27 19:47:16

+0

@Simon我會測試它併發布結果。看起來這正是我需要的!請注意,這些圖像適用於許多其他應用程序。另外,添加了「destFile」的描述。 – 2014-08-28 20:38:00

回答

1

考慮FileProvider問題,也因爲我想實現對採集的臨時文件最大緩存大小,我去了ContentProvider解決方案,它的工作原理治療。基本上,您可以毫無問題地使用內部緩存,但仍可向第三方應用程序提供一個可用於引用要與之共享的臨時文件的URI。因爲你使用你的內部緩存,所以不會有不必要的WRITE_EXTERNAL_STORAGE許可請求。

增加的最大緩存大小限制(您可以通過簡單地刪除從checkSize()到課程末尾的所有內容(例如,如果您可以確保在共享之後直接刪除所有文件,則可以從課程中刪除)保留在設備上)通過檢查每次調用時的累積最大大小並在必要時清除一半高速緩存(刪除最早的文件)來工作。

public class TemporaryFile extends ContentProvider { 
    private static final long MAX_SIZE = 512 * 1024; 
    // commented out on purpose so that you don't forget to rewrite it... 
    // public static final String AUTHORITY = "com.example.tempfile"; 

    private UriMatcher uriMatcher; 

    @Override 
    public boolean onCreate() { 
    uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); 
    uriMatcher.addURI(AUTHORITY, "*", 1); 
    return true; 
    } 

    @Override 
    public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { 
    if (uriMatcher.match(uri) == 1) { 
     final String file = getContext().getCacheDir() + File.separator + uri.getLastPathSegment(); 
     return ParcelFileDescriptor.open(new File(file), ParcelFileDescriptor.MODE_READ_ONLY); 
    } 
    else 
     throw new FileNotFoundException(uri.toString()); 
    } 

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

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

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

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

    @Override 
    public Cursor query (Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { 
    return null; 
    } 

    public static File getFile(Context context, String prefix, String extension) throws IOException { 
    checkSize(context); 
    File file = File.createTempFile(prefix, extension, context.getCacheDir()); 
    file.setReadable(true); 
    file.deleteOnExit(); 
    return file; 
    } 

    public static Uri getPublicUri(File file) { 
    return Uri.withAppendedPath(Uri.parse("content://" + AUTHORITY), file.getName()); 
    } 

    public static void checkSize(Context context) throws IOException { 
    File dir = context.getCacheDir(); 
    if (getDirSize(dir) > MAX_SIZE) 
     cleanDir(dir, MAX_SIZE/2); 
    } 

    private static long getDirSize(File dir) { 
    long size = 0; 
    for (File file : dir.listFiles()) 
     if (file.isFile()) 
     size += file.length(); 
    return size; 
    } 

    private static void cleanDir(File dir, long atLeast) { 
    long deleted = 0; 

    File[] files = dir.listFiles(); 
    Arrays.sort(files, new Comparator<File>() { 
     public int compare(File f1, File f2) { 
     return Long.valueOf(f1.lastModified()).compareTo(f2.lastModified()); 
     } 
    }); 

    for (File file : files) { 
     deleted += file.length(); 
     file.delete(); 
     if (deleted >= atLeast) 
     break; 
    } 
    } 
} 

使用它,不能再簡單,只需撥打

File file = TemporaryFile.getFile(this, "prefix", ".extension"); 

,每當你想創建一個新的文件,並

TemporaryFile.getPublicUri(file) 

,只要你想獲得公衆開放的到文件,例如。將其傳遞給數據或Intent.EXTRA_STREAM

作爲一個供應商,不要忘了添加必要的清單條目,或者:

<provider 
    android:name=".TemporaryFile" 
    android:authorities="com.example.tempfile" 
    android:exported="true" 
    tools:ignore="ExportedContentProvider" > 
</provider> 
0

這項工作,但需要外部存儲和相關權限。當下載應用程序時,對話框將顯示應用程序正在請求讀/寫數據,這可能會使用戶離開。如果這是一個問題,請按照Simon在我的初始文章中所建議的那樣使用FileProvider。

相關鏈接:
https://developer.android.com/reference/android/support/v4/content/FileProvider.html

我試圖使用文件提供西蒙在我最初的職位無濟於事建議。我收到一個NullPointerException以下行:

final ProviderInfo info = context.getPackageManager() 
      .resolveContentProvider(authority, PackageManager.GET_META_DATA); 

我無法跟隨在指南後跟蹤問題: https://developer.android.com/reference/android/support/v4/content/FileProvider.html
以及其他線程:
How to use support FileProvider for sharing content to other apps?

在這點我意識到沒有爲正在使用的圖像設置文件類型。我只是簡單地將.png添加到文件中,並且附件在Gmail中正常工作,以及之前已運行的應用程序。

如果有人很好奇我如何共享內部文件,我提供了下面的代碼。這不完整,並不完全處理錯誤,但它可能對某人有用作爲開始。

// Copy image file to external memory and send with the intent 
File srcFile = getImage(); 
File destDir = new File(((ActivityMain) getActivity()).getExternalCacheDir(), 
     Application2.instance().getResString(R.string.temporary_external_image_path)); 
if(!destDir.exists()) 
{ 
    destDir.mkdirs(); 
} 

if(destDir != null && srcFile != null) 
{ 
    File destFile = new File(destDir, srcFile.getName()); 

    if (!destFile.exists()) 
    { 
     try 
     { 
      Application2.instance().copy(srcFile, destFile); 
     } 
     catch (IOException e) 
     { 
      if (BuildConfig.DEBUG) Log.e("Failed to copy file '" + srcFile.getName() + "'"); 
     } 
    } 

    if (destFile != null) 
    { 
     Uri uri = Uri.fromFile(destFile); 
     sharingIntent.putExtra(Intent.EXTRA_STREAM, uri); 

     ((ActivityMain) getActivity()).startActivity(Intent.createChooser(sharingIntent, "Share via")); 
    } 
}