关于java:Phonegap / Cordova应用程序在Jelly Bean中中断-Access-Control-Allow-Origin和setAllowUniversalAccessFromFileURLs

Phonegap/Cordova App breaks in Jelly Bean - Access-Control-Allow-Origin and setAllowUniversalAccessFromFileURLs

我已经与Android的Cordova(aka Phonegap)合作开发*一年多了,并试图使我的应用程序可以在Jelly Bean中运行,但是出现以下错误:

1
XMLHttpRequest cannot load http://127.0.0.1:40582/[somerandomstring]. Origin null is not allowed by Access-Control-Allow-Origin. at null:1

(以及随后请求使用localhost或file://的任何后续ajax的类似错误)
为了进行测试,我授予对Access-Control-Allow-Origin

部分中config.xml中所有内容的访问权限

1
 

在我的研究中,我发现该错误与Google从Android Jelly Bean开始所做的设置更改有关。这是我发现的:
来自:https://git-wip-us.apache.org/repos/asf?p=incubator-cordova-android.git;a=commitdiff;h=07439ff9

-来自org.apache.cordova.CordovaWebView

1
2
3
4
// Jellybean rightfully tried to lock this down. Too bad they didn't give us a whitelist
// while we do this
if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)
    Level16Apis.enableUniversalAccess(settings);

-这也来自org.apache.cordova.CordovaWebView

1
2
3
4
5
6
7
8
// Wrapping these functions in their own class prevents warnings in adb like:
// VFY: unable to resolve virtual method 285: Landroid/webkit/WebSettings;.setAllowUniversalAccessFromFileURLs
@TargetApi(16)
private static class Level16Apis {
    static void enableUniversalAccess(WebSettings settings) {
         settings.setAllowUniversalAccessFromFileURLs(true);
     }
}

科尔多瓦(Cordova)尝试解决该变化很高兴,但不幸的是,这不起作用...

在这里和这里的这些SO线程中,我找到了一个通用的解决方案,可以简单地如下更改设置:

1
2
3
if(android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
    super.appView.getSettings().setAllowUniversalAccessFromFileURLs(true);    
}

现在我收到以下警告:

1
2
Call requires API level 16 (current min is 8)
android.webkit.WebSettings#setAllowUniversalAccessFromFileURLs

这是我在AndroidManifest.xml中的api

1
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="16" />

为什么要求我将minSdkVersion更改为16,而不是遵循我的targetSdkVersion(16)?

有何想法?

注意:我当前正在Windows 7 Home(所有更新),Java 7 Update 7上使用Cordova 2.0,Eclipse Indigo SR2(当前所有更新),Android SDK(当前所有更新)。


好的,因此经过大量搜索,猜测和检查,我找到了可行的解决方案。

我必须为setAllowUniversalAccessFromFileURLs调用创建一个单独的函数...修复了TargetApi问题,但随后在JellyBean上提出了另一个问题,它无法连接到我在loadURL调用中拥有的文件,因此我不得不覆盖onReceivedError函数。这是我的结果代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package com.MyUniqueDomain.MyUniquePackage;

import android.annotation.TargetApi;
import android.os.Bundle;
import org.apache.cordova.*;

public class MainActivity extends DroidGap {

    private int retryCount = 0;

    @Override
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        super.setStringProperty("loadingDialog","Please wait -- loading...");
        super.init();
        if(android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
            fixJellyBeanIssues();
        }
        super.loadUrl("file:///android_asset/www/index.html");
    }

    @TargetApi(16)
    protected void fixJellyBeanIssues() {
        System.out.println(super.appView.toString());
        try {
            super.appView.getSettings().setAllowUniversalAccessFromFileURLs(true);
        } catch(NullPointerException e) {
            System.out.println(e.toString());
        }
    }

    // catch an error and if try again 1x or quit
    @Override
    public void onReceivedError( int errorCode, String description, String failingUrl)
    {
        if(retryCount < 3) {
            retryCount++;
            System.out.println("Connection failed, trying again. Retry Count:"+retryCount);
            super.loadUrl("file:///android_asset/www/index.html");
        } else {
            System.out.println("Sorry, it failed three times so I give up.");
            super.loadUrl("file:///android_asset/www/fail.html");
        }
        return;
    }
}