在Android应用程序中使用CordovaWebView时出现JNI错误

时间:2013-01-04 17:43:12

标签: android cordova java-native-interface

我的Android应用使用Cordova / PhoneGap在JavaScript端实现业务逻辑。因此,有一个活动可以加载CordovaWebView,然后加载一些片段以提供本机UI元素。

以下是Activity的onCreate方法及其startFragment方法来实例化新片段

public class MyPhoneGapActivity extends
    SherlockFragmentActivity implements CordovaInterface {

    private static CordovaWebView sGlobalCordovaWebView;
    private final ExecutorService mThreadPool = Executors.newCachedThreadPool();
    private SherlockFragment mLatestFragment;
    private Bundle mSavedInstanceState;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        this.mSavedInstanceState = savedInstanceState;

        setIntegerProperty("loadUrlTimeoutValue", 60000);
        setContentView(R.layout.phonegap_activity);

        sGlobalCordovaWebView = (CordovaWebView) findViewById(R.id.phonegap_activity_cordovawebview);
        sGlobalCordovaWebView.loadUrl("file:///android_asset/www/index.html");

        startFragment("com.acme.view.ExampleScreenView");
    }

    public SherlockFragment startFragment(String name) throws RuntimeException {
        try {

            mLatestFragment = (SherlockFragment) SherlockFragment.instantiate(getActivity(),
                Class.forName(name).getName());

            getSupportFragmentManager()
                .beginTransaction()
                .add(R.id.phonegap_activity_fragment,
                        mLatestFragment, "activityFragment").commit();
            getSupportFragmentManager().executePendingTransactions();

        } catch (ClassNotFoundException e) {
            throw new RuntimeException(
                "startFragment: The class for the desired fragment could not be found.");
        }
        return mLatestFragment;
    }
}

但是在我的HTC EVO设备上运行应用程序时会导致JNI错误:

01-04 17:58:11.537: E/dalvikvm(5451): JNI ERROR (app bug): attempt to use stale local     reference 0x1
01-04 17:58:11.537: E/dalvikvm(5451): VM aborting
01-04 17:58:11.537: A/libc(5451): Fatal signal 11 (SIGSEGV) at 0xdeadd00d (code=1)
01-04 17:58:11.967: I/DEBUG(5047): debuggerd: 2013-01-04 17:58:11
01-04 17:58:11.967: I/DEBUG(5047): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
01-04 17:58:11.967: I/DEBUG(5047): Build fingerprint: 'htc_europe/htc_shooteru/shooteru:4.0.3/IML74K/385730.1:user/release-keys'
01-04 17:58:11.967: I/DEBUG(5047): pid: 5451, tid: 5531  >>> eu.mobilion.wasserfinder <<<
01-04 17:58:11.967: I/DEBUG(5047): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr deadd00d
01-04 17:58:11.967: I/DEBUG(5047):  r0 00000000  r1 00c34d48  r2 00000000  r3 00000000
01-04 17:58:11.967: I/DEBUG(5047):  r4 deadd00d  r5 40950ce8  r6 0000020c  r7 52131900
01-04 17:58:11.967: I/DEBUG(5047):  r8 01320c50  r9 27600005  10 0000000c  fp 0127c3d0
01-04 17:58:11.967: I/DEBUG(5047):  ip 00000000  sp 52131650  lr 408e82db  pc 408e82da  cpsr 60000030
01-04 17:58:11.967: I/DEBUG(5047):  d0  0000000000000000  d1  0000000000000000
...
01-04 17:58:11.977: I/DEBUG(5047):  d30 0000000000000000  d31 3ff0000000000000
01-04 17:58:11.977: I/DEBUG(5047):  scr 60000013
01-04 17:58:12.247: I/DEBUG(5047):          #00  pc 000512da  /system/lib/libdvm.so (dvmAbort)
01-04 17:58:12.247: I/DEBUG(5047):          #01  pc 000326b8  /system/lib/libdvm.so (_ZNK16IndirectRefTable3getEPv)
01-04 17:58:12.247: I/DEBUG(5047):          #02  pc 00055ea4  /system/lib/libdvm.so (_Z20dvmDecodeIndirectRefP6ThreadP8_jobject)
01-04 17:58:12.247: I/DEBUG(5047):          #03  pc 0005724c  /system/lib/libdvm.so
01-04 17:58:12.247: I/DEBUG(5047):          #04  pc 0022707e  /system/lib/libwebcore.so
01-04 17:58:12.247: I/DEBUG(5047):          #05  pc 003ee990  /system/lib/libwebcore.so
01-04 17:58:12.247: I/DEBUG(5047):          #06  pc 003a2cd2  /system/lib/libwebcore.so
01-04 17:58:12.247: I/DEBUG(5047):          #07  pc 003a30ca  /system/lib/libwebcore.so
...

评论行sGlobalCordovaWebView.loadUrl("file:///android_asset/www/index.html")时,应用程序启动并显示包含所有片段的原生UI,但当然由于缺少JavaScript逻辑而没有任何功能。

我注意到android JNI ERROR,但我没有为我做这个伎俩。


编辑:phonegap_activity.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <org.apache.cordova.CordovaWebView
        android:id="@+id/phonegap_activity_cordovawebview"
        android:layout_width="1dp"
        android:layout_height="1dp"
        android:visibility="invisible" />

    <FrameLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_below="@+id/phonegap_activity_cordovawebview"
        android:id="@+id/phonegap_activity_fragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    </FrameLayout>

</RelativeLayout>

1 个答案:

答案 0 :(得分:2)

解决了这个问题。诀窍是在cordova插件中使用getActivity().runOnUiThread(..)并将所有UI创建内容和片段启动放入其中。 E.g。

 public class MyPlugin extends CordovaPlugin {

     public boolean execute(String action, final JSONArray jA, final CallbackContext cC) {
         if (action.equals("myAction"))
             return doSth(action, jA, cC);
     }

     private boolean doSth(String action, final JSONArray jA, final CallbackContext cC) {
         getActivity().runOnUiThread(new Runnable() {
             @Override
             public void run() {
                 // start fragment with UI stuff ....
             }
         }
         cC.success(); 
         return true;
     }

 }