এনভায়রনমেন্ট.জেটএক্সটার্নাল স্টোরেজ ডিরেক্টরী () এপিআই স্তরের 29 জাভাতে অবমূল্যায়ন করা হয়েছে


102

অ্যান্ড্রয়েড জাভাতে কাজ করা, সম্প্রতি এসডিকে আপডেট করা হয়েছে এপিআই স্তর ২৯ এ 29 এখন একটি সতর্কতা দেখানো হয়েছে যা দেখায় যে

Environment.getExternalStorageDirectory() এপিআই স্তর 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");
            }
       });
   }

এর বিকল্প কী হবে?

উত্তর:


94

ব্যবহারের getExternalFilesDir(), getExternalCacheDir()অথবা getExternalMediaDirs()(চালু পদ্ধতি Context) পরিবর্তে Environment.getExternalStorageDirectory()

অথবা, এর mPhotoEditorসাথে কাজ করতে সক্ষম হতে সংশোধন করুন Uri, তারপরে:

  • ব্যবহারকারীর পছন্দের কোনও স্থানে ACTION_CREATE_DOCUMENTযেতে ব্যবহার করুন Uriবা

  • নির্দিষ্ট ধরণের মিডিয়া (উদাহরণস্বরূপ, একটি চিত্র) পাওয়ার জন্য ব্যবহার করুন MediaStore, ContentResolverএবং insert()এটি পেতে Uri- কোনও ওয়েব সাইট থেকে এমপি 4 ভিডিও ডাউনলোড করার জন্য এটি করার নমুনা অ্যাপ্লিকেশনটি দেখুন

এছাড়াও, নোট করুন যে আপনার Uri.fromFileসাথে ACTION_MEDIA_SCANNER_SCAN_FILEঅ এর সাথে অ্যান্ড্রয়েড 7.0+ এ ক্র্যাশ হওয়া উচিত FileUriExposedException। অ্যান্ড্রয়েড কিউ-তে, কেবলমাত্র MediaStore/ insert()বিকল্পগুলি আপনার সামগ্রীগুলি MediaStoreদ্রুত তালিকাভুক্ত করবে ।

মনে রাখবেন আপনি অ্যান্ড্রয়েড 10 এবং 11 এই "scoped স্টোরেজ" পরিবর্তন ছেড়ে যেতে পারেন, যদি আপনার targetSdkVersion, 30 নিচে ব্যবহার android:requestLegacyExternalStorage="true"মধ্যে <application>ম্যানিফেস্টের উপাদান। এটি কোনও দীর্ঘমেয়াদী সমাধান নয় , কারণ targetSdkVersionআপনি যদি প্লে স্টোর (এবং সম্ভবত অন্য কোথাও) এর মাধ্যমে আপনার অ্যাপ্লিকেশনটি বিতরণ করেন তবে আপনার ইচ্ছা 2021 সালের মধ্যে 30 বা তার বেশি হওয়া উচিত।


10
প্রিয় @ কমন্সওয়্যার, আমাদের যদি কখনও সত্যিকারের লাইভে দেখা হয় তবে দয়া করে আমাকে মনে করিয়ে দিন যে আমি আপনার ব্লগ পোস্টের জন্য একটি বিয়ার পাওনা। একটি নির্দিষ্ট বাহ্যিক গ্রন্থাগার কেন কাজ বন্ধ করে দিয়েছে তা খুঁজে বের করার জন্য আমি পুরো দুপুর কাটিয়েছি, আমি টার্গেট এসডকে স্তরটি 29-এ বাড়ানোর সাথে সাথেই Now এখন আমি জানি কেন ...
ন্যান্টোকা

4
getExternFilesDir () এবং getExternCacheDir () ব্যবহার করে এপিআই 29 দিয়ে কাজ করতে পারে তবে অ্যাপটি অবিসংযুক্ত থাকা অবস্থায় এই পদ্ধতিগুলি ব্যবহার করে সমস্ত ডেটা সরিয়ে ফেলা হবে ... আপনি যদি অ্যাপ্লিকেশন ট্যাগের মধ্যে এই বৈশিষ্ট্যটি ব্যবহার করেন "অ্যান্ড্রয়েড: রিকোয়েস্টএক্সটার্নসটোরেজ =" সত্য "" এপিআইয়ের জন্যও কাজ করতে পারে 29। অ্যাপ্লিকেশনের আনইস্টল ফাইলের নামটি বের হয়ে গেলেও ডেটা সরিয়ে ফেলা হয়
Ucdemir

