【问题标题】:Communication between Android Java and Phonegap Javascript?Android Java和Phonegap Javascript之间的通信?
【发布时间】:2011-02-13 05:46:39
【问题描述】:

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

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

【问题讨论】:

    标签: android cordova


    【解决方案1】:

    我终于成功了。

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

      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 页面访问的方法中。 Reference.

    【讨论】:

    • hmm,这个例子很好,但是我在appView上得到了一个空指针异常,它似乎是空的。你在哪里初始化对象?
    • 添加 super.init();像下面提到的@Karfield 为我修复了空指针异常。
    • 干得好!提示:如果您想以相反的方式进行通信(从 Java 到 Javascript),请使用:mGap.sendJavascript("window.myJavascriptFunction('some parameter');");
    • E/Web 控制台(2513):未捕获的类型错误:对象 [object Object] 在 file:///android_asset/www/loginfile.js:142 window.Mycls.sendEmail 处没有方法“sendEmail” (“rea@gmail.com”);在这一行得到错误
    • 我已经为 android 4.2.2 尝试过这段代码,我遇到了一个与 Deepu 类似的问题,即 Uncaught TypeError: Object [object Object] has no method 'getTelephoneNumber' at file:///android_asset/ www/app.js:142 。经过一些调试后,我发现您需要添加@JavascriptInterface 以访问您想要在 4.2.2 以上的 javascript 中访问的任何方法link
    【解决方案2】:

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

    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));
       }
    }
    

    【讨论】:

      【解决方案3】:

      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以下。对吗?
      【解决方案4】:

      更简单的形式:

      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 的解决方案......

        【讨论】:

          【解决方案6】:

          从 JavaScript 到 native 的通信是通过覆盖 Android 原生代码中的 JavaScript 提示函数来实现的,传递的消息很像 iOS 中使用的消息。我们曾经使用 WebView.addJavascriptInterface 将 Java 对象直接添加到 JavaScript 沙箱,但这会导致某些设备在 Android 2.3 上崩溃。为了从本机调用 JavaScript,我们目前使用 WebView.loadUrl(”javascript:...”) 但这有一些问题,所以我们很快就会转向通过长期 XHR 连接来轮询调用本地 HTTP 服务器的 Java 消息队列。

          Description by here

          【讨论】:

            猜你喜欢
            • 2013-10-11
            • 2015-12-10
            • 1970-01-01
            • 2022-07-14
            • 2015-05-24
            • 1970-01-01
            • 2013-10-07
            • 1970-01-01
            相关资源
            最近更新 更多