如何使像正常的浏览器文件API的PhoneGap的(科尔多瓦)文件API工作 [英] How to make Phonegap's (Cordova) File API work like File API in normal browser

查看:238
本文介绍了如何使像正常的浏览器文件API的PhoneGap的(科尔多瓦)文件API工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有一种方法,使的PhoneGap的文件API的工作就像在浏览器中相同的API的作品?
我需要相同的行为在浏览器:点击打开文件按钮 - >选择文件对话框 - > - >打开文件,对象的FileReader

感谢您!

更新:我已经找到了一些解决方案。它打开文件对话框,并返回JS文件对象的名称。但是,当我通过从PhoneGap的JS文件对象的FileReader - 它不会打开(onload事件监听器永远不会触发)。我该怎么办了?

下面是我的Java:

 包org.apache.cordova.example;进口android.os.Bundle;
进口org.apache.cordova.api.CordovaInterface;
进口android.content.Intent;
进口android.net.Uri;
进口android.webkit.ValueCallback;
进口org.apache.cordova.CordovaChromeClient;
进口org.apache.cordova.CordovaWebView;
进口org.apache.cordova.DroidGap;
公共类cordovaExample扩展DroidGap
{
私人ValueCallback<&乌里GT; mUploadMessage;
私人最终静态INT FILECHOOSER_RESULT code = 1;@覆盖
公共无效的onCreate(捆绑savedInstanceState)
{
    super.onCreate(savedInstanceState);
    super.loadUrl(文件:///android_asset/www/index.html);    this.appView.setWebChromeClient(新FileAttachmentChromeClient(这一点,this.appView));
}@覆盖
保护无效的onActivityResult(INT申请code,INT结果code,意图意图){
    如果(要求code == FILECHOOSER_RESULT code){
        如果(空== mUploadMessage)回报;
        乌里结果=意图== NULL ||结果code!= RESULT_OK?空:intent.getData();
        mUploadMessage.onReceiveValue(结果);
        mUploadMessage = NULL;
    }
}// openFileChooser是WebChromeClient可重写的方法,这是不
//包含在SDK的Andr​​oid存根code
公共类FileAttachmentChromeClient扩展CordovaChromeClient {    公共FileAttachmentChromeClient(CordovaInterface CTX,CordovaWebView应用程序){
        超(CTX,应用);    }
    公共无效openFileChooser(ValueCallback<&乌里GT; uploadMsg){
        mUploadMessage = uploadMsg;
        意图I =新意图(Intent.ACTION_GET_CONTENT);
        i.addCategory(Intent.CATEGORY_OPENABLE);
        i.setType(* / *);
        cordovaExample.this.startActivityForResult(Intent.createChooser(我,选择附件类型),FILECHOOSER_RESULT code);
    }}
}

和我做什么用JavaScript:

  VAR SelectedFile;
 VAR FReader; 。的document.getElementById('文件框中')的addEventListener('变化',fileChosen);
 功能fileChosen(EVNT){
SelectedFile = evnt.target.files [0];
     FReader =新的FileReader();
     FReader.readAsDataURL(SelectedFile);
     FReader.onload =功能(loadevnt){...} //不会发生
}


解决方案

那么问题是大多数移动浏览器不支持的文件对话框。 IIRC的iOS 6是第一个手机浏览器支持此功能。我没有写在我的科林斯项目的一些code,不是正在积极开发,但这猴子这个补丁功能。

首先你需要写一个Android插件启动一个意图提供文件对话框。我使用OI文件管理器。

 包org.apache.cordova;进口org.apache.cordova.api.CallbackContext;
进口org.apache.cordova.api.CordovaPlugin;
进口org.apache.cordova.api.LOG;
进口org.apache.cordova.api.PluginResult;
进口org.json.JSONArray;
进口org.json.JSONException;
进口org.json.JSONObject;进口的java.util.HashMap;/ **
 *此类公开在DroidGap方法,可以从JavaScript调用。
 * /
公共类应用扩展CordovaPlugin {    / **
     *执行该请求并返回PluginResult。
     *
     * @参数动作的动作来执行。
     *为插件参数@param ARGS JSONArry。
     * @参数callbackContext从中我们调用的回调上下文。
     * @返回一个PluginResult用状态和消息对象。
     * /
    公共布尔执行(串动,JSONArray ARGS,CallbackContext callbackContext)抛出JSONException {
        PluginResult.Status状态= PluginResult.Status.OK;
        字符串结果=;        尝试{
            如果(action.equals(clearCache)){
                this.clearCache();
            }
            否则,如果(action.equals(秀)){
                //这个被从JavaScript onCordovaReady称为显示网页视图。
                //我建议我们更改消息的名称微调/停止不
                //表示这是什么实际上做(显示web视图)。
                cordova.getActivity()。runOnUiThread(新的Runnable(){
                    公共无效的run(){
                        webView.postMessage(微调,停止);
                    }
                });
            }
            否则如果(action.equals(使用loadURL)){
                this.loadUrl(args.getString(0),args.optJSONObject(1));
            }
            否则如果(action.equals(cancelLoadUrl)){
                this.cancelLoadUrl();
            }
            否则如果(action.equals(clearHistory)){
                this.clearHistory();
            }
            否则如果(action.equals(backHistory)){
                this.backHistory();
            }
            否则如果(action.equals(overrideButton)){
                this.overrideButton(args.getString(0),args.getBoolean(1));
            }
            否则如果(action.equals(overrideBackbutton)){
                this.overrideBackbutton(args.getBoolean(0));
            }
            否则如果(action.equals(ExitApp命令)){
                this.exitApp();
            }
            callbackContext.sendPluginResult(新PluginResult(状态,结果));
            返回true;
        }赶上(JSONException E){
            callbackContext.sendPluginResult(新PluginResult(PluginResult.Status.JSON_EXCEPTION));
            返回false;
        }
    }    // ------------------------------------------------ --------------------------
    //本地方法
    // ------------------------------------------------ --------------------------    / **
     *清除资源缓存。
     * /
    公共无效clearCache(){
        this.webView.clearCache(真);
    }    / **
     *加载网址进入web视图。
     *
     * @参数网址
     * @参数道具,可以在传递给DroidGap活动属性(即loadingDialog,等...)
     * @throws JSONException
     * /
    公共无效使用loadURL(字符串URL,JSONObject的道具)抛出JSONException {
        LOG.d(应用程序,App.loadUrl(+ URL +,+道具+));
        INT等待= 0;
        布尔openExternal = FALSE;
        布尔clearHistory = FALSE;        //如果有属性,然后设置它们的活动
        HashMap的<弦乐,对象> PARAMS =新的HashMap<弦乐,对象>();
        如果(道具!= NULL){
            JSONArray键= props.names();
            的for(int i = 0; I< keys.length();我++){
                字符串键= keys.getString(I)
                如果(key.equals(等待)){
                    等待= props.getInt(键);
                }
                否则如果(key.equalsIgnoreCase(openexternal)){
                    openExternal = props.getBoolean(键);
                }
                否则如果(key.equalsIgnoreCase(clearhistory)){
                    clearHistory = props.getBoolean(键);
                }
                其他{
                    对象值= props.get(键);
                    如果(价值== NULL){                    }
                    否则如果(value.getClass()。等于(为String.class)){
                        params.put(键,(串)值);
                    }
                    否则如果(value.getClass()。等于(Boolean.class)){
                        params.put(键,(布尔)值);
                    }
                    否则如果(value.getClass()。等于(Integer.class)){
                        params.put(键,(整数)值);
                    }
                }
            }
        }        //如果等待的属性,那么延迟加载        如果(等待大于0){
            尝试{
                同步(本){
                    this.wait(等待);
                }
            }赶上(InterruptedException的E){
                e.printStackTrace();
            }
        }
        this.webView.showWebPage(URL,openExternal,clearHistory,则params);
    }    / **
     *已经载入前取消使用loadURL(仅适用于一类CordovaInterface)
     * /
    @德precated
    公共无效cancelLoadUrl(){
        this.cordova.cancelLoadUrl();
    }    / **
     *清除网页历史记录应用程序。
     * /
    公共无效clearHistory(){
        this.webView.clearHistory();
    }    / **
     *转到显示previous页面。
     *这是一样的pressing Android设备上的后退按钮。
     * /
    公共无效backHistory(){
        cordova.getActivity()。runOnUiThread(新的Runnable(){
            公共无效的run(){
                webView.backHistory();
            }
        });
    }    / **
     *覆盖了Android后退按钮的默认行为。
     *如果重写,当后退按钮是pressed的backKeyDownJavaScript事件将被解雇。
     *
     * @参数覆盖T =覆盖,F =取消忽略
     * /
    公共无效overrideBackbutton(布尔覆盖){
        LOG.i(应用程序,警告:!后退按钮默认的行为将被覆盖的后退按钮事件将被解雇);
        webView.bindButton(覆盖);
    }    / **
     *覆盖了Android音量按钮的默认行为。
     *如果重写,当音量按钮是pressed,音量[上一页|下一页]按钮JavaScript事件将被解雇。
     *
     * @参数按钮volumeup,volumedown
     * @参数覆盖T =覆盖,F =取消忽略
     * /
    公共无效overrideButton(字符串键,布尔覆盖){
        LOG.i(DroidGap,警告:!音量按钮默认的行为将被覆盖音量事件将被解雇);
        webView.bindButton(按钮,覆盖);
    }    / **
     *返回的Andr​​oid后退按钮是否被用户覆盖。
     *
     * @返回布尔
     * /
    公共布尔isBackbuttonOverridden(){
        返回webView.isBackButtonBound();
    }    / **
     *退出Android应用程序。
     * /
    公共无效ExitApp命令(){
        this.webView.postMessage(退出,NULL);
    }}包com.simonmacdonald.corinthian;进口org.apache.cordova.api.Plugin;
