Cordova文件插件 - 将文件保存在设备中

dav*_*ani 2 android cordova cordova-plugins ngcordova cordova-plugin-file

我在Android中保存文件时遇到了很多麻烦.
该项目是使用Ionic与这些插件一起开发的混合应用程序:

com.phonegap.plugins.fileopener 1.0.0 "File Opener"
com.telerik.plugins.nativepagetransitions 0.4.2 "Native Page Transitions"
cordova-plugin-compat 1.0.0 "Compat"
cordova-plugin-crosswalk-webview 2.0.0 "Crosswalk WebView Engine"
cordova-plugin-file 4.2.0 "File"
cordova-plugin-network-information 1.2.2-dev "Network Information"
cordova-plugin-whitelist 1.2.3-dev "Whitelist"
cordova-plugin-wkwebview-engine 1.0.4-dev "Cordova WKWebView Engine"
ionic-plugin-keyboard 2.2.1 "Keyboard"
Run Code Online (Sandbox Code Playgroud)

Android平台版本是5.2.1
我正在使用的设备Samsung A7

这是摘要 AndroidManifest.xml

<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="23" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<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" />
Run Code Online (Sandbox Code Playgroud)

情况1

如果我尝试使用此片段(实际上正在处理另一个项目)

var storagePath = "/storage/emulated/0";
var fileDir = cordova.file.externalDataDirectory.replace(cordova.file.externalRootDirectory, '');
var fileName = $scope.ngDocument.documentId + ".pdf"
var filePath = storagePath + "/" + fileDir + fileName;
$cordovaFile.writeFile(filePath, BINARY_ARR, {'append': false}).then(function(result) {}, function(err) {});
Run Code Online (Sandbox Code Playgroud)

无论是否使用绝对路径,相对路径,只是文件名并且没有创建任何文件,我都会从中获取{"code":5,"message":"ENCODING_ERR"}Callback $cordovaFile.writeFile.

案例2

有了这个片段

window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function (fs) {
  console.log('file system open: ' + fs.name);
  fs.root.getFile(fileName, { create: true, exclusive: false }, function (fileEntry) {
    console.log("fileEntry:" + JSON.stringify(fileEntry));
    writeFile(fileEntry, BINARY_ARR);
  }, function(data){});
}, function(data){});
Run Code Online (Sandbox Code Playgroud)

发生两件事

案例2.1

如果应用中未指定配置选项,则在config.xml/ storage/emulated/0/Android/media/{myAPP}中创建一个空文件夹

案例2.2

有这两个偏好

<preference name="AndroidPersistentFileLocation" value="Compatibility" />
<preference name="AndroidExtraFilesystems" value="cache" />
Run Code Online (Sandbox Code Playgroud)

/storage/emulated/0创建(外部SSD)中的文件,其中logcat包含以下错误:

E/Vold    ( 2280): Failed to find mounted volume for /storage/extSdCard/Android/data/{myApp}/files/
W/Vold    ( 2280): Returning OperationFailed - no handler for errno 0
W/ContextImpl(13364): Failed to ensure directory: /storage/extSdCard/Android/data/{myApp}/files
E/Vold    ( 2280): Failed to find mounted volume for /storage/extSdCard/Android/data/{myApp}/files/
W/Vold    ( 2280): Returning OperationFailed - no handler for errno 0
W/ContextImpl(13364): Failed to ensure directory: /storage/extSdCard/Android/data/{myApp}/files
E/Vold    ( 2280): Failed to find mounted volume for /storage/extSdCard/Android/data/{myApp}/cache/
W/Vold    ( 2280): Returning OperationFailed - no handler for errno 0
W/ContextImpl(13364): Failed to ensure directory: /storage/extSdCard/Android/data/{myApp}/cache
Run Code Online (Sandbox Code Playgroud)

奇怪的是,/storage/extSdCard/mnt/extSdCard安装外部SSD时未安装(符号链接)/mnt/sdcard

请帮帮忙:我是个棒球.
第一个片段在另一个项目中作为魅力.它可能是ngCordova的版本吗?

dav*_*ani 11

解决了:

经过几次尝试,我以这种方式解决了

config.xml:

<preference name="AndroidPersistentFileLocation" value="Compatibility" />
<preference name="AndroidExtraFilesystems" value="files,cache, sdcard, cache-external, files-external" />
Run Code Online (Sandbox Code Playgroud)

主要功能:

window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function (fs) {

    //var absPath = "file:///storage/emulated/0/";
    var absPath = cordova.file.externalRootDirectory;
    var fileDir = cordova.file.externalDataDirectory.replace(cordova.file.externalRootDirectory, '');
    var fileName = "somename.txt";
    var filePath = fileDir + fileName;

    fs.root.getFile(filePath, { create: true, exclusive: false }, function (fileEntry) {
        writeFile(fileEntry, BINARY_ARR).then(function(){
          //do something here
        });
    }, function(err) {});
}, function(err) {});

function writeFile(fileEntry, dataObj) {
    return $q(function (resolve, reject) {
        fileEntry.createWriter(function (fileWriter) {
            fileWriter.onwriteend = function () {
                resolve();
            };
            fileWriter.onerror = function (e) {
                reject(e);
            };
            fileWriter.write(dataObj);
        });
    });
}
Run Code Online (Sandbox Code Playgroud)

它似乎:

<preference name="AndroidPersistentFileLocation" value="Internal" />
Run Code Online (Sandbox Code Playgroud)

这是默认配置中,不能让该应用写入外部磁盘(无论是物理的或模拟的).相反,只允许应用程序写入/data/data/{myApp}/files