我要将应用程序从使用phonegap开发的7版android sdk升级到16版android sdk。
调用PhoneGap.JSCallback时,发生以下错误:
I/chromium: [INFO:CONSOLE(0)] "Access to XMLHttpRequest at 'http://127.0.0.1:42857/adbed140-2489-4bfd-94bf-319f79216d83' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.", source: file:///android_asset/www/index.html (0)
I/chromium: [INFO:CONSOLE(711)] "JSCallback Error: Request failed.", source: file:///android_asset/www/js/phonegap.0.9.4.js (711)
D/NetworkManagementSocketTagger: tagSocket(64) with statsTag=0xffffffff, statsUid=-1
D/NetworkManagementSocketTagger: tagSocket(165) with statsTag=0xffffffff, statsUid=-1
我发现问题是跨域的,我可以通过在标头中添加“ Access-Control-Allow-Orgin”来进行过滤,但是我不确定如何将相关信息添加到Android应用中。
以下是导致错误的部分来源:
PhoneGap.JSCallback = function() {
var xmlhttp = new XMLHttpRequest();
// Callback function when XMLHttpRequest is ready
xmlhttp.onreadystatechange=function(){
if(xmlhttp.readyState == 4){
// If callback has JavaScript statement to execute
if (xmlhttp.status == 200) {
var msg = xmlhttp.responseText;
setTimeout(function() {
try {
var t = eval(msg);
}
catch (e) {
// If we're getting an error here, seeing the message will help in debugging
console.log("JSCallback: Message from Server: " + msg);
console.log("JSCallback Error: "+e);
}
}, 1);
setTimeout(PhoneGap.JSCallback, 1);
}
// If callback ping (used to keep XHR request from timing out)
else if (xmlhttp.status == 404) {
setTimeout(PhoneGap.JSCallback, 10);
}
// If security error
else if (xmlhttp.status == 403) {
console.log("JSCallback Error: Invalid token. Stopping callbacks.");
}
// If server is stopping
else if (xmlhttp.status == 503) {
console.log("JSCallback Error: Service unavailable. Stopping callbacks.");
}
// If request wasn't GET
else if (xmlhttp.status == 400) {
console.log("JSCallback Error: Bad request. Stopping callbacks.");
}
// If error, restart callback server
else {
console.log("JSCallback Error: Request failed.");
CallbackServer.restartServer();
PhoneGap.JSCallbackPort = null;
PhoneGap.JSCallbackToken = null;
setTimeout(PhoneGap.JSCallback, 100);
}
}
}
if (PhoneGap.JSCallbackPort == null) {
PhoneGap.JSCallbackPort = CallbackServer.getPort();
}
if (PhoneGap.JSCallbackToken == null) {
PhoneGap.JSCallbackToken = CallbackServer.getToken();
}
/** the part where an error is expected to occur. **/
xmlhttp.open("GET", "http://127.0.0.1:"+PhoneGap.JSCallbackPort+"/"+PhoneGap.JSCallbackToken , true);
xmlhttp.send();
};
以下来源也有问题:
package com.hello.world.plugin;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.content.Intent;
import android.net.Uri;
import android.os.Handler;
import android.util.Log;
import com.hello.world.R;
import com.hello.world.World;
import com.hello.world.push.PushService;
import com.phonegap.Device;
import com.phonegap.api.Plugin;
import com.phonegap.api.PluginResult;
public class NativeControls extends Plugin {
String callbackId;
/**
* Executes the request and returns PluginResult.
*
* @param action The action to execute.
* @param args JSONArray 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.
*/
public PluginResult execute(String action, JSONArray args, String callbackId) {
try {
this.callbackId = callbackId;
String deviceId = "";
String serverUrl = "";
String pushServerIp = "";
String pushPort = "";
if (action.equals("serverUrlInfo")) {
serverUrl = this.ctx.getSharedPreferences(World.TAG, android.content.Context.MODE_PRIVATE).getString(World.SERVER_URL,"");
if(serverUrl == null || "".equals(serverUrl)){
Device device = new Device();
device.setContext(this.ctx);
deviceId = device.getDeviceId();
Log.e("NativeControls serverUrlInfo.deviceID", deviceId);
//default값 resource strings.xml read
serverUrl = this.ctx.getResources().getString(R.string.server_url);
pushServerIp = this.ctx.getResources().getString(R.string.push_server);
pushPort = this.ctx.getResources().getString(R.string.push_port);
// 서버 정보가 정상이라고 가정할 때, SharedPreferences에 SERVER_URL의 값이 없는 상태로
// WebView를 동작시에는 Toolbar에서 SERVER_URL이 빈 문자열로 반환될 수 있으므로, 기본값을 저장한다.
this.ctx.getSharedPreferences(World.TAG, android.content.Context.MODE_PRIVATE).edit().putString(World.SERVER_URL, serverUrl).commit();
this.ctx.getSharedPreferences(PushService.TAG, android.content.Context.MODE_PRIVATE).edit()
.putString(PushService.PREF_DEVICE_ID, deviceId)
.putString(PushService.MQTT_SVR_IP, pushServerIp)
.putInt(PushService.MQTT_SVR_PORT, Integer.parseInt(pushPort))
.commit();
}
String gwProtocol = "http", gwPort = "80";
if ( serverUrl.startsWith("https://") ){
gwProtocol = "https";
gwPort = "443";
}
String gwDomain = serverUrl.substring(gwProtocol.length() + 3);
gwDomain = gwDomain.substring(0, gwDomain.indexOf("/"));
if ( gwDomain.indexOf(":") > -1) {
gwPort = gwDomain.substring(gwDomain.indexOf(":")+1);
gwDomain = gwDomain.substring(0, gwDomain.indexOf(":"));
}
String gwContext = serverUrl.substring(serverUrl.lastIndexOf("/"));
if ( gwContext.startsWith(gwDomain) && gwContext.indexOf("/") < 0) {
gwContext = "";
}
JSONObject srvrInfo = new JSONObject();
srvrInfo.put("serverUrl", serverUrl);
srvrInfo.put("gwProtocol", gwProtocol); // GW service Protocol (http , https)
srvrInfo.put("gwDomain", gwDomain); // GW service Domain or Ip
srvrInfo.put("gwPort", gwPort); // GW service Port
srvrInfo.put("gwContext", gwContext); // GW service Context Name
// The corresponding code returns new pluginResult (PluginResult.Status).JSON_EXCEPTION); returns to
PluginResult r = new PluginResult(PluginResult.Status.OK, srvrInfo);
return r;
}
//config
else if (action.equals("serverUrlSave")) {
saveConfig(args);
}
else if (action.equals("showToolBar")) {
Handler mHandler = ((World)this.ctx).getToolbarHandler();
mHandler.sendEmptyMessage(1);
}
else if (action.equals("hideToolBar")) {
Handler mHandler = ((World)this.ctx).getToolbarHandler();
mHandler.sendEmptyMessage(0);
}
else if (action.equals("openBrowser")) {
String url = args.getString(0); //URL
final Intent intent = new Intent(Intent.ACTION_VIEW).setData(Uri.parse(url));
this.ctx.startActivity(intent);
}
PluginResult r = new PluginResult(PluginResult.Status.OK);
return r;
} catch (JSONException e) {
e.printStackTrace();
// I don't know why the stacks are returned immediately without being created.
return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
}
}
public void onActivityResult(int requestCode, int resultCode, Intent data){
super.onActivityResult(requestCode, resultCode, data);
}
}