web-dev-qa-db-ja.com

Environment.getExternalStorageDirectory()はAPIレベル29で廃止予定java

Android Java、最近更新されたSDK、APIレベル29に更新中です。

Environment.getExternalStorageDirectory()はAPIレベル29で廃止されました

私のコードは

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");
            }
       });
   }

これの代わりは何でしょうか?

42
Noaman Akram

getExternalFilesDir()の代わりにgetExternalCacheDir()getExternalMediaDir()、またはEnvironment.getExternalStorageDirectory()Contextのメソッド)を使用します。

または、mPhotoEditorを変更してUriを操作できるようにし、次のようにします。

  • _ACTION_CREATE_DOCUMENT_を使用してUriをユーザーが選択した場所に取得する、または

  • MediaStoreContentResolver、およびinsert()を使用して、特定の種類のメディア(たとえば、画像)のUriを取得します— このサンプルアプリ を参照してください。ウェブサイト

また、_Uri.fromFile_付きの_ACTION_MEDIA_SCANNER_SCAN_FILE_は、Android 7.0以降でFileUriExposedException付きでクラッシュするはずです。 Android Qでは、MediaStore/insert()オプションのみがMediaStoreによってコンテンツのインデックスをすばやく取得します。

Android Qが外部ストレージにどのように影響したかについての詳細は このブログ投稿 を参照してください。

40
CommonsWare

新しいAPI呼び出しでdestPathを取得します。

String destPath = mContext.getExternalFilesDir(null).getAbsolutePath();
14
Russell A

これは、デフォルトのカメラを使用して写真を撮り、それをDCIMフォルダー(DCIM/app_name/filename.jpg)に保存する場合に、ファイルのURIを取得する小さな例です。

カメラを開く(カメラの権限について覚えておいてください):

private var photoURI: Uri? = null

private fun openCamera() {
    Intent(MediaStore.ACTION_IMAGE_CAPTURE).also { takePictureIntent ->
        photoURI = getPhotoFileUri()
        takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI)
        takePictureIntent.resolveActivity(requireActivity().packageManager)?.also {
            startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE)
        }
    }
}

そしてURIを取得します:

private fun getPhotoFileUri(): Uri {
    val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(Date())
    val fileName = "IMG_${timeStamp}.jpg"

    var uri: Uri? = null
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
        val resolver = requireContext().contentResolver
        val contentValues = ContentValues().apply {
            put(MediaStore.MediaColumns.DISPLAY_NAME, fileName)
            put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
            put(MediaStore.MediaColumns.RELATIVE_PATH, "DCIM/app_name/")
        }

        uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
    }

    return uri ?: getUriForPreQ(fileName)
}

private fun getUriForPreQ(fileName: String): Uri {
    val dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
    val photoFile = File(dir, "/app_name/$fileName")
    if (photoFile.parentFile?.exists() == false) photoFile.parentFile?.mkdir()
    return FileProvider.getUriForFile(
        requireContext(),
        "ru.app_name.fileprovider",
        photoFile
    )
}

Qより前のWRITE_EXTERNAL_STORAGE権限について忘れずに、FileProviderをAndroidManifest.xmlに追加してください。

そして結果を得る:

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    when (requestCode) {
        REQUEST_IMAGE_CAPTURE -> {
            photoURI?.let {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                    val thumbnail: Bitmap =
                        requireContext().contentResolver.loadThumbnail(
                            it, Size(640, 480), null
                        )
                } else {
                    // pre Q actions
                }
            }
        }
    }
}
1
bitvale