Android 应用程序对 SD 卡的读取权限在特定平板电脑三星 T290上停止工作并更新了软件

问题描述

为我们开发的应用 (https://play.google.com/store/apps/details?id=io.rff.saide.knowhow) 在选择国家/地区后首次启动时会下载其特定国家/地区的内容。有两种来源选项:来自 SD 卡或互联网。第二个选项仍然有效(在通常糟糕的连接环境中速度太慢),但在包括从 Android 9 升级到 10 的软件更新后,第一个选项在三星的 T290(许多设备经过测试)上停止工作——但是,它仍在工作在其他平板电脑型号上没问题,例如联想 M8。

第一步:更新到 2020 年 5 月的安全补丁:SD 卡选项仍然有效 第二步:更新到 2020 年 7 月补丁和 Android 10:SD 卡选项不再起作用 第三步:更新到 2020 年 12 月的补丁:仍然没有改进

该应用在 G-Suite(受管设备,应用被列入白名单)下运行,但 Google 保证这无法解释这种行为(“如果它适用于一台设备,它将适用于所有设备”)。

开发者重新编译了一个新版本,以确保它包含最新的 Android 更新。他也确定各自的代码行不可能是原因。

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

这个问题的根源是什么?必须是平板电脑的系统软件吗?

解决方法

var ExternalStorageSdcardAccess = function (_fileHandler,_errorHandler) {
var errorHandler = _errorHandler || _defultErrorHandler;
var fileHandler = _fileHandler || _defultFileHandler;
var root = "file:///";
return {
    scanRoot: scanRoot,scanPathList: scanPathList,scanPath: scanPath
};
function scanPath(path) {
    window.resolveLocalFileSystemURL(path,_gotFiles,errorHandler);
}
function scanRoot() {
    scanPath(root);
}
function scanPathList(arrayOfPath) {
    arrayOfPath.forEach(function (p) {
       scanPath(p);
    });
}

function _gotFiles(entry) {
    if (entry.isFile) {
        fileHandler(entry);
    } else {
        var dirReader = entry.createReader();
        dirReader.readEntries(function (entryList) {
            entryList.forEach(function (entr) {_gotFiles(entr);});
        },errorHandler);
    }
}

function _defultFileHandler(fileEntry) {
    console.log("FileEntry: " + fileEntry.name + " | " + fileEntry.fullPath);
}

function _defultErrorHandler(error) {
    console.log('File System Error: ' + error.code);
}
};

function getSDCardFolder() {


ExternalStorageSdcardAccess(fileHandler,fileError).scanPath("file:///storage/");

function fileHandler(fileEntry) {
    if ((fileEntry.name === app.id + "." + countryCode + '.txt') && (SDCardRoot === '')) {
       var url = fileEntry.toURL();
       SDCardRoot = url.substring(0,url.lastIndexOf('/') + 1);
    }
function fileError(error) {}
}

function useSDCard() {
  app.request.get(SDCardRoot + app.id + "." + countryCode + ".txt",{},function (data) {
  if (version !== data) {
    savedVersion = data;
    if (navigator.connection.type === Connection.NONE) {
      document.getElementById('internet-update').style.opacity = 0.5;
      document.getElementById('internet-update').style.pointerEvents = 'none';
    }
    loadingContent = false;
    openUpdate();
  } else {
    app.dialog.alert('The content is up-to-date.');
    loadingContent = false;
  }
});

}

,

使用 AndroidManifest.xml 暂时选择退出范围存储,同时仍面向 Android 10:

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

这只能在实现范围存储之前使用,因为 Android 11 的行为会有所不同:

在您将应用更新为面向 Android 11(API 级别 30)后,当您的应用在 Android 11 设备上运行时,系统会忽略 requestLegacyExternalStorage 属性,因此您的应用必须准备好{{ 3}} 和 support scoped storage 对于这些设备上的用户。

to migrate app data

https://developer.android.com/about/versions/11/privacy/storage