升级到Phonegap 2.0后,datePicker插件无效。错误是: 未捕获的TypeError:无法读取未定义的属性'datePicker'。
javascript代码上出现错误: window.plugins.datePicker.show({...
DatePicker js文件:
/**
* 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文件:
/**
*
*/
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);
}
}
}
在谷歌上花了一些时间后,我做了以下更改: 取代
cordova.addConstructor(function() {debugger;
if (!window.plugins) {
window.plugins = {};
}
window.plugins.datePicker = new DatePicker();
});
带
window.datePicker = new DatePicker();
更新调用它的js代码
window.datePicker.show({...
现在我可以获得datePicker对象,但是遇到了这个新错误:
未捕获的TypeError:对象#没有方法'exec'
on
DatePicker.prototype.show = function(options, cb) {
...
return cordova.exec(cb, failureCallback, 'DatePickerPlugin', defaults.mode, new Array(defaults));
})
感谢您的帮助!
答案 0 :(得分:2)
检查完之后,我发现:
常见陷阱
插件可以访问CordovaInterface对象。该对象可以访问运行该应用程序的Android Activity。这是启动新Android Intent所需的Context。 CordovaInterface允许插件为结果启动Activity,并为Intent返回应用程序时设置回调插件。这很重要,因为Intents系统是Android在进程之间进行通信的方式。
插件无法像过去那样直接访问Context。旧版ctx成员已弃用,将在2.0发布后六个月删除。上下文中存在ctx的所有方法,因此getContext()和getActivity()都能够返回所需的正确对象。
避免使用webView.loadUrl()调用JavaScript。我们有一个回调服务器的原因是允许JavaScript执行是线程安全的,并且loadUrl显式地中断了UI线程,并且可能影响插件的可用性。
这是我的修复:
在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();
by:
final Context currentCtx = cordova.getActivity();
查找
ctx.runOnUiThread(runnable);
替换为:
cordova.getActivity().runOnUiThread(runnable);
这在我的带有phonegap 2.0的模拟器4.0.3中运行良好
答案 1 :(得分:1)
设置输入字段以键入“date”会显示本机日期选择器。超级简单的方法。
答案 2 :(得分:0)
window.plugins
。尝试从https://github.com/phonegap/phonegap-plugins下载最新版本的插件。