Android phonegap/cordova文件写入程序和读取器不工作

Android phonegap/cordova文件写入程序和读取器不工作,android,eclipse,cordova,Android,Eclipse,Cordova,我正在用cordova 2.2.0在eclipse上开发一个Android应用程序。它似乎获取了Phonegap的文件API,但无法读取或写入文件 我已经从xcode复制了这个脚本,在那里我已经完成了iOS应用程序,它可以正常工作 以下是我的脚本,通过控制台输出进行跟踪: window.onload = function (){ console.log('1: onload'); document.addEventListener("deviceready", getSettin

我正在用cordova 2.2.0在eclipse上开发一个Android应用程序。它似乎获取了Phonegap的文件API,但无法读取或写入文件

我已经从xcode复制了这个脚本,在那里我已经完成了iOS应用程序,它可以正常工作

以下是我的脚本,通过控制台输出进行跟踪:

window.onload = function (){
    console.log('1: onload');
    document.addEventListener("deviceready", getSettings, false);
}
function getSettings(){
    console.log('2: getSettings()');
    fileSys('settings.txt', 'getContent', null);
    //fileSys('settings.txt', 'replaceContent', 'new settings');
}
function fileSys(fileName, action, data){
    console.log('3: fileSys - '+fileName+' - '+action);
    var directory = (fileName == 'sidur') ? 'appin/sidur':'appin';
    window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, gotFS, fail);
    function gotFS(fileSystem) {
    console.log('4: Got file system, get directory...');
    fileSystem.root.getDirectory(directory, {create: true}, gotDir, fail);
    }
    function gotDir(dirEntry) {
        console.log('5: Got directory. Get file...');
        dirEntry.getFile(fileName, {create: true, exclusive: false}, gotFileEntry, fail);
    }
    function gotFileEntry(fileEntry){
        console.log('6: got file. Perform action: '+action+'...');
        if(action == 'getContent') readAsText(fileEntry);
        if(action == 'replaceContent') fileEntry.createWriter(gotFileWriter, fail);
    }
    function gotFileWriter(writer){
        console.log('7: got file writer...');
        writer.write(data); //function variable of fileSys();
        writer.onwriteend = function(evt) {
        console.log('8: file written');
        };
    }
    function readAsText(file) {
        console.log('7: read as text...');
        var reader = new FileReader();
        reader.readAsText(file);
        reader.onloadend = function(evt) {
            console.log('9: done reading file');
            init(evt.target.result);
        }
    }
    function fail(error){
        console.log('fail: '+error.code);

    }
}
function init(settings){
    console.log('Init. Settings: '+JSON.stringify(settings));
}
运行此脚本将提供以下控制台输出:

  • 1:空载
  • 2:getSettings()
  • 3:fileSys-settings.txt-getContent
  • 4:获取文件系统,获取目录
  • 5:找到了目录。获取文件
  • 6:我拿到文件了。执行操作:getContent
  • 7:以文本形式阅读
然后就停了。从未调用reader.onloadend,也未指定错误。如果我再次运行,而是调用fileSys('settings.txt','replaceContent','newsettings');与对fileSys的另一个调用相比,控制台输出:

  • 1:空载
  • 2:getSettings()
  • 3:fileSys-settings.txt-replaceContent
  • 4:获取文件系统,获取目录
  • 5:找到了目录。获取文件
  • 6:我拿到文件了。执行操作:替换内容
  • 7:有文件写入器
我有:

  • 在res/config.xml和android manifest.xml中设置正确的权限/插件
  • 已验证Phonegap API是否包含并正在使用(带有通知)

我对应用程序开发和eclipse都是新手,所以这很可能是我错过的一些基本东西。欢迎提出任何建议和建议。

好吧,我想出来了。问题在于我的代码结构

这在ios上运行良好:

function readAsText(file) {
    var reader = new FileReader();
    reader.readAsText(file);
    reader.onloadend = function(evt) {
        console.log('9: done reading file');
        init(evt.target.result);
    };
}
但不知何故,Android的phonegap要求您在阅读器的readAsText方法之上为阅读器的onloadend方法声明变量。像这样:

function readAsText(file) {
    var reader = new FileReader();
    reader.onloadend = function(evt) {
        console.log('9: done reading file');
        init(evt.target.result);
    };
    reader.readAsText(file);
}

回想起来,这对我来说非常有意义。看起来很奇怪,iOS允许了另一种方式。

事实上,这不是你陈述的顺序,因为Android和iOS都将以相同的顺序解释它们。不同的是readAsText完成的速度,因为它的工作在另一个线程中异步进行。以下是iOS上发生的一个示例:

reader.readAsText - this starts the read process in another thread
reader.onloadend = function... - you set up your handler
-- on separate thread, readAsText finally completes and sees your handler and calls it
这就是Android上发生的事情:

reader.readAsText - this starts the read process in another thread
-- on separate thread, readAsText completed quickly but your handler has not been set yet so it does not get called
reader.onloadend = function... - you set up your handler too late, the read already completed in its own thread

在异步调用中,您无法保证其他任务何时完成。Android和iOS之间没有区别,这只是多线程操作的本质。有各种各样的方法来处理异步调用(正确地排序和嵌套回调,使用jquerydeferred,某种类型的信号量机制,等等,我确信)。最重要的是,永远不要依赖或假设任务会在一定时间内完成。依赖计时会让你很难调试。

需要以这种方式定义它的原因是,在设置onloadend侦听器之前,你的读取已经成功。是的,这非常有意义。但奇怪的是,它在iOS中的工作方式正好相反。所以我猜这都是关于每个浏览器解释代码和定义变量的顺序。