本文介绍了datePicker 插件在 Phonegap 2.0 中不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

升级到Phonegap 2.0后,datePicker插件不能用了.错误是:未捕获的类型错误:无法读取未定义的属性datePicker".

After upgrading to Phonegap 2.0, the datePicker plugin does not work. The error is:Uncaught TypeError: Cannot read property 'datePicker' of undefined.

错误发生在javascript代码上:window.plugins.datePicker.show({...

the error occcurs on the javascript code:window.plugins.datePicker.show({...

DatePicker js 文件:

The DatePicker js file:

/**
* Phonegap DatePicker Plugin Copyright (c) Greg Allen 2011 MIT Licensed
* Reused and ported to Android plugin by Daniel van 't Oever
*/
if (typeof cordova !== "undefined") {
/**
 * Constructor
 */
function DatePicker() {
    this._callback;
}

/**
 * show - true to show the ad, false to hide the ad
 */
DatePicker.prototype.show = function(options, cb) {
    if (options.date) {
        options.date = (options.date.getMonth() + 1) + "/" + (options.date.getDate()) + "/" + (options.date.getFullYear()) + "/"
                + (options.date.getHours()) + "/" + (options.date.getMinutes());
    }
    var defaults = {
        mode : '',
        date : '',
        allowOldDates : true
    };

    for ( var key in defaults) {
        if (typeof options[key] !== "undefined")
            defaults[key] = options[key];
    }
    this._callback = cb;

    return cordova.exec(cb, failureCallback, 'DatePickerPlugin', defaults.mode, new Array(defaults));
};

DatePicker.prototype._dateSelected = function(date) {
    var d = new Date(parseFloat(date) * 1000);
    if (this._callback)
        this._callback(d);
};

function failureCallback(err) {
    console.log("datePickerPlugin.js failed: " + err);
}

cordova.addConstructor(function() {debugger;
    if (!window.plugins) {
        window.plugins = {};
    }
    window.plugins.datePicker = new DatePicker();
});
};

DatePicker 插件 java 文件:

The DatePicker plugin java file:

    /**
 *
 */
package com.phonegap.plugin;

import java.util.Calendar;
import java.util.Date;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.app.DatePickerDialog;
import android.app.DatePickerDialog.OnDateSetListener;
import android.app.TimePickerDialog;
import android.app.TimePickerDialog.OnTimeSetListener;
import android.util.Log;
import android.widget.DatePicker;
import android.widget.TimePicker;


import org.apache.cordova.DroidGap;
import org.apache.cordova.api.Plugin;
import org.apache.cordova.api.PluginResult;

/**
 * @author ng4e
 * @author Daniel van 't Oever
 *
 *         Rewrote plugin so it it similar to the iOS datepicker plugin and it
 *         accepts prefilled dates and time
 */
public class DatePickerPlugin extends Plugin {

    private static final String ACTION_DATE = "date";
    private static final String ACTION_TIME = "time";
    private final String pluginName = "DatePickerPlugin";

    /*
     * (non-Javadoc)
     *
     * @see com.phonegap.api.Plugin#execute(java.lang.String,
     * org.json.JSONArray, java.lang.String)
     */
    @Override
    public PluginResult execute(final String action, final JSONArray data, final String callBackId) {
        Log.d(pluginName, "DatePicker called with options: " + data);
        PluginResult result = null;

        this.show(data, callBackId);
        result = new PluginResult(PluginResult.Status.NO_RESULT);
        result.setKeepCallback(true);

        return result;
    }

    public synchronized void show(final JSONArray data, final String callBackId) {
        final DatePickerPlugin datePickerPlugin = this;
        @SuppressWarnings("deprecation")
        final DroidGap currentCtx = (DroidGap) ctx.getContext();
        final Calendar c = Calendar.getInstance();
        final Runnable runnable;

        String action = "date";

        /*
         * Parse information from data parameter and where possible, override
         * above date fields
         */
        int month = -1, day = -1, year = -1, hour = -1, min = -1;
        try {
            JSONObject obj = data.getJSONObject(0);
            action = obj.getString("mode");

            String optionDate = obj.getString("date");

            String[] datePart = optionDate.split("/");
            month = Integer.parseInt(datePart[0]);
            day = Integer.parseInt(datePart[1]);
            year = Integer.parseInt(datePart[2]);
            hour = Integer.parseInt(datePart[3]);
            min = Integer.parseInt(datePart[4]);

            /* currently not handled in Android */
            // boolean optionAllowOldDates = obj.getBoolean("allowOldDates");

        } catch (JSONException e) {
            e.printStackTrace();
        }

        // By default initialize these fields to 'now'
        final int mYear = year == -1 ? c.get(Calendar.YEAR) : year;
        final int mMonth = month == -1 ? c.get(Calendar.MONTH) : month - 1;
        final int mDay = day == -1 ? c.get(Calendar.DAY_OF_MONTH) : day;
        final int mHour = hour == -1 ? c.get(Calendar.HOUR_OF_DAY) : hour;
        final int mMinutes = min == -1 ? c.get(Calendar.MINUTE) : min;

        if (ACTION_TIME.equalsIgnoreCase(action)) {
            runnable = new Runnable() {
                public void run() {
                    final TimeSetListener timeSetListener = new TimeSetListener(datePickerPlugin, callBackId);
                    final TimePickerDialog timeDialog = new TimePickerDialog(currentCtx, timeSetListener, mHour,
                            mMinutes, true);
                    timeDialog.show();
                }
            };

        } else if (ACTION_DATE.equalsIgnoreCase(action)) {
            runnable = new Runnable() {
                public void run() {
                    final DateSetListener dateSetListener = new DateSetListener(datePickerPlugin, callBackId);
                    final DatePickerDialog dateDialog = new DatePickerDialog(currentCtx, dateSetListener, mYear,
                            mMonth, mDay);
                    dateDialog.show();
                }
            };

        } else {
            Log.d(pluginName, "Unknown action. Only 'date' or 'time' are valid actions");
            return;
        }

        //((Activity) ctx).runOnUiThread(runnable);
    }

    private final class DateSetListener implements OnDateSetListener {
        private final DatePickerPlugin datePickerPlugin;
        private final String callBackId;

        private DateSetListener(DatePickerPlugin datePickerPlugin, String callBackId) {
            this.datePickerPlugin = datePickerPlugin;
            this.callBackId = callBackId;
        }

        /**
         * Return a string containing the date in the format YYYY/MM/DD
         */
        public void onDateSet(final DatePicker view, final int year, final int monthOfYear, final int dayOfMonth) {
            String returnDate = year + "/" + (monthOfYear + 1) + "/" + dayOfMonth;
            datePickerPlugin.success(new PluginResult(PluginResult.Status.OK, returnDate), callBackId);

        }
    }

    private final class TimeSetListener implements OnTimeSetListener {
        private final DatePickerPlugin datePickerPlugin;
        private final String callBackId;

        private TimeSetListener(DatePickerPlugin datePickerPlugin, String callBackId) {
            this.datePickerPlugin = datePickerPlugin;
            this.callBackId = callBackId;
        }

        /**
         * Return the current date with the time modified as it was set in the
         * time picker.
         */
        public void onTimeSet(final TimePicker view, final int hourOfDay, final int minute) {
            /*Date date = new Date();
            date.setHours(hourOfDay);
            date.setMinutes(minute);*/
            Calendar today = Calendar.getInstance();
            today.set(Calendar.HOUR_OF_DAY, hourOfDay);
            today.set(Calendar.MINUTE, minute);
            Date date = today.getTime();

            datePickerPlugin.success(new PluginResult(PluginResult.Status.OK, date.toString()), callBackId);

        }
    }

}

在我花时间在 google 上之后,我做了以下更改:替换

After I spend time on google, I made the following changes:replace

    cordova.addConstructor(function() {debugger;
    if (!window.plugins) {
        window.plugins = {};
    }
    window.plugins.datePicker = new DatePicker();
    });

window.datePicker = new DatePicker();

更新调用的js代码为

window.datePicker.show({...

现在我无论如何都可以获取 datePicker 对象,但是出现了这个新错误:

Now I can get the datePicker object anyway, but got this new error:

Uncaught TypeError: Object # has no method 'exec'

Uncaught TypeError: Object # has no method 'exec'

DatePicker.prototype.show = function(options, cb) {
    ...
    return cordova.exec(cb, failureCallback, 'DatePickerPlugin', defaults.mode, new  Array(defaults));
})

感谢您的帮助!

推荐答案

http://docs.phonegap.com/en/2.0.0/guide_plugin-development_android_index.md.html#Developing%20a%20Plugin%20on%20Android

检查后,我发现:

常见的陷阱

插件可以访问 CordovaInterface 对象.该对象可以访问运行该应用程序的 Android Activity.这是启动新的 Android Intent 所需的 Context.CordovaInterface 允许插件为结果启动 Activity,并为 Intent 返回应用程序时设置回调插件.这很重要,因为 Intents 系统是 Android 在进程之间进行通信的方式.

Plugins have access to a CordovaInterface object. This object has access to the Android Activity that is running the application. This is the Context required to launch a new Android Intent. The CordovaInterface allows plugins to start an Activity for a result, and to set the callback plugin for when the Intent comes back to the application. This is important, since the Intents system is how Android communicates between processes.

插件不能像过去那样直接访问上下文.旧版 ctx 成员已弃用,将在 2.0 发布六个月后删除.ctx 拥有的所有方法都存在于 Context 中,因此 getContext() 和 getActivity() 都能够返回所需的正确对象.

Plugins do not have direct access to the Context as they have in the past. The legacy ctx member is deprecated, and will be removed six months after 2.0 is released. All the methods that ctx has exist on the Context, so both getContext() and getActivity() are capable of returning the proper object required.

避免使用 webView.loadUrl() 调用 JavaScript.我们有回调服务器的原因是为了让 JavaScript 执行是线程安全的,而 loadUrl 会显式中断 UI 线程,并且会影响插件的可用性.

Avoid calling JavaScript using webView.loadUrl(). The reason we have a callback server is to allow JavaScript execution to be thread-safe, and loadUrl explicitly interrupts the UI thread, and can affect the usability of your plugin.

这是我的修复:

在 DatePickerPlugin.java 中

in DatePickerPlugin.java

import android.content.Context;
....

public synchronized void show(final JSONArray data, final String callBackId) {
     final DatePickerPlugin datePickerPlugin = this;
     final DroidGap currentCtx = (DroidGap) ctx.getContext();
     final Calendar c = Calendar.getInstance();
.....

替换行:

final DroidGap currentCtx = (DroidGap) ctx.getContext();

作者:

final Context currentCtx = cordova.getActivity();

查找:

ctx.runOnUiThread(runnable);

替换为:

cordova.getActivity().runOnUiThread(runnable);

这在我的模拟器 4.0.3 和 phonegap 2.0 中运行良好

This is working fine in my emulator 4.0.3 with phonegap 2.0

这篇关于datePicker 插件在 Phonegap 2.0 中不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-30 07:17