Android Java和Phonegap Javascript之间的通信?


81

我相信可以从(PhoneGap)Javascript调用Java方法。

有人知道该怎么做吗?(我知道如何通过更改PhoneGap的源代码来做到这一点,但我会避免这样做)

Answers:


125

我终于做到了。

  • 使用您要使用的方法创建一个类:

    public class MyClass {
      private WebView mAppView;
      private DroidGap mGap;
    
      public MyClass(DroidGap gap, WebView view)
      {
        mAppView = view;
        mGap = gap;
      }
    
      public String getTelephoneNumber(){
        TelephonyManager tm = 
          (TelephonyManager) mGap.getSystemService(Context.TELEPHONY_SERVICE);
        String number = tm.getLine1Number();
        return number;
      }
    }
    
  • 在您的主要活动中,为该类添加一个Javascript接口:

    public class Main extends DroidGap
    {
        private MyClass mc;
    
        @Override
        public void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
            super.init();
    
            mc = new MyClass(this, appView);
            appView.addJavascriptInterface(mc, "MyCls");
    
            super.loadUrl(getString(R.string.url));
        }
    }
    
  • 在Javascript调用window.MyCls方法中:

    <script>
      $(function(){
        $("#phone").text("My telephone number is: " + 
                window.MyCls.getTelephoneNumber());
      });
    </script>
    

注意:

如评论中所述,对于Android 4.2及更高版本,将其添加@JavascriptInterface到要从HTML页面访问的方法中。参考


嗯,这个例子很棒,但是我在appView上得到了一个nullpointer异常,它似乎为null。您在哪里初始化对象?
最白目

1
添加super.init(); 就像下面提到的@Karfield一样,为我修复了nullpointer异常。
Renato H.

8
做得好!提示:如果您想反方向交流(从Java到Javascript),请使用以下方法:mGap.sendJavascript(“ window.myJavascriptFunction('some parameter');”);
aeldron 2012年

5
E / Web控制台(2513):未捕获的TypeError:对象[object Object]在file:///android_asset/www/loginfile.js:142 window.Mycls.sendEmail(“ rea@gmail.com”)上没有方法'sendEmail' ); 在此行发生错误
Deepu Mandy 2013年

2
我已经为Android 4.2.2尝试过此代码,我遇到了一个与Deepu类似的问题,即Uncaught TypeError:Object [object Object]在file:///android_asset/www/app.js:142上没有方法'getTelephoneNumber'。经过一些调试后,我发现您需要添加@JavascriptInterface来访问要在4.2.2链接
Akshay

14

addJavaScriptInterface(mc, "MyCls")没有Gap init()ed可能会导致应用程序崩溃,您最好super.init()在添加之前addJavascriptInterface()

public class Main extends DroidGap
{
   private MyClass mc;

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

       super.init();

       mc = new MyClass(this, appView);
       appView.addJavascriptInterface(mc, "MyCls");

       super.loadUrl(getString(R.string.url));
   }
}

9

PhoneGap有一个不错的插件API。您将通过实现IPlugin接口用Java编写插件。大多数魔术都在execute()函数中。

public interface IPlugin {

    /**
     * Executes the request and returns PluginResult.
     *
     * @param action        The action to execute.
     * @param args          JSONArry 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.
     */
    PluginResult execute(String action, JSONArray args, String callbackId);

        // ... more ...
}

开始编写插件的最佳方法是首先编写javascript API。通常,您首先要编写一个自定义javascript类,然后在javascript类的每个方法中,将变量编组并调用使用Phonegap.exec()方法开发的插件。这是方法签名,供您参考。

/* src/com/phonegap/api/PluginManager.java */
/**
 * Receives a request for execution and fulfills it by finding the appropriate
 * Java class and calling it's execute method.
 *
 * PluginManager.exec can be used either synchronously or async. In either case, a JSON encoded
 * string is returned that will indicate if any errors have occurred when trying to find
 * or execute the class denoted by the clazz argument.
 *
 * @param service       String containing the service to run
 * @param action        String containt the action that the class is supposed to perform. This is
 *                      passed to the plugin execute method and it is up to the plugin developer
 *                      how to deal with it.
 * @param callbackId    String containing the id of the callback that is execute in JavaScript if
 *                      this is an async plugin call.
 * @param args          An Array literal string containing any arguments needed in the
 *                      plugin execute method.
 * @param async         Boolean indicating whether the calling JavaScript code is expecting an
 *                      immediate return value. If true, either PhoneGap.callbackSuccess(...) or
 *                      PhoneGap.callbackError(...) is called once the plugin code has executed.
 *
 * @return              JSON encoded string with a response message and status.
 */
@SuppressWarnings("unchecked")
public String exec(final String service, final String action,
    final String callbackId, final String jsonArgs,
    final boolean async)

您还需要注册插件。为此,您可以在自定义javascript库的底部添加注册代码。

在下面的示例中,作者定义了一个javascript BarcodeScanner类,并使用addConstructor方法对其进行注册。

在addConstructor中执行两个步骤:

  1. 在javascript中创建BarcodeScanner的新实例并进行注册。这可以在javascript中作为window.plugins.barcodeScanner访问

  2. 用服务名称注册自定义插件类。该服务名称作为第一个参数传递给PhoneGap.exec,以便PhoneGap可以实例化Java插件类并在其上调用execute()方法。

样本注册码:

PhoneGap.addConstructor(function() {
    /* The following registers an instance of BarcodeScanner in window.plugins.barcodeScanner */
    PhoneGap.addPlugin('barcodeScanner', new BarcodeScanner());

    /* The following associates a service name BarcodeScanner with a class com.beetight.barcodescanner.BarcodeScanner */
    /* The service name is the first argument passed into PhoneGap.exec */
    PluginManager.addService("BarcodeScanner","com.beetight.barcodescanner.BarcodeScanner");
});

此样本适用于什么版本的phonegap?我认为您是在2.0以下。对?
Anas Azeem 2013年

6

一个简单的形式:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    super.init(); 
    super.appView.getSettings().setJavaScriptEnabled(true);
    super.appView.addJavascriptInterface(this, "MyCls");
    super.loadUrl("file:///android_asset/www/login.html");
}

5

如果有人使用上面的代码获取了nullPointer异常,请先执行super.oncreate(),然后再执行super..init()

super.onCreate(savedInstanceState);
super.init();

我在这里找到此解决方案:Phonegap Google Group

非常感谢@ zorglub76提供的解决方案。...


0

通过覆盖Android本机代码中的JavaScript提示功能,可以实现从JavaScript到本机的通信,并且传递的消息与iOS中使用的消息非常相似。我们曾经使用WebView.addJavascriptInterface将Java对象直接添加到JavaScript沙箱,但这导致某些设备在Android 2.3下崩溃。要从本机调用JavaScript,我们目前使用WebView.loadUrl(“ javascript:...”),但这存在一些问题,因此我们很快将转向轮询通过长期XHR连接调用本地HTTP服务器的Java消息队列。

这里的描述

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.