2012-12-13 3 views
7

ImageView가 설정되어 있고 갤러리에서 클릭하여 열 수있는 응용 프로그램이 있습니다. 기본적으로내부 메모리에 저장된 이미지 공유

, 내 사진과를 저장하는 외부 저장 장치에서 파일 디렉토리를 얻기 위해 다음 코드를 사용

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

그러나! 외부 저장소가 마운트되지 않았거나 단순히 존재하지 않는다고 가정하면 (Galaxy Nexus) 작동하지 않습니다. 그래서 if-statement를 써서 내부 캐시 디렉토리를 fallback으로 가져옵니다.

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> 

다음이었다 내 경우에는, 당신은 매니페스트에 컨텐트 프로에 대한 참조가 필요합니다 다음

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이

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

처럼 사용하는 _ SQLite는 DB를 가리 아이디 저장 엔티티 내가로 (객체를 다시 채울 데이터를 페치하는 클래스를 사용 mediaData), 당신은 당신의 요구에

에 맞게 난 내 응용 프로그램 아마

+0

좋은 답변이지만 Google은이 게시물 이후 '파일 제공자'를 제공했습니다. 다음은 자습서입니다. http://developer.android.com/reference/android/support/v4/content/FileProvider.html – DaMachk

0

이 대체가 필요하지 않다는 것을 알고 있습니다. Google Play가있는 기기는 Environment.getExternalStorageDirectory()에서 2GB 이상 사용할 수 있습니다.

나는 Galaxy Nexus에서 외부 메모리로 표시된 내부 메모리의 파티션이라고 가정합니다. 사용할 수없는 경우 경고 만 표시합니다.

+2

일종. Galaxy Nexus는 내부 및 비 분리형이지만 가장 확실하게 "외부 저장 장치"를 갖추고 있습니다. 그러나 저장소가 제거 된 장치에서는 존재하지 않을 수 있습니다. USB 대용량 저장 장치를 사용하는 장치에서는 외부 컴퓨터에 장착하는 동안에는 사용할 수 없습니다. –

관련 문제