相关疑难解决方法(0)

为什么getExternalFilesDirs()在某些设备上不起作用?

我的应用在Android 5.0上运行.我用方法getExternalFilesDirs()来检查外部SD卡是否可用.如果返回超过1 File,则表示存在外部SD卡.

但是在某些设备(例如Elephone G2)上,方法getExternalFilesDirs()只返回一个主存储目录.我确定该设备有外部SD卡(/ storage/sdcard1 /).

任何人都可以给我答案吗?

android android-sdcard android-external-storage

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

正确删除DocumentFile(尊重MediaStore)

我有DocumentFile以下两种定义:

DocumentFile documentFile;
Uri documentFileUri;
Run Code Online (Sandbox Code Playgroud)

我可以通过以下方法从SD卡中删除文档文件:

  1. documentFile.delete();
  2. DocumentsContract.deleteDocument(contentResolver, documentFileUri);

但以上方法均不能从中删除相应的条目MediaStore

处理该问题的正确方法是什么?如果我使用ContentProvider删除本地文件,它将File从数据库(contentResolver.delete(localFileUri, null, null);)中删除AND行。我希望如果使用,也会发生相同的情况,DocumentsContract但不会发生...

我想要的是

我想了解一下更新MediaStore。通常我会打电话给我,contentResolver.delete(documentFileUri, null, null);但这会失败,但有一个例外,说uri不支持删除...

是否有比我的解决方法更有效的方法?

解决方法

目前,我在删除a后使用以下功能立即更新媒体存储DocumentFile

