2011-10-11 5 views
18

이전에이 코드 스 니펫을 사용했지만 파일이 SD 카드의 어떤 곳을 가리키고 있습니다.카메라 의도가 사진을 저장하지 않습니다.

final File temp = new File(getCacheDir(), "temp.jpg"); 
temp.delete(); 
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); 
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(temp)); 
startActivityForResult(intent, CONFIG.Intents.Actions.SELECT_CAMERA_PHOTO); 

그러나 SD 카드의 loc 대신 getCacheDir을 사용하면 사진이 저장되지 않는 것 같습니다. 이것은 캐시 디렉토리와 이미지 캡처의 한계입니까?

답변

41

기술적으로 이것은 카메라 응용 프로그램을 사용하여 이미지를 캡처 할 때 내부 저장소에 쓰기가 지원되지 않기 때문입니다. 실제로 logcat에 Writing to internal storage is not supported이라는 예외가 인쇄되어 있습니다. 그러나 이것이 작동하지 않는 진정한 이유는 기본적으로 응용 프로그램 패키지에 대한 비공개 파일을 만들고 다른 응용 프로그램 (예 : 카메라 응용 프로그램)은 해당 파일 위치에 액세스 할 수 없기 때문입니다. 그렇게해라. 외부 저장소는 파일 시스템에서 유일하게 접근 가능한 부분입니다.

해결 방법은 전역 (WORLD_WRITEABLE) 권한을 가진 파일을 만드는 것입니다. 일반적으로 카메라 앱이 전달 된 Uri를 통해 파일에 액세스 할 수 있습니다. 이 직접 File에이 작업을 수행하는 정말 방법이 있습니다, 그래서 당신은 Context에서 사용할 수있는 방법을 사용하여 파일을 만든 다음 나중에이 핸들을 잡아가 ​​: 어디 당신이 할 수있는이 또한 일종의 한계를

//Remove if exists, the file MUST be created using the lines below 
File f = new File(getFilesDir(), "Captured.jpg"); 
f.delete(); 
//Create new file 
FileOutputStream fos = openFileOutput("Captured.jpg", Context.MODE_WORLD_WRITEABLE); 
fos.close(); 
//Get reference to the file 
File f = new File(getFilesDir(), "Captured.jpg"); 

Context 메서드는 기본적으로 루트 "files"디렉토리에 파일을 생성하므로 파일을 배치해야하며 캐시 디렉토리로 리디렉션 할 수 없습니다.

HTH

+0

좋아, 내가 문제였다 직감했다 . SD 카드에 일시적으로 사진을 저장하는 방법을 다시 옮겨야 겠지만, 내 툴킷에 이것을 추가 할 것입니다 :) – sgarman

+1

Context.MODE_WORLD_WRITEABLE을 해결하는 방법에 대한 아이디어가 있으십니까? – superbre

+6

[here] (http://developer.android.com/reference/android/content/Context.html) : ** MODE_WORLD_WRITEABLE이 상수는 API 레벨 17에서 사용되지 않습니다. 세계에서 쓰기가 가능한 파일을 만드는 것은 매우 위험하며 응용 프로그램에 보안 허점이 생길 수 있습니다.강력히 낙담하게됩니다 ** – Atul

25
내가 찾은

최선의 해결책은 다음과 같습니다 FileProvider 그것은 내부 저장소를 사용 (지원 라이브러리-V4 필요)! https://developer.android.com/reference/android/support/v4/content/FileProvider.html

  1. 이 응용 프로그램 요소에 매니페스트에 FileProvider을 정의

    <provider 
         android:name="android.support.v4.content.FileProvider" 
         android:authorities="your.package.name.fileprovider" 
         android:exported="false" 
         android:grantUriPermissions="true" > 
         <meta-data 
           android:name="android.support.FILE_PROVIDER_PATHS" 
           android:resource="@xml/image_path" /> 
    </provider> 
    
  2. 추가 권한을 매니페스트 루트 요소 :

    <uses-permission android:name="android.permission.CAMERA" /> 
    <uses-feature android:name="android.hardware.camera" android:required="false" /> 
    
  3. 예를 입술에 대한 귀하의 이미지 경로를 정의/xml/image_path.xml :

    (210)
    <paths xmlns:android="http://schemas.android.com/apk/res/android"> 
    <files-path name="captured_image" path="your/path/"/> 
    </paths> 
    
  4. 자바 :

    private static final int IMAGE_REQUEST_CODE = 1; 
    // your authority, must be the same as in your manifest file 
    private static final String CAPTURE_IMAGE_FILE_PROVIDER = "your.package.name.fileprovider"; 
    

4.1 캡처 의도 :

File path = new File(activity.getFilesDir(), "your/path"); 
    if (!path.exists()) path.mkdirs(); 
    File image = new File(path, "image.jpg"); 
    Uri imageUri = FileProvider.getUriForFile(activity, CAPTURE_IMAGE_FILE_PROVIDER, image); 
    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); 
    intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); 
    startActivityForResult(intent, IMAGE_REQUEST_CODE); 

4.2 onActivityResult를() :

@Override 
    public void onActivityResult(int requestCode, int resultCode, Intent intent) { 
     if (requestCode == IMAGE_REQUEST_CODE) { 
      if (resultCode == Activity.RESULT_OK) { 
       File path = new File(getFilesDir(), "your/path"); 
       if (!path.exists()) path.mkdirs(); 
       File imageFile = new File(path, "image.jpg"); 
       // use imageFile to open your image 
      } 
     } 
     super.onActivityResult(requestCode, resultCode, intent); 
    } 
+0

FileProvide는 Camera Intent를 사용하여 이미지를 내부적으로 저장하는 최상의 솔루션입니다. – tagy22

+0

FileProvide에'READ_EXTERNAL_STORAGE' 권한이 필요합니까? 나는 그것이 옳다고 믿지 않는다. –

+0

마틴, 나는 네가 옳다고 생각한다. 나는 내 대답을 바꿀 것이다. – Harry

관련 문제