4
@ মিলাদসালিমি: দুঃখিত, তবে আমি আপনার প্রশ্নটি বুঝতে পারি না। আমি আপনাকে পরামর্শ দিচ্ছি যে আপনি একটি পৃথক স্ট্যাক ওভারফ্লো প্রশ্ন জিজ্ঞাসা করুন যেখানে আপনার উদ্বেগটি কী তা আপনি বিশদে ব্যাখ্যা করবেন।
কমন্সওয়্যার

4
সেখানে নেই getExternalMediaDirContext, এটা নিজেকে দেখুন: developer.android.com/reference/android/content/Context আর getExternalMediaDirsনিন্দা করা হয়েছে, এছাড়াও দেখুন: developer.android.com/reference/android/content/... উভয় getExternalFilesDir()এবং getExternalCacheDir()অ্যাপ্লিকেশনটি আনইনস্টল উপর মুছে ফেলা হয় ( একই ইউআরএল দেখুন)। সুতরাং, উপরের কেউ বিকল্প করতে পারবেন না Environment.getExternalStorageDirectory()
Dims

4
এটি খনি ব্যবহারের ক্ষেত্রে নয়, উপরে টপিক স্টার্টারের ব্যবহারক্ষেত্র সম্পর্কে।
Dims

29

destPathনতুন এপিআই কল সহ এটি পান :

String destPath = mContext.getExternalFilesDir(null).getAbsolutePath();

4
আমরা এই পদ্ধতিটি ব্যবহার করতে পারি: developer.android.com/training/data-stores/… ? আপনি এটি সম্পর্কে কি মনে করেন ? :)
aeroxr1

4
পরিবেশের পরিবর্তনশীল getExternFilesDir (পরিবেশ। IDRECTORY_DOWNLOADS) এর পরিবর্তে পরিবেশের স্থান পরিবর্তন করতে পারে। বহির্মুখী গণপরিবহন ডিরেক্টরি (পরিবেশ.ড্রেইটারেক্টরি_ডাউনলোড)
রোয়ান বেরি

বহিরাগত স্টোরেজ 29 লক্ষ্যবস্তু করার জন্য createNewwile থেকে ত্রুটিযুক্ত এই ফিক্সড "অনুমতি অস্বীকার" এ ত্রুটিযুক্ত! ধন্যবাদ!
coolcool1994

এটি সর্বজনীন ডিরেক্টরি নয়
ইরফান উল হক

22

অ্যান্ড্রয়েড কিউয়ের জন্য, আপনি android:requestLegacyExternalStorage="true"ম্যানিফেস্টে আপনার উপাদানটি যুক্ত করতে পারেন । এটি আপনাকে উত্তীর্ণ স্টোরেজ মডেলটিতে বেছে নিয়েছে এবং আপনার বিদ্যমান বাহ্যিক স্টোরেজ কোডটি কাজ করবে।

<manifest ... >
<!-- This attribute is "false" by default on apps targeting
     Android 10 or higher. -->
  <application android:requestLegacyExternalStorage="true" ... >
    ...
  </application>
</manifest>

প্রযুক্তিগতভাবে, আপনি কেবল targetSdkVersionএটি 29 এর ক্ষেত্রে আপডেট করার পরে আপনার প্রয়োজন। নিম্ন targetSdkVersionমানের মানসম্পন্ন অ্যাপ্লিকেশনগুলি উত্তরাধিকারী সঞ্চয়স্থানের android:requestLegacyExternalStorage="false"বিকল্প বেছে নিতে অপ্ট আউট করতে হবে ।


4
এই পোস্টটি আমার অনুসন্ধানটি পূর্ববর্তী বিকাশিত কোড সহ অ্যান্ড্রয়েড স্টুডিওর সর্বশেষ সংস্করণে বাহ্যিক স্টোরেজে ডেটা সংরক্ষণের সমাধানের জন্য সন্ধান করেছে - যা 8 ঘন্টা স্থায়ী ছিল। ধন্যবাদ.
শ্রীরাম নাদিমিন্তি

