如何将文件保存到 Android Q(API 29)上的公共(外部)存储?

我一直在使用外部存储来保存不同类型的文件。该文件需要对用户可见。现在从 Android Q 开始,该方法getExternalStoragePublicDirectory()已被弃用getExternalStoragePublicDirectory(docs)。

我使用了以下代码:

File externalFilesDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "DirectoryName");

还有另一种方法可以保存用户可见的文件吗?


墨色风雨
浏览 189回答 4
4回答

函数式编程

您需要为 Android Q 添加检查。假设您要将图像保存在公共下载文件夹中。try{     OutputStream fos;    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {       ContentResolver resolver = context.getContentResolver();       ContentValues contentValues = new ContentValues();       contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, fileName);       contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpg");       contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS);       Uri imageUri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);       fos = resolver.openOutputStream(Objects.requireNonNull(imageUri));    } else {       String imagesDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString();       File image = new File(imagesDir, fileName);       fos = new FileOutputStream(image);    }     finalBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);     Objects.requireNonNull(fos).close();}catch (IOException e) {  // Log Message}

POPMUISE

在android Q及以下verison中保存捕获位图private class AsyncTaskExample extends AsyncTask<String, String, Bitmap> {&nbsp; &nbsp; &nbsp; &nbsp; Bitmap icon = null;&nbsp; &nbsp; &nbsp; &nbsp; ByteArrayOutputStream bytes;&nbsp; &nbsp; @Override&nbsp; &nbsp; protected void onPreExecute() {&nbsp; &nbsp; &nbsp; &nbsp; super.onPreExecute();&nbsp; &nbsp; &nbsp; &nbsp; mBitmap = BaseApplication.getInstance().getBitmap();&nbsp; &nbsp; &nbsp; &nbsp; ((BaseActivity)mContext).showFullScreenProgressLoader(((BaseActivity)mContext), ((BaseActivity)mContext).getString(R.string.please_wait), ((BaseActivity)mContext).getString(R.string.we_are_processing_your_request));&nbsp; &nbsp; }&nbsp; &nbsp; @Override&nbsp; &nbsp; protected Bitmap doInBackground(String... strings) {&nbsp; &nbsp; &nbsp; &nbsp; try {&nbsp; &nbsp; &nbsp; String imageFileName = "picture_" + System.currentTimeMillis() + ".jpg";&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; File directory = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + "/" + Constants.INTERNAL_FOLDER_NAME + "/");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; directory.mkdirs();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mFile = new File(directory, imageFileName);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!mFile.isFile()) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mFile.createNewFile();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } catch (IOException e) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; e.printStackTrace();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (Build.VERSION.SDK_INT == Build.VERSION_CODES.Q) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; final ContentResolver resolver = ((CameraFaceDetectionActivity) mContext).getContentResolver();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; insertImage(resolver, mBitmap, mFile.getAbsolutePath(), "");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FileOutputStream out = new FileOutputStream(mFile);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try {//&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mBitmap = modifyOrientation(mBitmap,mFile.getAbsolutePath());&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; OutputStream output = new FileOutputStream(mFile);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, output);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; output.flush(); // Not really required&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; output.close();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; catch (IOException e) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; e.printStackTrace();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; } catch(Exception e){&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; e.printStackTrace();&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; return mBitmap;&nbsp; &nbsp; }&nbsp; &nbsp; @Override&nbsp; &nbsp; protected void onPostExecute(Bitmap bitmap) {&nbsp; &nbsp; &nbsp; &nbsp; super.onPostExecute(bitmap);&nbsp; &nbsp; &nbsp; &nbsp; final Handler handler = new Handler();&nbsp; &nbsp; &nbsp; &nbsp; handler.postDelayed(new Runnable() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @Override&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; public void run() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; OutputStream output = new FileOutputStream(mFile);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Bitmap b = modifyOrientation(mBitmap, mFile.getAbsolutePath());&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; b.compress(Bitmap.CompressFormat.JPEG, 100, output);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } catch (IOException e) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; e.printStackTrace();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; startActivity(new Intent(mContext, SelfiePreviewForgetPsdActivity.class)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .putExtra(Constants.KEY_MOBILE, mMobileNumber)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .putExtra(Constants.KEY_COUNTRY_CODE, mCountryCode)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .putExtra(KEY_ID_NUMBER, idNumber)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .putExtra(Constants.KEY_USER_DETAIL, mVerifyUserDetailResponse)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .putExtra(KEY_ID_TYPE, idType)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .putExtra(Constants.IMAGE_PATH, mFile.getAbsolutePath()));&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }, 500);&nbsp; &nbsp; }}下面是在android Q上保存位图指定文件夹的方法public static String insertImage(ContentResolver cr,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Bitmap source,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;String title,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;String description) {&nbsp; &nbsp; ContentValues values = new ContentValues();&nbsp; &nbsp; values.put(MediaStore.Images.Media.TITLE, title);&nbsp; &nbsp; values.put(MediaStore.Images.Media.DISPLAY_NAME, title);&nbsp; &nbsp; values.put(MediaStore.Images.Media.DESCRIPTION, description);&nbsp; &nbsp; values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpg");&nbsp; &nbsp; // Add the date meta data to ensure the image is added at the front of the gallery&nbsp; &nbsp; values.put(MediaStore.Images.Media.DATE_ADDED, System.currentTimeMillis());&nbsp; &nbsp; values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis());&nbsp; &nbsp; Uri url = null;&nbsp; &nbsp; String stringUrl = null;&nbsp; &nbsp; /* value to be returned */&nbsp; &nbsp; try {&nbsp; &nbsp; &nbsp; &nbsp; url = cr.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);&nbsp; &nbsp; &nbsp; &nbsp; if (source != null) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; OutputStream imageOut = cr.openOutputStream(url);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; source.compress(Bitmap.CompressFormat.JPEG, 100, imageOut);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } finally {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; imageOut.close();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; long id = ContentUris.parseId(url);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Wait until MINI_KIND thumbnail is generated.&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Bitmap miniThumb = MediaStore.Images.Thumbnails.getThumbnail(cr, id, MediaStore.Images.Thumbnails.MINI_KIND, null);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // This is for backward compatibility.&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; storeThumbnail(cr, miniThumb, id, source.getWidth(), source.getHeight(), MediaStore.Images.Thumbnails.MICRO_KIND);&nbsp; &nbsp; &nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cr.delete(url, null, null);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; url = null;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; } catch (Exception e) {&nbsp; &nbsp; &nbsp; &nbsp; if (url != null) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cr.delete(url, null, null);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; url = null;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; if (url != null) {&nbsp; &nbsp; &nbsp; &nbsp; stringUrl = url.toString();&nbsp; &nbsp; }&nbsp; &nbsp; return stringUrl;}保存位图方法&nbsp;private static final Bitmap storeThumbnail(&nbsp; &nbsp; &nbsp; &nbsp; ContentResolver cr,&nbsp; &nbsp; &nbsp; &nbsp; Bitmap source,&nbsp; &nbsp; &nbsp; &nbsp; long id,&nbsp; &nbsp; &nbsp; &nbsp; float width,&nbsp; &nbsp; &nbsp; &nbsp; float height,&nbsp; &nbsp; &nbsp; &nbsp; int kind) {&nbsp; &nbsp; // create the matrix to scale it&nbsp; &nbsp; Matrix matrix = new Matrix();&nbsp; &nbsp; float scaleX = width / source.getWidth();&nbsp; &nbsp; float scaleY = height / source.getHeight();&nbsp; &nbsp; matrix.setScale(scaleX, scaleY);&nbsp; &nbsp; Bitmap thumb = Bitmap.createBitmap(source, 0, 0,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; source.getWidth(),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; source.getHeight(), matrix,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; true&nbsp; &nbsp; );&nbsp; &nbsp; ContentValues values = new ContentValues(4);&nbsp; &nbsp; values.put(MediaStore.Images.Thumbnails.KIND, kind);&nbsp; &nbsp; values.put(MediaStore.Images.Thumbnails.IMAGE_ID, (int) id);&nbsp; &nbsp; values.put(MediaStore.Images.Thumbnails.HEIGHT, thumb.getHeight());&nbsp; &nbsp; values.put(MediaStore.Images.Thumbnails.WIDTH, thumb.getWidth());&nbsp; &nbsp; Uri url = cr.insert(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, values);&nbsp; &nbsp; try {&nbsp; &nbsp; &nbsp; &nbsp; OutputStream thumbOut = cr.openOutputStream(url);&nbsp; &nbsp; &nbsp; &nbsp; thumb.compress(Bitmap.CompressFormat.JPEG, 100, thumbOut);&nbsp; &nbsp; &nbsp; &nbsp; thumbOut.close();&nbsp; &nbsp; &nbsp; &nbsp; return thumb;&nbsp; &nbsp; } catch (Exception ex) {&nbsp; &nbsp; &nbsp; &nbsp; return null;&nbsp; &nbsp; }}

白板的微信

File newDir = new File (Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + "folder_name");&nbsp; &nbsp; if (!newDir.exists()) {&nbsp; &nbsp; &nbsp; &nbsp; newDir.mkdirs();&nbsp; &nbsp; &nbsp; &nbsp;}&nbsp; &nbsp;&nbsp;File file = new File(newDir, imagename);&nbsp; &nbsp;try {&nbsp; &nbsp; &nbsp; FileOutputStream out = new FileOutputStream(file);&nbsp; &nbsp; &nbsp; bmpOverlay.compress(Bitmap.CompressFormat.PNG, 100, out);&nbsp; &nbsp; &nbsp; out.flush();&nbsp; &nbsp; &nbsp; out.close();} catch (Exception e) {&nbsp; &nbsp; &nbsp;Log.e("interior", "Save image to SD");}

浮云间

Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)替换为:&nbsp;&nbsp;&nbsp;requireContext().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS)!!.absolutePath
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java