public static boolean updateAfterChangeBlocking(String path, int timeToWaitToRecheckMediaScanner)
{
    final AtomicBoolean changed = new AtomicBoolean(false);
    MediaScannerConnection.scanFile(StorageManager.get().getContext(),
            new String[]{path}, null,
            new MediaScannerConnection.OnScanCompletedListener() {
                public void onScanCompleted(String path, Uri uri) {
                    changed.set(true);
                }
            });

    while (!changed.get()) {
        try {
            Thread.sleep(timeToWaitToRecheckMediaScanner);
        } catch (InterruptedException e) …
Run Code Online (Sandbox Code Playgroud)

android storage-access-framework documentfile

9
推荐指数
1
解决办法
978
查看次数

额外启用带存储访问框架(SAF)的显示/隐藏SD卡

我正在使用存储访问框架(SAF):

Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/*");
startActivityForResult(intent, 0);
Run Code Online (Sandbox Code Playgroud)

我想知道是否有一个额外的启用显示SD卡选项,用户可以在溢出菜单中看到.

在此输入图像描述

android storage-access-framework

7
推荐指数
1
解决办法
1309
查看次数

如何使用Android 5.0的新SD卡访问API设置上次修改的文件属性?

背景:

使用:ACTION_OPEN_DOCUMENT_TREE + DocumentFile

更多信息: 如何使用针对Android 5.0(Lollipop)推出的新SD卡访问API?

我想问一下:

我找不到如何更改文件属性的方法.有没有?

特别是,我需要更改Last Modified属性 - 比如File Class方法:

public boolean setLastModified(long time); 
Run Code Online (Sandbox Code Playgroud)

我没有找到任何替补:

https://developer.android.com/reference/android/support/v4/provider/DocumentFile.html

或者在DocumentsContract之类的相关类中,...

新API的文档几乎没用,API函数运行速度极慢,新API的代码重写非常麻烦.我很抱歉这么强硬,但Kitkat"EACCESS(Permission denied)功能"花了我几年的生命而不是解决方案我会得到这个.

编辑:

似乎setLastModified(...)方法即使使用java.io.FileClass 也不起作用(至少从Android版本4.4开始):

https://code.google.com/p/android/issues/detail?id=18624

例如,如果您有一个归档应用程序,并且您想要真正的上次修改时间,而不是从归档中提取文件的时间 - 抱歉.很多同步工具变得无用......

编辑2:

Android 5.1(模拟器):setLastModified(long time)方法仍然不起作用.

编辑3:

Android 6.0(模拟器):setLastModified(long time)方法仍然无法正常工作.

android file sd-card android-5.0-lollipop documentfile

6
推荐指数
0
解决办法
2115
查看次数

Android - 获取DocumentFile,对sd卡上的任何文件路径具有写访问权限(已获得sd卡权限)

在我的应用程序中,我使用以下意图获得SD卡写入权限.如果用户从系统文件资源管理器中选择sd卡文件夹,那么我有SD卡写访问权限.

Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
intent.putExtra("android.content.extra.SHOW_ADVANCED", true);
startActivityForResult(intent, 42);
Run Code Online (Sandbox Code Playgroud)

之后,我可以使用DocumentFile类修改SD卡中的文件.但我在获取随机文件路径的DocumentFile时遇到问题.

Document.fromFile(new File(path));
Document.fromSingleUri(Uri.fromFile(new File(path)));
Run Code Online (Sandbox Code Playgroud)

两者都返回一个DocumentFile对象,该对象在.canWrite()上返回false.即使我已经获得SD卡许可.

所以我编写了在我的问题末尾发布的方法,以获得一个在.ca​​nWrite()上返回true的DocumentFile.但这很慢......而且感觉非常错误!必须有更好的方法来做到这一点.我还写了一个返回相同字符串的方法

String docFileUriString = docFile.getUri().toString(); 
Run Code Online (Sandbox Code Playgroud)

对于任何文件,其中docFile是由下面的方法返回的DocumentFile.但

DocumentFile.fromTreeUri(Uri.parse(docFileUriString ));
Run Code Online (Sandbox Code Playgroud)

返回一个DocumentFile,它指向sd卡的根,而不是DocumentFile路径.这很奇怪.有人可以提出更优雅的解决方案吗?

public static DocumentFile getDocumentFileIfAllowedToWrite(File file, Context con){ 

    List<UriPermission> permissionUris = con.getContentResolver().getPersistedUriPermissions();

    for(UriPermission permissionUri:permissionUris){

        Uri treeUri = permissionUri.getUri();
        DocumentFile rootDocFile = DocumentFile.fromTreeUri(con, treeUri);
        String rootDocFilePath = FileUtil.getFullPathFromTreeUri(treeUri, con);

        if(file.getAbsolutePath().startsWith(rootDocFilePath)){

            ArrayList<String> pathInRootDocParts = new ArrayList<String>();
            while(!rootDocFilePath.equals(file.getAbsolutePath())){
                pathInRootDocParts.add(file.getName());
                file = file.getParentFile();
            } 

            DocumentFile docFile = null;  

            if(pathInRootDocParts.size()==0){ 
                docFile = DocumentFile.fromTreeUri(con, rootDocFile.getUri()); 
            }
            else{
                for(int i=pathInRootDocParts.size()-1;i>=0;i--){
                    if(docFile==null){docFile = rootDocFile.findFile(pathInRootDocParts.get(i));} …
Run Code Online (Sandbox Code Playgroud)

android android-sdcard documentfile

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

mkdirs aways 在 Android 5.1 中返回 false

我搜索了这些问题,但无法解决。请帮我解决这个问题

那是我的 mkdir 代码:

File _sdcardPath = Environment.getExternalStorageDirectory(); // sdcard path is /storage/emulate/0
File _dirPath = new File(_sdcardPath, "CreateFolder");
boolean _isCreate = _dirPath.mkdir();
if (_isCreate) {
   tvResult.append(_dirPath + " mkdir success");
} else {
   tvResult.append(_dirPath + " mkdir fail");
}
Run Code Online (Sandbox Code Playgroud)

我的 manifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.createfolder"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

    <uses-sdk
        android:minSdkVersion="11"
        android:targetSdkVersion="21" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

</manifest>
Run Code Online (Sandbox Code Playgroud)

我的设备android版本是:5.1.1,12GB可用空间,代码在5.0下正常运行

在运行应用程序时,我遇到了这个异常: …

android exception-handling

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

当我只能处理文件或文件路径时如何处理 SAF?

背景

在 Android Q 之前,如果我们想要获取有关 APK 文件的信息,我们可以使用WRITE_EXTERNAL_STORAGEREAD_EXTERNAL_STORAGE来访问存储,然后在文件路径上使用PackageManager.getPackageArchiveInfo函数。

类似的情况也存在,例如在压缩文件上使用ZipFile 类,可能还有无数的框架 API 和第三方库。

问题

谷歌最近宣布了对 Android Q 的大量限制。

其中之一称为“范围存储”,当访问设备拥有的所有文件时,它会破坏存储权限。它可以让您处理媒体文件,或者使用非常受限的存储访问框架 ( SAF ),该框架不允许应用程序使用文件 API 和文件路径访问和使用文件。

当Android Q Beta 2发布时,它破坏了很多应用程序,包括谷歌的应用程序。原因是它默认打开,影响所有应用程序,无论它们是否针对 Android Q。

原因是许多应用程序、SDK 和 Android 框架本身 - 都经常使用文件 API。在许多情况下,它们也不支持 InputStream 或 SAF 相关的解决方案。一个例子就是我写的 APK 解析示例 (PackageManager.getPackageArchiveInfo)。

然而,在 Q beta 3 上,情况发生了一些变化,因此目标 Q 的应用程序将具有范围存储,并且有一个标志可以禁用它,但仍然像往常一样使用正常的存储权限和文件 API。遗憾的是,该标志只是暂时的(请阅读此处),因此它推迟了不可避免的事情。

我尝试过的

我已经尝试并发现了接下来的事情:

  1. 使用存储权限确实不允许我读取任何非媒体文件的文件(我想找到 APK 文件)。就好像这些文件不存在一样。

  2. 使用 SAF,我可以找到 APK 文件,并通过一些解决方法来找到其真实路径(链接此处),我注意到文件 API 可以告诉我该文件确实存在,但无法获取其大小,并且框架无法使用其路径getPackageArchiveInfo在这里写过这个

  3. 我尝试创建到该文件的符号链接(链接此处 …

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

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

在 Android 11 上写入许多文件

设想

我正在尝试创建许多文件,作为用户的一项功能。例如,我可能会编写一个应用程序,为他们过去几周听过的每首歌曲创建一个文件(例如,带有歌词的文本文件)。我不能让用户为我生成的每个文件选择目录和文件名,这需要他们几个小时。用户应该可以从其他应用程序访问这些文档。

解决方案(不是真的)

在 Android 11 中,存储访问框架似乎没有用处。我注意到最初有两个有趣的选项:

  1. 创建一个新文件(创建用户与之交互的启动活动以仅保存一个文件),描述here
  2. 授予对目录内容的访问权限(允许读取访问,但无法写入任何文档),描述为here
  3. 注意:如果您面向 Android 10 并请求WRITE_EXTERNAL_STORAGE. 不幸的是,此权限在 Android 11 上被拒绝。因此,我无法使用此处发布的解决方案。
  4. 使用存储访问框架(特别是 ACTION_OPEN_DOCUMENT_TREE)访问目录以访问目录,但我无法将文件写入此目录。(我明白了FileNotFoundException,因为这不是普通路径,而是树路径。)

判决书

我想在我的情况下,我需要沿着“管理存储设备上的所有文件”的路线走下去,如此处所述这涉及使用ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION. 我宁愿不请求读取整个驱动器的权限,也不想让用户进入设置应用程序以授予权限。写入文件不应该需要任何权限...

您将如何为用户保存许多(非媒体)文件?

android storage-access-framework

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

如何在运行KITKAT的设备上使用新的Lollipop SD卡访问API?

Kit-Kat问题无法写入外部SD卡,

Goolge文档中所述 为了简化运行KITKAT或更早版本的设备上的代码,您可以使用fromFile(File)模拟DocumentsProvider的行为 下面的代码(New API)适用于Lollipop,但如何使用kitkat的新API?

另请参阅Kit-Kat问题(新API)

public class MyActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_my);
    Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
    startActivityForResult(intent, 42);
}

public void onActivityResult(int requestCode, int resultCode, Intent resultData) {
    if (resultCode == RESULT_OK) {
        Uri treeUri = resultData.getData();
        DocumentFile pickedDir = DocumentFile.fromFile(new File("/mnt/extSdCard/Test"));

        // List all existing files inside picked directory
        for (DocumentFile file : pickedDir.listFiles()) {
            Log.d("Tag", "Found file " + file.getName() + " with size " + file.length()); …
Run Code Online (Sandbox Code Playgroud)

java android android-sdcard

3
推荐指数
1
解决办法
2215
查看次数

写入 SD 卡总是失败

我正在尝试将文件从任何位置(包括内部设备存储)移动到 SD 卡,

为此我有

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Run Code Online (Sandbox Code Playgroud)

在我的清单中,并通过检查是否使用以下方法授予权限来检查它是否有效:

Contex.checkCallingOrSelfPermission("android.permission.WRITE_EXTERNAL_STORAGE")Contex.checkCallingOrSelfPermission("android.permission.READ_EXTERNAL_STORAGE")

我尝试了 3 种不同的方法来做到这一点:

  1. Files.move(original, newPath1),它是 Guava com.google.common.io 自带的
  2. 这种方法:

    public static void move(File src, File dst) throws IOException {
        FileInputStream inStream = new FileInputStream(src);
        FileOutputStream outStream = new FileOutputStream(dst);
        FileChannel inChannel = inStream.getChannel();
        FileChannel outChannel = outStream.getChannel();
        inChannel.transferTo(0, inChannel.size(), outChannel);
        inStream.close();
        outStream.close();
    }
    
    Run Code Online (Sandbox Code Playgroud)
  3. original.renameTo(newPath1);

我阅读了很多关于此的 SO 帖子,我尝试过的所有解决方案都不起作用,我确保安装了 SD 卡,并且在尝试时我没有将我的设备连接到 PC。我什至尝试了 2 种不同的带有 SD 卡的设备。请注意,我可以使用 BitmapFactory.decode() 以完全相同的路径访问图像,并且可以将该图像加载到 imageview。

我总是收到 EACCES(权限被拒绝)。我不知道还能做什么来解决这个问题:(

11-13 11:11:54.358 19192-19372/xaday.ofek.ron.xaday W/System.err: java.io.FileNotFoundException: /storage/sdcard1/DCIM/thai2/IMG-20150702-WA0001.jpg: open …
Run Code Online (Sandbox Code Playgroud)

android android-sdcard

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