进口org.apache.cordova.api.PluginResult;
进口org.json.JSONArray;
进口org.json.JSONObject;进口android.app.Activity;
进口android.app.AlertDialog;
进口android.content.ActivityNotFoundException;
进口android.content.Context;
进口android.content.DialogInterface;
进口android.content.Intent;
进口android.net.Uri;
进口android.util.Log;公共类FileDialog的扩展插件{
    私有静态最终诠释PICK_FILE_RESULT_ code = 8974;
    私有静态最终诠释PICK_DIRECTORY_RESULT_ code = 8975;
    私有静态最后弦乐LOG_TAG =FileDialog的;
    公共字符串callbackId;    / **
     *执行该请求并返回PluginResult。
     *
     * @参数动作的动作来执行。
     *为插件参数@param ARGS JSONArry。
     * @参数callbackId回调成JavaScript时使用的回调ID。
     * @返回一个PluginResult用状态和消息对象。
     * /
    @覆盖
    公共PluginResult执行(串动,JSONArray ARGS,弦乐callbackId){
        this.callbackId = callbackId;        JSONObject的选项= args.optJSONObject(0);        如果(action.equals(pickFile)){
            的ShowDialog(选项,PICK_FILE_RESULT_ code);
        }否则如果(action.equals(pickFolder)){
            的ShowDialog(选项,PICK_DIRECTORY_RESULT_ code);
        }
        其他{
            返回新PluginResult(PluginResult.Status.INVALID_ACTION);
        }
        PluginResult R =新PluginResult(PluginResult.Status.NO_RESULT);
        r.setKeepCallback(真);
        返回ř;
    }    私人无效的ShowDialog(JSONObject的选项,整型){
        意图意图;
        如果(类型== PICK_FILE_RESULT_ code){
            意图=新意图(org.openintents.action.PICK_FILE);
        }其他{
            意图=新意图(org.openintents.action.PICK_DIRECTORY);
        }
        如果(选项!= NULL){
            字符串title = options.optString(标题);
            如果(标题!= NULL){
                intent.putExtra(org.openintents.extra.TITLE称号);
            }
            弦钮= options.optString(按钮);
            如果(按钮!= NULL){
                intent.putExtra(org.openintents.extra.BUTTON_TEXT按钮);
            }
        }
        //intent.setData(Uri.fromFile(new文件(/)));
        尝试{
            this.cordova.startActivityForResult((插件)这一点,意图,PICK_FILE_RESULT_ code);
        }赶上(ActivityNotFoundException E){
            showDownloadDialog();
        }
    }    私人无效showDownloadDialog(){
        最后上下文的背景下= this.cordova.getContext();
        可运行可运行=新的Runnable(){
            公共无效的run(){                AlertDialog.Builder对话框=新AlertDialog.Builder(背景);
                dialog.setTitle(安装文件管理器?);
                dialog.setMessage(这就要求免费OI文件管理器应用程序是否要立即安装它?);
                dialog.setPositiveButton(是,新DialogInterface.OnClickListener(){
                    公共无效的onClick(DLG DialogInterface,int i)以{
                        dlg.dismiss();
                        意向意图=新意图(Intent.ACTION_VIEW,
                            Uri.parse(市场://搜Q = PNAME:org.openintents.filemanager)
                        );
                        尝试{
                            context.startActivity(意向);
                        }赶上(ActivityNotFoundException E){
//我们没有安装的应用程序市场,所以直接下载。
                            在意向=新意图(Intent.ACTION_VIEW);
                            in.setData(Uri.parse(HTTP://openintents.google$c$c.com/files/FileManager-1.2.apk));
                            context.startActivity(在);                        }                    }
                });
                dialog.setNegativeButton(否,新DialogInterface.OnClickListener(){
                    公共无效的onClick(DLG DialogInterface,int i)以{
                        dlg.dismiss();
                    }
                });
                dialog.create();
                dialog.show();
            }
        };
        。this.cordova.getActivity()runOnUiThread(可运行);
    }    @覆盖
    公共无效的onActivityResult(INT REQ code,INT结果code,意图数据){
      //super.onActivityResult(req$c$c,结果code,数据);
      //Log.d(LOG_TAG,数据为+ data.getData()的toString())。
      Log.d(LOG_TAG,我们在活动的结果);
      开关(REQ code){
      案例PICK_FILE_RESULT_ code:
      案例PICK_DIRECTORY_RESULT_ code:{
          如果(结果code == Activity.RESULT_OK&放大器;&放大器;数据= NULL&放大器;!&安培;!data.getData()= NULL){
              。字符串文件路径=文件://+ data.getData()的getPath();
              Log.d(LOG_TAG,数据是=+文件路径);
              Log.d(+ this.callbackId LOG_TAG,有回调ID =主叫更迭);
              this.success(新PluginResult(PluginResult.Status.OK,文件路径),this.callbackId);
          }
          打破;
      }
  }
    }
}

然后,你需要写你的JavaScript接口:

  FileDialog的:{
    pickFile:功能(successCallback,errorCallback,期权){
        VAR赢= typeof运算suc​​cessCallback!==功能?空:函数(f){
            window.resolveLocalFileSystemURI(F,函数(FileEntry的){
                successCallback(FileEntry的);
            },失败);
        };
        cordova.exec(赢,errorCallback,FileDialog的,pickFile,[选项]);
    },
    pickFolder:功能(successCallback,errorCallback,期权){
        VAR赢= typeof运算suc​​cessCallback!==功能?空:功能(D){
            window.resolveLocalFileSystemURI(D,功能(dirEntry){
                successCallback(dirEntry);
            },失败);
        };
        cordova.exec(赢,errorCallback,FileDialog的,pickFolder,[选项]);
    },
    补丁:功能(){
        VAR输入= document.getElementsByTagName(输入);
        对于(VAR I = 0; I< inputs.length;我++){
           如果(输入[I] .getAttribute('类型')=='文件'){
               VAR我=输入[I]
               输入[I]阅读进度(点击,函数(){
                   corinthian.FileDialog.pickFile(功能(FileEntry的){
                       me.value = fileEntry.fullPath;
                   });
               });
           }
        }
    }
}

和调用FileDialog.patch()终于猴补丁;一旦你已经收到了deviceready事件PhoneGap的。

希望这有助于...

Is there a way to make Phonegap's File API work just like same API works in browser? I need same behavior as in browser: Tap on "Open file" button -> "Select File" dialog ->... -> Opening the file with FileReader Object.

Thank you!!!

UPDATE: I've found some solution. It opens File Dialog and it returns the name of the JS File Object. But when i pass that JS File Object to FileReader from PhoneGap - it doesn't open (onload listener never fires). What i do wrong?

Here's my Java:

package org.apache.cordova.example;

import android.os.Bundle;
import org.apache.cordova.api.CordovaInterface;
import android.content.Intent;
import android.net.Uri;
import android.webkit.ValueCallback;
import org.apache.cordova.CordovaChromeClient;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.DroidGap;


public class cordovaExample extends DroidGap
{
private ValueCallback<Uri> mUploadMessage;
private final static int FILECHOOSER_RESULTCODE = 1;

@Override
public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    super.loadUrl("file:///android_asset/www/index.html");

    this.appView.setWebChromeClient(new FileAttachmentChromeClient(this,     this.appView));
}



@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
    if (requestCode == FILECHOOSER_RESULTCODE) {
        if (null == mUploadMessage) return;
        Uri result = intent == null || resultCode != RESULT_OK ? null : intent.getData();
        mUploadMessage.onReceiveValue(result);
        mUploadMessage = null;
    }
}

// openFileChooser is an overridable method in WebChromeClient which isn't
// included in the SDK's Android stub code
public class FileAttachmentChromeClient extends CordovaChromeClient {

    public FileAttachmentChromeClient(CordovaInterface ctx, CordovaWebView app) {
        super(ctx, app);

    }
    public void openFileChooser(ValueCallback<Uri> uploadMsg) {
        mUploadMessage = uploadMsg;
        Intent i = new Intent(Intent.ACTION_GET_CONTENT);
        i.addCategory(Intent.CATEGORY_OPENABLE);
        i.setType("*/*");
        cordovaExample.this.startActivityForResult(Intent.createChooser(i, "Choose type of attachment"), FILECHOOSER_RESULTCODE);
    }

}
}

And what i do with JavaScript:

 var SelectedFile;
 var FReader; 

 document.getElementById('fileBox').addEventListener('change', fileChosen);     


 function fileChosen(evnt) {
SelectedFile = evnt.target.files[0];      
     FReader = new FileReader(); 
     FReader.readAsDataURL(SelectedFile);
     FReader.onload = function(loadevnt){   ....   }  //never happens
}

解决方案

Well the problem is most mobile browsers do not support the file dialog. IIRC iOS 6 is the first mobile browser to support this functionality. I did write some code in my Corinthian project, not under active development, that does monkey patch this functionality.

First you'd need to write an Android plugin to start an intent to provide the file dialog. I'm using OI File Manager.

package org.apache.cordova;

import org.apache.cordova.api.CallbackContext;
import org.apache.cordova.api.CordovaPlugin;
import org.apache.cordova.api.LOG;
import org.apache.cordova.api.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.HashMap;

/**
 * This class exposes methods in DroidGap that can be called from JavaScript.
 */
public class App extends CordovaPlugin {

    /**
     * Executes the request and returns PluginResult.
     *
     * @param action            The action to execute.
     * @param args              JSONArry of arguments for the plugin.
     * @param callbackContext   The callback context from which we were invoked.
     * @return                  A PluginResult object with a status and message.
     */
    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
        PluginResult.Status status = PluginResult.Status.OK;
        String result = "";

        try {
            if (action.equals("clearCache")) {
                this.clearCache();
            }
            else if (action.equals("show")) {
                // This gets called from JavaScript onCordovaReady to show the webview.
                // I recommend we change the name of the Message as spinner/stop is not
                // indicative of what this actually does (shows the webview).
                cordova.getActivity().runOnUiThread(new Runnable() {
                    public void run() {
                        webView.postMessage("spinner", "stop");
                    }
                });
            }
            else if (action.equals("loadUrl")) {
                this.loadUrl(args.getString(0), args.optJSONObject(1));
            }
            else if (action.equals("cancelLoadUrl")) {
                this.cancelLoadUrl();
            }
            else if (action.equals("clearHistory")) {
                this.clearHistory();
            }
            else if (action.equals("backHistory")) {
                this.backHistory();
            }
            else if (action.equals("overrideButton")) {
                this.overrideButton(args.getString(0), args.getBoolean(1));
            }
            else if (action.equals("overrideBackbutton")) {
                this.overrideBackbutton(args.getBoolean(0));
            }
            else if (action.equals("exitApp")) {
                this.exitApp();
            }
            callbackContext.sendPluginResult(new PluginResult(status, result));
            return true;
        } catch (JSONException e) {
            callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
            return false;
        }
    }

    //--------------------------------------------------------------------------
    // LOCAL METHODS
    //--------------------------------------------------------------------------

    /**
     * Clear the resource cache.
     */
    public void clearCache() {
        this.webView.clearCache(true);
    }

    /**
     * Load the url into the webview.
     *
     * @param url
     * @param props         Properties that can be passed in to the DroidGap activity (i.e. loadingDialog, wait, ...)
     * @throws JSONException
     */
    public void loadUrl(String url, JSONObject props) throws JSONException {
        LOG.d("App", "App.loadUrl("+url+","+props+")");
        int wait = 0;
        boolean openExternal = false;
        boolean clearHistory = false;

        // If there are properties, then set them on the Activity
        HashMap<String, Object> params = new HashMap<String, Object>();
        if (props != null) {
            JSONArray keys = props.names();
            for (int i = 0; i < keys.length(); i++) {
                String key = keys.getString(i);
                if (key.equals("wait")) {
                    wait = props.getInt(key);
                }
                else if (key.equalsIgnoreCase("openexternal")) {
                    openExternal = props.getBoolean(key);
                }
                else if (key.equalsIgnoreCase("clearhistory")) {
                    clearHistory = props.getBoolean(key);
                }
                else {
                    Object value = props.get(key);
                    if (value == null) {

                    }
                    else if (value.getClass().equals(String.class)) {
                        params.put(key, (String)value);
                    }
                    else if (value.getClass().equals(Boolean.class)) {
                        params.put(key, (Boolean)value);
                    }
                    else if (value.getClass().equals(Integer.class)) {
                        params.put(key, (Integer)value);
                    }
                }
            }
        }

        // If wait property, then delay loading

        if (wait > 0) {
            try {
                synchronized(this) {
                    this.wait(wait);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.webView.showWebPage(url, openExternal, clearHistory, params);
    }

    /**
     * Cancel loadUrl before it has been loaded (Only works on a CordovaInterface class)
     */
    @Deprecated
    public void cancelLoadUrl() {
        this.cordova.cancelLoadUrl();
    }

    /**
     * Clear page history for the app.
     */
    public void clearHistory() {
        this.webView.clearHistory();
    }

    /**
     * Go to previous page displayed.
     * This is the same as pressing the backbutton on Android device.
     */
    public void backHistory() {
        cordova.getActivity().runOnUiThread(new Runnable() {
            public void run() {
                webView.backHistory();
            }
        });
    }

    /**
     * Override the default behavior of the Android back button.
     * If overridden, when the back button is pressed, the "backKeyDown" JavaScript event will be fired.
     *
     * @param override      T=override, F=cancel override
     */
    public void overrideBackbutton(boolean override) {
        LOG.i("App", "WARNING: Back Button Default Behaviour will be overridden.  The backbutton event will be fired!");
        webView.bindButton(override);
    }

    /**
     * Override the default behavior of the Android volume buttons.
     * If overridden, when the volume button is pressed, the "volume[up|down]button" JavaScript event will be fired.
     *
     * @param button        volumeup, volumedown
     * @param override      T=override, F=cancel override
     */
    public void overrideButton(String button, boolean override) {
        LOG.i("DroidGap", "WARNING: Volume Button Default Behaviour will be overridden.  The volume event will be fired!");
        webView.bindButton(button, override);
    }

    /**
     * Return whether the Android back button is overridden by the user.
     *
     * @return boolean
     */
    public boolean isBackbuttonOverridden() {
        return webView.isBackButtonBound();
    }

    /**
     * Exit the Android application.
     */
    public void exitApp() {
        this.webView.postMessage("exit", null);
    }

}

package com.simonmacdonald.corinthian;

import org.apache.cordova.api.Plugin;
import org.apache.cordova.api.PluginResult;
import org.json.JSONArray;
import org.json.JSONObject;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.util.Log;

public class FileDialog extends Plugin {
    private static final int PICK_FILE_RESULT_CODE = 8974;
    private static final int PICK_DIRECTORY_RESULT_CODE = 8975;
    private static final String LOG_TAG = "FileDialog";
    public String callbackId;

    /**
     * Executes the request and returns PluginResult.
     *
     * @param action        The action to execute.
     * @param args          JSONArry of arguments for the plugin.
     * @param callbackId    The callback id used when calling back into JavaScript.
     * @return              A PluginResult object with a status and message.
     */
    @Override
    public PluginResult execute(String action, JSONArray args, String callbackId) {
        this.callbackId = callbackId;

        JSONObject options = args.optJSONObject(0);

        if (action.equals("pickFile")) {
            showDialog(options, PICK_FILE_RESULT_CODE);
        } else if (action.equals("pickFolder")) {
            showDialog(options, PICK_DIRECTORY_RESULT_CODE);
        }
        else {
            return new PluginResult(PluginResult.Status.INVALID_ACTION);
        }
        PluginResult r = new PluginResult(PluginResult.Status.NO_RESULT);
        r.setKeepCallback(true);
        return r;
    }

    private void showDialog(JSONObject options, int type) {
        Intent intent;
        if (type == PICK_FILE_RESULT_CODE) {
            intent = new Intent("org.openintents.action.PICK_FILE");
        } else {
            intent = new Intent("org.openintents.action.PICK_DIRECTORY");
        }
        if (options != null) {
            String title = options.optString("title");
            if (title != null) {
                intent.putExtra("org.openintents.extra.TITLE", title);
            }
            String button = options.optString("button");
            if (button != null) {
                intent.putExtra("org.openintents.extra.BUTTON_TEXT", button);
            }
        }
        //intent.setData(Uri.fromFile(new File("/")));
        try {
            this.cordova.startActivityForResult((Plugin)this,intent,PICK_FILE_RESULT_CODE);
        } catch (ActivityNotFoundException e) {
            showDownloadDialog();
        }
    }

    private void showDownloadDialog() {
        final Context context = this.cordova.getContext();
        Runnable runnable = new Runnable() {
            public void run() {

                AlertDialog.Builder dialog = new AlertDialog.Builder(context);
                dialog.setTitle("Install File Manager?");
                dialog.setMessage("This requires the free OI File Manager app. Would you like to install it now?");
                dialog.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dlg, int i) {
                        dlg.dismiss();
                        Intent intent = new Intent(Intent.ACTION_VIEW,
                            Uri.parse("market://search?q=pname:org.openintents.filemanager")
                        );
                        try {
                            context.startActivity(intent);
                        } catch (ActivityNotFoundException e) {
//                          We don't have the market app installed, so download it directly.
                            Intent in = new Intent(Intent.ACTION_VIEW);
                            in.setData(Uri.parse("http://openintents.googlecode.com/files/FileManager-1.2.apk"));
                            context.startActivity(in);

                        }

                    }
                });
                dialog.setNegativeButton("No", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dlg, int i) {
                        dlg.dismiss();
                    }
                });
                dialog.create();
                dialog.show();
            }
        };
        this.cordova.getActivity().runOnUiThread(runnable);
    }

    @Override
    public void onActivityResult(int reqCode, int resultCode, Intent data) {
      //super.onActivityResult(reqCode, resultCode, data);
      //Log.d(LOG_TAG, "Data is " + data.getData().toString());
      Log.d(LOG_TAG, "we are in on activity result");
      switch (reqCode) {
      case PICK_FILE_RESULT_CODE:
      case PICK_DIRECTORY_RESULT_CODE: {
          if (resultCode==Activity.RESULT_OK && data!=null && data.getData()!=null) {
              String filePath = "file://" + data.getData().getPath();
              Log.d(LOG_TAG, "The data is = " + filePath);
              Log.d(LOG_TAG, "Calling succes with callback id = " + this.callbackId);
              this.success(new PluginResult(PluginResult.Status.OK, filePath), this.callbackId);
          }
          break;
      }
  }
    }
}

