今天在测试PhoneGap官方提供的例子,运行到手机上一直弹出Error initializing Cordova:Class not found...网上资料不多,大部分都是说res/xml/config.xml配置有问题,导致找不到类...
然而,细心的查了一遍res/xml/config.xml,并没有发现有错误的地方,那么是什么原因呢?冥思苦想,甚至把cordova.android.js细看了一遍,还是没发现错误,最后,定位到了org.apache.cordova.api.PluginManager这个类,控制台报了这么一段错误:
错误是说config.xml找不到,但是config.xml明明就存在,而且在R文件里面也能找到
这下有意思了,我们来org.apache.cordova.api.PluginManager类里面的loadPlugins()方法的第一行
/**
* Load plugins from res/xml/config.xml
*/
public void loadPlugins() {
int id = this.ctx.getActivity().getResources().getIdentifier("config", "xml", this.ctx.getActivity().getClass().getPackage().getName()); // 就是这一句,返回的id是0,也就是这样的方式并无法找到config.xml
//int id = org.apache.cordova.R.xml.config; // 替换成这一句,问题搞定~
Log.e(TAG, "。。。。"+id); // 这边id Log输出就知道了...真是个坑
if (id == 0) {
this.pluginConfigurationMissing();
//We have the error, we need to exit without crashing!
return;
}
XmlResourceParser xml = this.ctx.getActivity().getResources().getXml(id);
int eventType = -1;
String service = "", pluginClass = "", paramType = "";
boolean onload = false;
boolean insideFeature = false;
while (eventType != XmlResourceParser.END_DOCUMENT) {
if (eventType == XmlResourceParser.START_TAG) {
String strNode = xml.getName();
//This is for the old scheme
if (strNode.equals("plugin")) {
service = xml.getAttributeValue(null, "name");
pluginClass = xml.getAttributeValue(null, "value");
Log.d(TAG, " tags are deprecated, please use instead. will no longer work as of Cordova 3.0");
onload = "true".equals(xml.getAttributeValue(null, "onload"));
}
//What is this?
else if (strNode.equals("url-filter")) {
this.urlMap.put(xml.getAttributeValue(null, "value"), service);
}
else if (strNode.equals("feature")) {
//Check for supported feature sets aka. plugins (Accelerometer, Geolocation, etc)
//Set the bit for reading params
insideFeature = true;
service = xml.getAttributeValue(null, "name");
}
else if (insideFeature && strNode.equals("param")) {
paramType = xml.getAttributeValue(null, "name");
if (paramType.equals("service")) // check if it is using the older service param
service = xml.getAttributeValue(null, "value");
else if (paramType.equals("package") || paramType.equals("android-package"))
pluginClass = xml.getAttributeValue(null,"value");
else if (paramType.equals("onload"))
onload = "true".equals(xml.getAttributeValue(null, "value"));
}
}
else if (eventType == XmlResourceParser.END_TAG)
{
String strNode = xml.getName();
if (strNode.equals("feature") || strNode.equals("plugin"))
{
PluginEntry entry = new PluginEntry(service, pluginClass, onload);
this.addService(entry);
//Empty the strings to prevent plugin loading bugs
service = "";
pluginClass = "";
insideFeature = false;
}
}
try {
eventType = xml.next();
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
所以,把寻找config.xml这句直接替换为 int id = org.apache.cordova.R.xml.config;
那么为什么会找不到config.xml呢?Log输出一下可以发现,this.ctx.getActivity().getClass().getPackage().getName() 这句话返回的包名并不正确,而是我们测试工程里面的一个包名...
为什么会这样呢?因为this.ctx,这个是一个CordovaInterface类型,是一个接口,而最终真正实现它的是org.apache.cordova.test.actions.CordovaActivity这个类,那么我们来看一下他的继承关系:
org.apache.cordova.api.CordovaInterface
-> org.apache.cordova.CordovaActivity
-> org.apache.cordova.DroidGap
-> org.apache.cordova.test.actions.CordovaActivity
这么看来,出现Class not found的问题也就不奇怪了...