2012-12-13 14 views
7

ImageViewが設定されているアプリケーションがあり、これをクリックしてギャラリーで開くことができます。デフォルトでは内部メモリに保存されている画像を共有する

、私は私のJPEGファイルを保存するために、外部ストレージからファイルディレクトリを取得するには、次のコードを使用します。

File picsDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),"MyCameraApp"); 

しかし!外部ストレージがマウントされていないか、単に存在しないと仮定した場合(Galaxy Nexus)、これは機能しません。だから、私はそれのまわりにif文を書いて、内部のキャッシュディレクトリをフォールバックとして得る。

String state = Environment.getExternalStorageState() 
if(Environment.MEDIA_MOUNTED.equals(state)){ 
    File picsDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),"MyCameraApp");  
}else{ 
    context.getCacheDir(); 
} 

イメージはImageViewで正常に表示されますが、インテントが起動しても表示されません。

Intent intent = new Intent();    
intent.setAction(android.content.Intent.ACTION_VIEW); 
intent.setDataAndType(Uri.fromFile(imgFile), "image/jpeg"); 
startActivity(intent); 

ギャラリーが読み込まれますが、黒い画面が表示されます。おそらくギャラリーは私のアプリケーションのキャッシュディレクトリにファイルへのアクセス権がないためです。代替案として

、私はMediaStore.Images.Media.INTERNAL_CONTENT_URIを使用してメディアコンテンツプロバイダを使用してみましたが、inserにイメージをしようとしたとき、これはエラーにつながる:

java.lang.UnsupportedOperationException: Writing to internal storage is not supported. 

私は何をすべき?

+0

私は意思と一緒にビットマップをパッケージ化しようとすることができ、正確にあなたの問題を解決し、このようにコードを変更することができますか? 'intent.putExtra(" BitmapImage "、ビットマップ);のように。私の画像は通常約5MBです。 – Maarten

+0

イメージをアプリケーションのプライベートストレージに保存して一般的な読み取り専用アクセスを許可することができますが、Googleの組み込み関数を含む多くのアプリケーションでは、パスを渡したときにアクセスできるかどうかを確認する必要はありませんが、所有しているアプリケーションが実際にグローバル・リード・アクセスを許可している場合でも、それらが失敗したり失敗したりすると仮定します。 –

答えて

3

私はここでの問題は、あなたがギャラリーメモリーのプライベートな空間で保存したファイルを持つオープンしようとしているということであると仮定

(getCacheDirは、そのメモリのパスにアクセスすることができ、アプリケーションとのみ、アプリケーションに相対パスを返します)外部メモリに保存できない場合は、パブリックパスで保存しようとすることができます(ただし、すべてのアプリケーションでメディアファイルを操作できます。アプリケーションをアンインストールすると、そこに保存された生成メディアは消去されません)

プライベートな内部メモリを使用する場合は、ContentProviderを書くことができます

私はコンテンツプロバイダを投稿するために編集します。私は何を言ったかを解明するために使用します。それは

<provider 
     android:name=".contentproviders.MediaContentProvider" 
     android:authorities="com.way.srl.HandyWay.contentproviders.media" > 
    </provider> 

してからだった私の場合には、あなたがマニフェストにあなたのContentProviderへの参照を必要とし、その後

public class MediaContentProvider extends ContentProvider { 
private static final String TAG = "MediaContentProvider"; 

// name for the provider class 
public static final String AUTHORITY = "com.way.srl.HandyWay.contentproviders.media"; 

private MediaData _mediaData; 

// UriMatcher used to match against incoming requests 
private UriMatcher _uriMatcher; 

@Override 
public int delete(Uri uri, String selection, String[] selectionArgs) { 
    // TODO Auto-generated method stub 
    return 0; 
} 

@Override 
public String getType(Uri uri) { 
    // TODO Auto-generated method stub 
    return null; 
} 

@Override 
public Uri insert(Uri uri, ContentValues values) { 
    // TODO Auto-generated method stub 
    return null; 
} 

@Override 
public boolean onCreate() { 
    uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); 

    // Add a URI to the matcher which will match against the form 
    // 'content://com.stephendnicholas.gmailattach.provider/*' 
    // and return 1 in the case that the incoming Uri matches this pattern 
    _uriMatcher.addURI(AUTHORITY, "*", 1); 

    return true; 
} 

@Override 
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { 
    // TODO Auto-generated method stub 
    return null; 
} 

@Override 
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 
    // TODO Auto-generated method stub 
    return 0; 
} 

@Override 
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { 

    Log.v(TAG, "Called with uri: '" + uri + "'." + uri.getLastPathSegment()); 

    // Check incoming Uri against the matcher 
    switch (_uriMatcher.match(uri)) { 

    // If it returns 1 - then it matches the Uri defined in onCreate 
     case 1: 

      // The desired file name is specified by the last segment of the 
      // path 
      // E.g. 
      // 'content://com.stephendnicholas.gmailattach.provider/Test.txt' 
      // Take this and build the path to the file 
      // String fileLocation = getContext().getCacheDir() + File.separator + uri.getLastPathSegment(); 
      Integer mediaID = Integer.valueOf(uri.getLastPathSegment()); 

      if (_mediaData == null) { 
       _mediaData = new MediaData(); 
      } 
      Media m = _mediaData.get(mediaID); 

      // Create & return a ParcelFileDescriptor pointing to the file 
      // Note: I don't care what mode they ask for - they're only getting 
      // read only 
      ParcelFileDescriptor pfd = ParcelFileDescriptor.open(new File(m.filePath), ParcelFileDescriptor.MODE_READ_ONLY); 
      return pfd; 

      // Otherwise unrecognised Uri 
     default: 
      Log.v(TAG, "Unsupported uri: '" + uri + "'."); 
      throw new FileNotFoundException("Unsupported uri: " + uri.toString()); 
    } 
} 

: これは私のコンテンツプロバイダである(私はちょうどあなたが必要とする関連部分を掲載しました) mは、SQLiteのDBに指し、_で私は(再びオブジェクトに移入するデータをフェッチクラスを使用するIDを格納するエンティティである私の場合、この

Intent intent = new Intent(); 
intent.setAction(Intent.ACTION_VIEW); 
intent.setDataAndType(Uri.parse("content://" + MediaContentProvider.AUTHORITY + "/" + m.id), "image/jpg"); 

ようにそれを使用mediaData)、あなたは自分のニーズ

にフィットするように私は自分のアプリケーションたぶん

+0

これは良い答えですが、Googleはこの投稿以来 'ファイルプロバイダ'を提供しています。チュートリアルです:http://developer.android.com/reference/android/support/v4/content/FileProvider.html – DaMachk

0

このフォールバックは必要ないと私は理解しています。 Google Playを搭載している端末では、Environment.getExternalStorageDirectory()で2 GB以上の使用が保証されています。

ギャラクシーネクサスでは、これは外部としてマークされた内部メモリ上のパーティションです。利用できない場合は警告を表示します。

+2

並べ替えGalaxy Nexusは、内蔵型で取り外し不可能であっても、確実に「外部ストレージ」を備えています。ただし、ストレージが削除されたデバイスでは、存在しない可能性があります。 USBマスストレージを行うデバイスでは、外部コンピュータにマウントしている間は使用できなくなります。 –

関連する問題