今天在测试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, "<plugin> tags are deprecated, please use <features> instead. <plugin> 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的问题也就不奇怪了...