Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plugin initialization error in older devices when using Cordova 5 #226

Closed
homer-jay opened this issue Feb 26, 2016 · 1 comment
Closed

Comments

@homer-jay
Copy link
Contributor

CordovaWebView.sendJavascript method is deprecated. It has been deprecated from some time ago, but it worked. Now with Cordova 5 in a 4.2 device this exception is thrown during Cordova initialization:

02-26 10:06:30.048: W/dalvikvm(7979): DexOpt: method is in an interface
02-26 10:06:30.048: I/dalvikvm(7979): Could not find method org.apache.cordova.CordovaWebView.sendJavascript, referenced from method com.chariotsolutions.nfc.plugin.NfcPlugin.fireNdefEvent
02-26 10:06:30.048: W/dalvikvm(7979): VFY:  rejected Lcom/chariotsolutions/nfc/plugin/NfcPlugin;.fireNdefEvent (Ljava/lang/String;Landroid/nfc/tech/Ndef;[Landroid/os/Parcelable;)V
02-26 10:06:30.048: W/dalvikvm(7979): Verifier rejected class Lcom/chariotsolutions/nfc/plugin/NfcPlugin;
02-26 10:06:30.048: W/System.err(7979): java.lang.ClassNotFoundException: com.chariotsolutions.nfc.plugin.NfcPlugin
02-26 10:06:30.048: W/System.err(7979):     at java.lang.Class.classForName(Native Method)
02-26 10:06:30.048: W/System.err(7979):     at java.lang.Class.forName(Class.java:217)
02-26 10:06:30.048: W/System.err(7979):     at java.lang.Class.forName(Class.java:172)
02-26 10:06:30.048: W/System.err(7979):     at org.apache.cordova.PluginManager.instantiatePlugin(PluginManager.java:490)
02-26 10:06:30.048: W/System.err(7979):     at org.apache.cordova.PluginManager.getPlugin(PluginManager.java:170)
02-26 10:06:30.048: W/System.err(7979):     at org.apache.cordova.PluginManager.exec(PluginManager.java:123)
02-26 10:06:30.058: W/System.err(7979):     at org.apache.cordova.CordovaBridge.jsExec(CordovaBridge.java:59)
02-26 10:06:30.058: W/System.err(7979):     at org.apache.cordova.CordovaBridge.promptOnJsPrompt(CordovaBridge.java:135)
02-26 10:06:30.058: W/System.err(7979):     at org.apache.cordova.engine.SystemWebChromeClient.onJsPrompt(SystemWebChromeClient.java:124)
02-26 10:06:30.058: W/System.err(7979):     at android.webkit.CallbackProxy.handleMessage(CallbackProxy.java:886)
02-26 10:06:30.058: W/System.err(7979):     at android.os.Handler.dispatchMessage(Handler.java:99)
02-26 10:06:30.058: W/System.err(7979):     at android.os.Looper.loop(Looper.java:137)
02-26 10:06:30.058: W/System.err(7979):     at android.app.ActivityThread.main(ActivityThread.java:4867)
02-26 10:06:30.058: W/System.err(7979):     at java.lang.reflect.Method.invokeNative(Native Method)
02-26 10:06:30.058: W/System.err(7979):     at java.lang.reflect.Method.invoke(Method.java:511)
02-26 10:06:30.058: W/System.err(7979):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1007)
02-26 10:06:30.058: W/System.err(7979):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:774)
02-26 10:06:30.058: W/System.err(7979):     at dalvik.system.NativeStart.main(Native Method)
02-26 10:06:30.058: W/System.err(7979): Caused by: java.lang.VerifyError: com/chariotsolutions/nfc/plugin/NfcPlugin
02-26 10:06:30.058: W/System.err(7979):     ... 18 more
02-26 10:06:30.058: I/System.out(7979): Error adding plugin com.chariotsolutions.nfc.plugin.NfcPlugin.
02-26 10:06:30.058: W/System.err(7979): java.lang.NullPointerException
02-26 10:06:30.068: W/System.err(7979):     at org.apache.cordova.PluginManager.getPlugin(PluginManager.java:172)
02-26 10:06:30.068: W/System.err(7979):     at org.apache.cordova.PluginManager.exec(PluginManager.java:123)
02-26 10:06:30.068: W/System.err(7979):     at org.apache.cordova.CordovaBridge.jsExec(CordovaBridge.java:59)
02-26 10:06:30.068: W/System.err(7979):     at org.apache.cordova.CordovaBridge.promptOnJsPrompt(CordovaBridge.java:135)
02-26 10:06:30.068: W/System.err(7979):     at org.apache.cordova.engine.SystemWebChromeClient.onJsPrompt(SystemWebChromeClient.java:124)
02-26 10:06:30.068: W/System.err(7979):     at android.webkit.CallbackProxy.handleMessage(CallbackProxy.java:886)
02-26 10:06:30.068: W/System.err(7979):     at android.os.Handler.dispatchMessage(Handler.java:99)
02-26 10:06:30.068: W/System.err(7979):     at android.os.Looper.loop(Looper.java:137)
02-26 10:06:30.068: W/System.err(7979):     at android.app.ActivityThread.main(ActivityThread.java:4867)
02-26 10:06:30.068: W/System.err(7979):     at java.lang.reflect.Method.invokeNative(Native Method)
02-26 10:06:30.068: W/System.err(7979):     at java.lang.reflect.Method.invoke(Method.java:511)
02-26 10:06:30.068: W/System.err(7979):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1007)
02-26 10:06:30.068: W/System.err(7979):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:774)
02-26 10:06:30.078: W/System.err(7979):     at dalvik.system.NativeStart.main(Native Method)

