【问题标题】:How to access external storage with cordova file / file-system-roots plugins?如何使用cordova文件/文件系统根插件访问外部存储?
【发布时间】:2014-04-04 16:24:25
【问题描述】:

问题描述: 我可以使用文件或文件系统根(读写)访问内部存储。但是这样的文件不能从其他应用程序访问。例如,如果我想通过 emailComposerPlugin 发送此文件,则电子邮件客户端无法访问该文件。 (“打开方式”功能也是如此。) 如果我将选项 {sandboxed: true} 更改为 false(写入外部存储),它不起作用并最终出现 FileUtils.UNKNOWN_ERR。我在手机与 USB 断开连接时尝试了该应用程序,因为一些文档提到在安装在 pc 上时无法访问外部存储 - 但结果相同。

根据我在mailing list 上读到的内容,这应该是可能的。看来我错过了一个关键点?

背景: 我尝试让为 iPhone 创建的混合应用程序在 android 设备上运行。为了有一个小操场,我创建了一个小型测试项目。

编辑: 文件系统根目录和文件插件之间似乎存在问题。但我有他们两个的最新版本。 (文件:1.0.1 文件系统根目录:0.1.0) 调试文件系统和文件类表明

private String fullPathForLocalURL(Uri URL) {
    if (FILESYSTEM_PROTOCOL.equals(URL.getScheme()) && "localhost".equals(URL.getHost())) {
        String path = URL.getPath();
        if (URL.getQuery() != null) {
            path = path + "?" + URL.getQuery();
        }
        return path.substring(path.indexOf('/', 1));
        // path = "/cache-external" at this point
        // results in index out of bounds exception

我尝试了什么?

config.xml

<preference name="AndroidExtraFilesystems" value="files,files-external,documents,sdcard,cache,cache-external" />

AndroidManifest.xml

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

javascript 代码

function createTextDocument(filename, text) {

    cordova.filesystem.getDirectoryForPurpose('cache', {sandboxed: false}, successCallback, failureCallback);

    function successCallback(directoryEntry){
        console.log('directory found (cordova): ' + directoryEntry.toURL());
        console.log('directory found (native) : ' + directoryEntry.toNativeURL());
        directoryEntry.getFile(filename, {create: true, exclusive: false},
            function(fileEntry){
                var filePath = fileEntry.toNativeURL();
                fileEntry.createWriter(
                    function(fileWriter){
                        console.log('start writing to: ' + filePath );
                        fileWriter.write(text);
                        console.log('file written');
                    },failureCallback
                );
            }, failureCallback
        );
    }

    function failureCallback(error){
        console.log('error creating file: ' + error.code);
        // results in code 1000
    }
}

【问题讨论】:

    标签: android cordova file-io


    【解决方案1】:

    在深入研究了整个主题之后,我想通了:

    • 不需要文件系统根插件。
    • config.xml 中需要更多配置。
    • 您需要使用的不是标准的 FileApi 方式,而是以下方式来访问文件。

    JavaScript 用法:

    window.resolveLocalFileSystemURL(path, cbSuccess, cbFail);
    
    @param path: {string} a cordova path with scheme: 
                 'cdvfile://localhost/<file-system-name>/<path-to-file>' 
                 Examples: 'cdvfile://localhost/sdcard/path/to/global/file'
                           'cdvfile://localhost/cache/onlyVisibleToTheApp.txt'
    @param cbSuccess: {function} a callback method that receives a DirectoryEntry object.
    @param cbFail: {function} a callback method that receives a FileError object.
    

    config.xml

    <preference name="AndroidPersistentFileLocation" value="Compatibility" />
    <preference name="AndroidExtraFilesystems" value="sdcard,cache" />
    

    AndroidManifest.xml

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

    【讨论】:

    • 你能提供一个将新文件写入外部SD卡的完整工作示例吗?
    • 我最终使用了这个代码:window.resolveLocalFileSystemURL('file:///storage/extSdCard/', function (fs){ var nativePath = fs.toURL(); alert(nativePath);}, function(err){alert(err);});
    • 不确定我的问题有多相似。但是让 AndroidPersistentFileLocation 兼容解决了 Android 的 cordova v5+ 文件系统的问题
    【解决方案2】:

    经过数小时的努力,我终于可以通过提供“files://pathtofile/”之类的目录来扫描 sdcard 并访问文件。
    我已经提交了一个 API 和一个示例项目 https://github.com/xjxxjx1017/cordova-phonegap-android-sdcard-full-external-storage-access-library

    API 使用示例

    new ExternalStorageSdcardAccess( fileHandler ).scanPath( "file:///storage/sdcard1/music" );
    function fileHandler( fileEntry ) {
        console.log( fileEntry.name + " | " + fileEntry.toURL() );
    }
    

    API 源代码

    var ExternalStorageSdcardAccess = function ( _fileHandler, _errorHandler ) {
    
        var errorHandler = _errorHandler || _defultErrorHandler;
        var fileHandler = _fileHandler || _defultFileHandler;
        var root = "file:///";
    
        return {
            scanRoot:scanRoot,
            scanPath:scanPath
        };
    
        function scanPath( path ) {
            window.resolveLocalFileSystemURL(path, _gotFiles, errorHandler );
        }
    
        function scanRoot() {
            scanPath( root );
        }
    
    function _gotFiles(entry) {
        // ? Check whether the entry is a file or a directory
        if (entry.isFile) {
            // * Handle file
            fileHandler( entry );
        }
        else {
            // * Scan directory and add media
            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 );
        }
    };
    

    配置

    • config.xml
      删除首选项:首选项名称="AndroidExtraFilesystems"

    • 确保测试环境在测试时可以访问它自己的外部存储。 (e.p.如果你用usb连接它,请确保它作为相机连接;在收到“deviceready”事件后调用API)

    路径示例:
    文件:///
    文件:///某个文件/
    文件:///一些文件
    文件:///somefile/music/aaaaa.mp3

    【讨论】:

    • 我将为 mp3 生成的 url 提交给了 cordova-plugin-media 实例。插件没有播放。文件的实际 URI 有区别吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-10
    • 2016-07-27
    • 2012-11-04
    • 1970-01-01
    • 2011-09-25
    • 1970-01-01
    相关资源
    最近更新 更多