标签: scoped-storage

如何解决Android 10的存储混乱

由于Android在有关文件访问的不同主要版本之间非常不一致,因此我感到有些失落。我尝试尽可能简单地描述问题:

我的公司使用商业本地DRM保护我们提供的其他本地库。我们有一个许可应用程序,该应用程序调用了一些Voodoo来结束/ sdcard / companyname / LicenseContainer /中的许可文件。其他受保护的应用程序以本机代码查看此目录,检查用户是否具有有效的许可证。

但是,Android 10更新仅提供,使该工作流程完全无效scoped storage access。我们可以使用一种方法Storage Manager来授予访问权限,不幸的是,现在也已弃用该方法。

所以我的问题是:一个应用程序如何将文件保存到/ sdcard / FOLDER上的某个位置

  1. 应用删除后未删除
  2. 其他应用可使用本机代码访问

对于所有可能的解决方案(SAF,FileProvider等),我有点不知所措,这些解决方案通常会调用一个应用程序将权限授予另一个应用程序的权限。但是,如果没有安装的第一个应用程序将文件放到那里,则应该可以访问这些文件。

我知道必须有解决方案,因为最近的FileManagers(即Files by Google)可以访问整个/sdcard/目录。

在不调用“黑客”之类的情况下,最简单,最适合未来的路线是什么 android:requestLegacyExternalStorage="true"

android file android-fileprovider storage-access-framework scoped-storage

6
推荐指数
1
解决办法
134
查看次数

Android Q:从图库中获取图像并进行处理

我知道这似乎是一个非常基本的问题,但它专门针对 Android Q。

我只想从图库中获取图像并将其压缩并发送到服务器。但是由于 Android Q 的 Scoped Storage,它比我想象的要难。我将首先解释我用代码做了什么:

首先,我发出选择图像的意图。

fun openGallery(fragment: Fragment){
    val intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
    intent.type = "*/*"
    val mimeTypes = arrayOf("image/*")
    intent.putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes)
    fragment.startActivityForResult(intent, REQUEST_IMAGE_PICK)
}
Run Code Online (Sandbox Code Playgroud)

它工作正常,我能够在 onActivityResult 方法中获取图像

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {

    if (requestCode == REQUEST_IMAGE_PICK && resultCode == Activity.RESULT_OK && null != data) {
        val selectedImage = data.data

        val source = ImageDecoder.createSource(activity!!.contentResolver, selectedImage)
        val bitmap = ImageDecoder.decodeBitmap(source)
        mBinding.circularProfileImage.setImageBitmap(bitmap)
    }
}
Run Code Online (Sandbox Code Playgroud)

好的,现在的问题是如何以文件格式访问此图像,以便我可以进一步处理/压缩它。

以下是我尝试过的事情:

val mImagePath = getImagePathFromUri(activity!!, selectedImage)
Run Code Online (Sandbox Code Playgroud)

这是我得到的路径:

/storage/emulated/0/DCIM/Camera/IMG_20191022_152437.jpg …
Run Code Online (Sandbox Code Playgroud)

android storage-access-framework android-10.0 scoped-storage

6
推荐指数
1
解决办法
8479
查看次数

在 Android 11 上将文件保存到 SD 卡上

我想将照片保存在 Android 11 上 SD 卡的外部应用程序目录中。执行此操作的正确方法是什么?我是否必须将 SAF API 与由操作 ACTION_OPEN_DOCUMENT_TREE 触发的系统选择器一起使用,其中用户必须选择 sd 卡上的文件夹?

或者也许我可以使用这个方法:

File[] externalStorageVolumes =ContextCompat.getExternalFilesDirs(mContext, null);
Run Code Online (Sandbox Code Playgroud)

并假设如果 SD 卡可用,它将打开externalStorageVolumes[1]?这适用于我的 2 台设备(搭载 Android 5 的三星 j1 和搭载 Android 10 的三星 s10),但我没有机会访问更多设备来测试它。

java android android-external-storage scoped-storage

6
推荐指数
1
解决办法
9462
查看次数

如何删除 Android 10 范围存储中的图像(媒体存储条目和文件)

当我尝试删除我的应用程序贡献/拥有的图像时,它可以轻松删除。但对于我的应用程序不拥有的图片文件夹内的共享媒体,我通过捕获 向用户显示提示RecoverableSecurityException。但即使在ALLOWING之后,我也无法删除该特定图像文件。

这是我正在使用的代码,请指出我做错了什么。

  • 删除后,图像不会出现在图库或我的应用程序中,但它保留在文件管理器中,并在手机重新启动后重新出现在图库中(我猜只有 MediaStore 条目被删除)
  • 该代码适用于 Android 11 设备。
  • 结果startIntentSenderForResult(intentSender, 12, null, 0, 0, 0, null);RESULT_OK

用于获取文件:(此代码位于“我的活动”中)

   try {
            String DIRECTORY_NAME = "%Pictures/App_Name%";
            String selection = MediaStore.MediaColumns.RELATIVE_PATH + " like ? ";
            String[] selectionArgs = new String[]{DIRECTORY_NAME};
            ContentResolver contentResolver = this.getContentResolver();
            Cursor cursor = contentResolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, selection, selectionArgs, null);

            while(cursor.moveToNext()){
                long id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID));
                Uri contentUri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, id);

                uriArrayList.add(contentUri);

            }
            cursor.close();
        }
        catch (Exception e){
            e.printStackTrace();
        }
Run Code Online (Sandbox Code Playgroud)

对于删除图像文件:(此代码位于我的适配器类中)

    try {
    ContentResolver …
Run Code Online (Sandbox Code Playgroud)

android android-contentresolver android-studio android-10.0 scoped-storage

6
推荐指数
1
解决办法
3000
查看次数

如何在Andrdoid 10上拍照并将结果保存到图片中?

Google 在 Android 10 上引入了 Scoped Storage,根据文档,我们可以使用 MediaStore API 无需请求权限即可写入公共目录。

在Android 10之前,当我们需要拍照并将其保存到图片中时,代码如下:


private void dispatchTakePictureIntent() {
    Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    // Ensure that there's a camera activity to handle the intent
    if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
        // Create the File where the photo should go
        File photoFile = null;
        try {
            photoFile = createImageFile();
        } catch (IOException ex) {
            // Error occurred while creating the File
            ...
        }
        // Continue only if the File was successfully created
        if (photoFile …
Run Code Online (Sandbox Code Playgroud)

android mediastore android-10.0 scoped-storage

5
推荐指数
0
解决办法
872
查看次数

如何使用范围存储创建外部目录并授予对目录 android 的访问权限

在我的应用程序中,我需要创建一个外部目录并将文档文件存储在子目录中。到 Android Pie,API 28,它进展顺利。从 Android 10 开始,它发生了变化,在范围存储中,我如何在外部存储中创建目录并授予对整个目录的权限?我想使用 uri 将文件下载到这些目录,我想稍后使用他们的 uri 读取它们。

android file firebase android-10.0 scoped-storage

5
推荐指数
0
解决办法
1170
查看次数

为什么 android:requestLegacyExternalStorage="true" 在 Android 10 - API 29 中不起作用

我已将项目compileSdkVersion从28迁移到29,并在清单中添加 android:requestLegacyExternalStorage="true",但下载和文件打开等文件操作无法像在 SDK 28 中那样工作

梯度文件

compileSdkVersion 29

defaultConfig {
    applicationId "in.example.app"
    minSdkVersion 21
    targetSdkVersion 29
    versionCode 90
    versionName "1.8.3"

    testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
Run Code Online (Sandbox Code Playgroud)

清单文件

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="in.example.app">

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.SMS_FINANCIAL_TRANSACTIONS" />

<application
    android:name=".MyApp"
    android:allowBackup="true"
    android:hardwareAccelerated="true"
    android:icon="@mipmap/ic_launcher"
    android:largeHeap="true"
    android:networkSecurityConfig="@xml/network_security_config"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme"
    tools:replace="android:theme,android:allowBackup"
    tools:targetApi="n"
    android:requestLegacyExternalStorage="true">

    <activity android:name=".ui.main.MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </activity>

    <provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="in.example.app.fileprovider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/provider_paths" />
    </provider> …
Run Code Online (Sandbox Code Playgroud)

android android-10.0 scoped-storage

5
推荐指数
1
解决办法
1万
查看次数

Android 11 - 在外部存储上创建应用程序特定目录

最近,我正在尝试将我的应用程序从 SDK-29 迁移到 SDK-30。我最关心的一件事是范围存储。

我在官方文档中看到“在 Android 11(API 级别 30)及更高版本上,应用程序无法在外部存储上创建自己的应用程序特定目录”。

因此,我尝试在外部存储中创建自己的目录并向其中写入一个新文件。代码如下所示:

// creating new directory under external storage
val appDir = File(applicationContext.getExternalFilesDir(null), "play")
appDir.mkdir()

// writing new file under my own directory
val newFile = File(appDir.absolutePath, "test.jpg")
val outputStream = FileOutputStream(newFile)
val inputStream = resources.openRawResource(R.drawable.ic_launcher_foreground)
val data = byteArrayOf()
inputStream.read(data)
outputStream.write(data)
inputStream.close()
outputStream.close()
Run Code Online (Sandbox Code Playgroud)

我预计这段代码会崩溃,但它有效。我在给定路径中找到该文件。所以,我有点困惑那张纸条的含义。

Google“无法在外部存储上创建自己的应用程序特定目录”是什么意思?

android scoped-storage

5
推荐指数
1
解决办法
3161
查看次数

通过 Intent 共享照片时 EXIF 位置数据被删除

我最近将我的应用程序切换到范围存储。但是,我注意到,当我从应用程序内共享图像(通过 Intent)时,GPS 位置数据将从图像的 Exif 元数据中删除。我知道范围存储对访问图像的 Exif 位置数据有一些限制,并且我知道该权限<uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />,但是添加此权限在共享图像时似乎没有任何效果。知道如何通过 Intent 共享图像,同时保留图像 Exif 数据中的位置数据吗?

这是我的代码:

 val imageUri = mediaList[photo_view_pager.currentItem].uri

 val intent = Intent().apply {
     val mediaType = MimeTypeMap.getSingleton()
        .getMimeTypeFromExtension("jpg")
     putExtra(Intent.EXTRA_STREAM, imageUri)
     type = mediaType
     action = Intent.ACTION_SEND
     flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
 }

 startActivity(Intent.createChooser(intent, getString(R.string.share_hint)))
Run Code Online (Sandbox Code Playgroud)

预先非常感谢您的帮助!

android geolocation mediastore android-intent scoped-storage

5
推荐指数
1
解决办法
1330
查看次数

Android 11:卸载后重新获得应用文件夹所有权

我有一个关于 Android 11 中存储更改的问题。如果我理解正确,应用程序可以读取/写入/删除它创建的文件。然后我还可以访问这些文件,例如如下所示:

File path = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString() + "/ExampleApp/" + fileName);
Run Code Online (Sandbox Code Playgroud)

ExampleApp is the app folder I created in the public Downloads folder. But once the app gets uninstalled, it losses the ownership over all the files it created. Is there a way to regain the ownership of the ExampleApp folder by the app once it gets reinstalled? One could use scoped storage & ACTION_OPEN_DOCUMENT_TREE, but that would then have to be done on every fresh start …

android scoped-storage android-11

5
推荐指数
1
解决办法
950
查看次数