As I said it was working fine in Cordova 3.7, and the method still exists in the CordovaWebView class, but for some unknown reason the exception is thrown only in older devices. And in my case I only got the exception when using NDEF-related functionality. If you only need to read a tag's ID you probably won't see it.

So I looked for alternatives to sendJavascript. Many other plugins stopped using it to get rid of the deprecation warning.
In some repos (links at the end) I've seen they replaced the calls to webView.sendJavascript with calls to a private sendJavascript method that executes JavaScript in the WebView using alternative methods:

@TargetApi(Build.VERSION_CODES.KITKAT)
private void sendJavascript(final String javascript) {
    webView.post(new Runnable() {
        @Override
        public void run() {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                webView.evaluateJavascript(javascript, null);
            } else {
                webView.loadUrl("javascript:"  +  javascript);
            }
        }
    });
}

This probably worked for Cordova 4, but then the guys at Cordova changed everything again in their new release (as they do always) and broke such code.
There are two issues here that will prevent compilation in Cordova 5:
- CordovaWebView.post was removed
- CordovaWebView.evaluateJavascript was removed

So the proposed fix for Cordova 5 now looks like this:

@TargetApi(Build.VERSION_CODES.KITKAT)
private void sendJavascript(final String javascript) {
    webView.getView().post(new Runnable() {
        @Override           
        public void run() {             
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                webView.sendJavascript(javascript);
            } else {                    
                webView.loadUrl("javascript:" + javascript);
            }
        }
    });
}

It falls back again to sendJavascript but only for KitKat and newer versions. I've tested this code in 4.2 and 5.1 devices and it works well.

But there are a number of issues with this code:

  • First I don't know whether the Build.VERSION check for KitKat is correct or not. Maybe it has been carried over from the previous snippets when they needed KitKat to call evaluateJavascript?
    Maybe it would also work in JellyBean? Or maybe we should check for Lollipop instead?
  • Second: why do they need to post a new runnable? What implications could this have for our plugin?

So my proposed fix is simpler and can be seen in this commit. I've tested it in 4.2 and 5.1 devices and it works, so I've created a pull request.

LINKS TO OTHER REPOS WITH RELATED PROBLEMS:
katzer/cordova-plugin-local-notifications#535
https://github.com/driftyco/ionic-plugin-keyboard/pull/40/commits

@don
Copy link
Member

don commented Apr 18, 2018

Closing old issue. Hopefully new Cordova and Android fixes all this.

@don don closed this as completed Apr 18, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants