티스토리 뷰

반응형

Stack Overflow에 자주 검색, 등록되는 문제들과 제가 개발 중 찾아 본 문제들 중에서 나중에도 찾아 볼 것 같은 문제들을 정리하고 있습니다.

Stack Overflow에서 가장 먼저 확인하게 되는 가장 높은 점수를 받은 Solution과 현 시점에 도움이 될 수 있는 가장 최근에 업데이트(최소 점수 확보)된 Solution을 각각 정리하였습니다.

 

아래 word cloud를 통해 이번 포스팅의 주요 키워드를 미리 확인하세요.

Environment.getExternalStorageDirectory() deprecated in API level 29 java

Environment.getExternalStorageDirectory()는 API 레벨 29에서 사용이 중단된 메서드입니다.

 문제 내용 

Working on android Java, recently updated SDK to API level 29 now there is a warning shown which states that

안드로이드 자바 작업 중에, 최근에 SDK를 API 레벨 29로 업데이트하였고 이제 경고가 표시되며 다음과 같이 나타납니다.

 

Environment.getExternalStorageDirectory() is deprecated in API level 29

API 레벨 29에서 Environment.getExternalStorageDirectory()는 사용이 중단되었습니다.

 

My code is

제 코드 :
private void saveImage() {

if (requestPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {

    final String folderPath = Environment.getExternalStorageDirectory() + "/PhotoEditors";
    File folder = new File(folderPath);
    if (!folder.exists()) {
        File wallpaperDirectory = new File(folderPath);
        wallpaperDirectory.mkdirs();
    }


    showLoading("Saving...");
    final String filepath=folderPath
                + File.separator + ""
                + System.currentTimeMillis() + ".png";
    File file = new File(filepath);

    try {
        file.createNewFile();
        SaveSettings saveSettings = new SaveSettings.Builder()
                .setClearViewsEnabled(true)
                .setTransparencyEnabled(true)
                .build();
        if(isStoragePermissionGranted() ) {
            mPhotoEditor.saveAsFile(file.getAbsolutePath(), saveSettings, new PhotoEditor.OnSaveListener() {
            @Override
            public void onSuccess(@NonNull String imagePath) {
                hideLoading();
                showSnackbar("Image Saved Successfully");
                mPhotoEditorView.getSource().setImageURI(Uri.fromFile(new File(imagePath)));
                sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,Uri.fromFile(new File(filepath))));
                Intent intent = new Intent(EditImageActivity.this, StartActivity.class);
                startActivity(intent);
                finish();

            } 

            @Override
            public void onFailure(@NonNull Exception exception) {
                hideLoading();
                showSnackbar("Failed to save Image");
            }
       });
   }

 

What will be the alternative for this?

이 것의 대체 방안은 무엇인가요?

 

 

 

 높은 점수를 받은 Solution 

Use getExternalFilesDir(), getExternalCacheDir(), or getExternalMediaDirs() (methods on Context) instead of Environment.getExternalStorageDirectory().

Environment.getExternalStorageDirectory() 대신 Context의 getExternalFilesDir(), getExternalCacheDir(), 또는 getExternalMediaDirs() 메소드를 사용하세요.

 

Or, modify mPhotoEditor to be able to work with a Uri, then:

또는 mPhotoEditor를 Uri로 작업할 수 있도록 수정한 다음, 다음과 같이 작업합니다:

 

  • Use ACTION_CREATE_DOCUMENT to get a Uri to a location of the user's choosing, or
  • Use MediaStore, ContentResolver, and insert() to get a Uri for a particular type of media (e.g., an image) — see this sample app that demonstrates doing this for downloading MP4 videos from a Web site
사용자가 선택한 위치에 대한 Uri를 가져 오기 위해 ACTION_CREATE_DOCUMENT를 사용하거나,
미디어 유형(예 : 이미지)에 대한 Uri를 가져 오기 위해 MediaStore, ContentResolver 및 insert()를 사용합니다. 이 예제 앱에서는 웹 사이트에서 MP4 비디오를 다운로드하는 방법을 보여줍니다.

 

Also, note that your Uri.fromFile with ACTION_MEDIA_SCANNER_SCAN_FILE should be crashing on Android 7.0+ with a FileUriExposedException. On Android Q, only the MediaStore/insert() option will get your content indexed by the MediaStore quickly.

또한, ACTION_MEDIA_SCANNER_SCAN_FILE과 함께 사용되는 Uri.fromFile은 Android 7.0 이상에서 FileUriExposedException으로 충돌할 수 있음을 유의하십시오. Android Q에서는 미디어 스토어 insert() 옵션만 빠르게 미디어 스토어에 색인화됩니다.

 

Note that you can opt out of these "scoped storage" changes on Android 10 and 11, if your targetSdkVersion is below 30, using android:requestLegacyExternalStorage="true" in the <application> element of the manifest. This is not a long-term solution, as your targetSdkVersion will need to be 30 or higher sometime in 2021 if you are distributing your app through the Play Store (and perhaps elsewhere).

참고로, targetSdkVersion이 30보다 낮은 경우 Android 10과 11에서 이러한 "scoped storage" 변경 사항에서 벗어날 수 있습니다. 이를 위해서는 매니페스트 파일의 요소에 android:requestLegacyExternalStorage="true"을 사용하면 됩니다. 그러나 이는 장기적인 해결책이 아닙니다. 앱을 Play 스토어를 통해 배포하는 경우 (아마도 다른 곳에서도) 2021년 언저리에 targetSdkVersion을 30 이상으로 설정해야 할 것입니다.

 

 

 

 가장 최근 달린 Solution 

To get internal storage directory without hard coding,

하드 코딩 없이 내부 저장소 디렉토리를 가져오려면,

 

Permissions (For all Android versions). Don't forget to get permissions from the user.

모든 안드로이드 버전에서 권한 (Permissions)을 받는 것을 잊지 마세요. 사용자로부터 권한을 받는 것이 필요합니다.

 

Request all files access

모든 파일 접근 권한 요청
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="29" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage" />

 

Legacy permission for Android 10 (add this to AndroidManifest.xml > application tag).

안드로이드 10을 위한 레거시 권한 (AndroidManifest.xml의 태그에 추가)
android:requestLegacyExternalStorage="true"

 

Get internal storage directory path:

내부 저장소 디렉토리 경로 가져오기:
public static String getInternalStorageDirectoryPath(Context context) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
        StorageManager storageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
        return storageManager.getPrimaryStorageVolume().getDirectory().getAbsolutePath();
    } else {
        return Environment.getExternalStorageDirectory().getAbsolutePath();
    }
}

 

 

출처 : https://stackoverflow.com/questions/57116335/environment-getexternalstoragedirectory-deprecated-in-api-level-29-java

반응형
댓글
공지사항
최근에 올라온 글