Then you'd need to write your JavaScript interface:

FileDialog: {
    pickFile: function(successCallback, errorCallback, options) {
        var win = typeof successCallback !== 'function' ? null : function(f) {
            window.resolveLocalFileSystemURI(f, function(fileEntry) {
                successCallback(fileEntry);
            }, fail);
        };
        cordova.exec(win, errorCallback, "FileDialog", "pickFile", [options]);
    },
    pickFolder: function(successCallback, errorCallback, options) {
        var win = typeof successCallback !== 'function' ? null : function(d) {
            window.resolveLocalFileSystemURI(d, function(dirEntry) {
                successCallback(dirEntry);
            }, fail);
        };
        cordova.exec(win, errorCallback, "FileDialog", "pickFolder", [options]);
    },
    patch: function() {
        var inputs = document.getElementsByTagName("input");
        for (var i=0; i < inputs.length; i++) {
           if (inputs[i].getAttribute('type') == 'file'){
               var me = inputs[i];
               inputs[i].addEventListener("click", function() {
                   corinthian.FileDialog.pickFile(function(fileEntry) {
                       me.value = fileEntry.fullPath;
                   });
               });
           }
        }
    }
}

and finally monkey patch by calling FileDialog.patch(); once you have received the deviceready event in PhoneGap.

Hope this helps...

这篇关于如何使像正常的浏览器文件API的PhoneGap的(科尔多瓦)文件API工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