4
এটি এপিআই ২৯ অবধি কাজ করবে। "সতর্কতা: আপনার অ্যাপ্লিকেশনটি অ্যান্ড্রয়েড 11 (এপিআই স্তর 30) টার্গেট করার জন্য আপডেট করার পরে, আপনার অ্যাপ্লিকেশনটি অ্যান্ড্রয়েড 11 ডিভাইসে চলমান থাকা অবস্থায় সিস্টেমটি অনুরোধের আবেদনটি উপেক্ষা করে, সুতরাং আপনার অ্যাপ্লিকেশনটি স্কোপ সমর্থন করতে প্রস্তুত থাকতে হবে সঞ্চয়স্থান এবং সেই ডিভাইসে ব্যবহারকারীদের জন্য অ্যাপ্লিকেশন ডেটা স্থানান্তরিত করতে। ডেভেলপার.আ্যান্ড্রয়েড
ট্রেনিং

5

আপনি যদি ডিফল্ট ক্যামেরা ব্যবহার করে ফটো তোলা এবং একটি DCIM ফোল্ডারে (DCIM / app_name / filename.jpg) সংরক্ষণ করতে চান তবে এটি কোনও ছোট উদাহরণ হিসাবে কীভাবে কোনও ফাইলের জন্য ইউআরআই পাবেন?

ক্যামেরা খুলুন (ক্যামেরার অনুমতি সম্পর্কে মনে রাখবেন):

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

এবং ইউআরআই পান:

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

প্রি কিউর জন্য ডাব্লুআরআইটি.এসইটিআরেক্টরএনএলপিপিআরজি অনুমতি সম্পর্কে ভুলে যাবেন না এবং অ্যান্ড্রয়েড ম্যানিফেস্ট.এক্সএমএলে একটি ফাইলপ্রবাহ যোগ করুন।

এবং একটি ফলাফল পান:

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
                }
            }
        }
    }
}


এটি জাভা পোস্ট করুন
আততুল্লাহ

5

দযা করে ব্যবহারের getExternalFilesDir(), getExternalCacheDir()পরিবর্তে Environment.getExternalStorageDirectory()যখন আপনি Android 10 ফাইল তৈরি।

নীচের লাইন দেখুন:

val file = File(this.externalCacheDir!!.absolutePath, "/your_file_name")

4
হাই, getExternalFilesDir()চিত্রটি সংরক্ষণের জন্য আমরা কীভাবে কাস্টম পাথ দিয়ে ব্যবহার করতে পারি , আমি গ্যালারীটিতে চিত্রগুলি প্রদর্শন করতে বাধা দেওয়ার জন্য এটি ব্যবহার করতে চাই? ডিফল্টরূপে এটি সংরক্ষণ করুনAndorid/data/packagename/...
মিলাদ সালিমি

আপনাকে অ্যাপ ডিরেক্টরিতে ফাইলটি সংরক্ষণ করতে হবে এবং তারপরে এটি মিডিয়া ইউরি ব্যবহার করে
sertোকাতে হবে

4
ভুল উত্তর .. কীভাবে / স্টোরেজ / এমুলেটেড / 0 / মাইফোর্ডার পাবেন / তবে আপনার আনসার / ডেটা / ইউজার/0/com.example.package/files/MyFolder
তারিফ চাকদার

3

এটি আমার পক্ষে কাজ করেছে

manifestফাইলের অ্যাপ্লিকেশন ট্যাগে এই লাইনটি যুক্ত করুন

android:requestLegacyExternalStorage="true"

উদাহরণ

 <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:networkSecurityConfig="@xml/network_security_config"
        android:requestLegacyExternalStorage="true"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

 </application>

টার্গেট এসডিকে 29

  defaultConfig {
        minSdkVersion 16
        targetSdkVersion 29
        multiDexEnabled true
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

4
এই মন্তব্যের সদৃশ: stackoverflow.com/a/61774820/7487335
জোশ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.