2012-05-26 2 views
5

Хорошо, поэтому мне нужно дать немного фона. Сначала я использую jquery-mobile с PhoneGap 1.7. Я закодировал очень простой Java-сервер, который использует объект ServerSocket. На телефоне Android я подключаюсь к серверу, и после этого сервер отправляет данные через сокет. Эта часть работает.Android PhoneGap 1.7, вызывающий функцию javascript

Часть, с которой я застрял, заключается в том, что я намерен отправлять данные по этому сокету, для чего требуется, чтобы мобильный пользовательский интерфейс jquery обновлялся после приема данных.


Ответ: Саймон был массивной помощью, и я понял это с его помощью и следуя this tutorial

Той часть, которая действительно ударила меня были с нитью порождала в самом плагине PhoneGap. Однажды я понял, что все встало на свои места. Тем не менее, для любого заинтересованного здесь кода. Имейте в виду, я много взял из учебника. Я также включил очень простой Java-сервер, который я создал для тестирования этой концепции. Я подумал, может быть, это поможет кому-то в будущем. Просто помните, это в основном доказательство концепции.

мне нужно обновить этот плагин, чтобы удовлетворить свои реальные потребности:

Android активность: импорт org.apache.cordova.DroidGap;

import android.os.Bundle; 

public class ISSAndroidActivity extends DroidGap { 
    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     super.loadUrl("file:///android_asset/www/index.html"); 
    } 
} 

PhoneGap плагин:

import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.net.InetSocketAddress; 
import java.net.Socket; 
import java.net.SocketAddress; 
import java.net.SocketException; 

import org.apache.cordova.api.*; 
import org.apache.cordova.api.PluginResult; 
import org.apache.cordova.api.PluginResult.Status; 
import org.json.JSONArray; 
import org.json.JSONException; 
import org.json.JSONObject; 

import android.util.Log; 

public class InvokeJavaScriptPlugin extends Plugin { 
    public static String PLUGIN_TAG = "InvokeJavaScriptPlugin"; 
    public static String PROCESS_DATA_ACTION = "processData"; 
    private String callBackId = ""; 

    @Override 
    public PluginResult execute(String action, JSONArray args, String callbackId) { 
     PluginResult pluginResult = null; 
     Log.d(PLUGIN_TAG, "Invoking Javascript w\\ NO_RESULT"); 

     if (action.equals(PROCESS_DATA_ACTION)) { 
      this.callBackId = callbackId; 
      startProcessingData(); 
      pluginResult = new PluginResult(Status.NO_RESULT); 
      pluginResult.setKeepCallback(true); 
     } else { 
      pluginResult = new PluginResult(Status.INVALID_ACTION); 
      Log.e(PLUGIN_TAG, "Invalid action : " + action); 
     } 
     return pluginResult; 
    } 

    /** 
    * Spawns a thread that connects to a server, and receives data from it 
    */ 
    private void startProcessingData() { 
     new Thread() { 
      @Override 
      public void run() { 

       // Socket Testing 
       ObjectOutputStream out; 
       ObjectInputStream in; 
       Socket requestSocket = new Socket(); 
       Object inboundObject; 

       SocketAddress ipAddr = new InetSocketAddress("192.168.1.2", 
         2012); 
       try { 
        requestSocket.connect(ipAddr); 

        out = new ObjectOutputStream(
          requestSocket.getOutputStream()); 
        out.flush(); 
        in = new ObjectInputStream(requestSocket.getInputStream()); 

        do { 
         inboundObject = in.readObject(); // Data is received 
                 // here 
         int processedData = ((Number) inboundObject).intValue(); 
         onProcessDataReadSuccess(processedData); 

        } while (requestSocket.isConnected()); 

       } catch (SocketException ex) { 
        Log.d(PLUGIN_TAG, "Connection to Server lost"); 
       } catch (Exception ex) { 
        ex.printStackTrace(); 
       } 
      } 
     }.start(); 
    } 

    /** 
    * Callback method for startProcessingData(). Sends the result up to 
    * javascript layer via Plugin.success()<br> 
    * This method is automatically called asynchronously when processing is 
    * finished. 
    * 
    * @param processedData 
    *   the result of data processing which will be passed back to 
    *   javascript. 
    */ 
    private void onProcessDataReadSuccess(int processedData) { 
     Log.d(PLUGIN_TAG, "Processing data: " + processedData); 
     PluginResult result; 
     try { 
      JSONObject resultJSON = new JSONObject(); 
      resultJSON.put("processedData", processedData); 
      result = new PluginResult(Status.OK, resultJSON); 
     } catch (JSONException jsonEx) { 
      Log.e(PLUGIN_TAG, "Got JSON Exception " + jsonEx.getMessage()); 
      jsonEx.printStackTrace(); 
      result = new PluginResult(Status.JSON_EXCEPTION); 
     } 

     result.setKeepCallback(true); 
     this.success(result, this.callBackId); 
    } 
} 

index.html:

<!DOCTYPE html> 
<html> 
<head> 
<title></title> 
<meta name="viewport" content="width=device-width, initial-scale=1" /> 
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> 
<title>Insert title here</title> 
<link type="text/css" href="css/jquery.mobile-1.1.0.min.css" 
    rel="stylesheet" /> 
</head> 
<script type="text/javascript" charset="utf-8" 
    src="scripts/cordova-1.7.0.js"></script> 
<script type="text/javascript" src="scripts/jquery-1.7.2.min.js"></script> 
<script type="text/javascript" src="scripts/jquery.mobile-1.1.0.min.js"></script> 
<script type="text/javascript" src="scripts/InvokeJavaScript.js"></script> 
<script type="text/javascript" charset="utf-8"> 
    document.addEventListener('deviceready', function() { 
     window.plugins.InvokeJavaScript.processData(function(result) { 
      displayProcessedData(result) 
     }, function(error) { 
      console.log(error) 
     }); 
    }, true); 

    function displayProcessedData(result) { 
     document.getElementById("processedData").innerHTML = result.processedData; 
    } 
</script> 

<body> 
    <div data-role="page"> 
     <div data-role="header" data-position="fixed"> 
      <h1>Demo</h1> 
     </div> 
     <div data-role="content"> 
      Result: 
      <div id="processedData"></div> 
     </div> 
     <div data-role="footer" data-position="fixed"> 
      <div data-role="navbar"></div> 
     </div> 
    </div> 
</body> 
</html> 

Server.java

import java.io.BufferedReader; 
import java.io.ObjectOutputStream; 
import java.net.ServerSocket; 
import java.net.Socket; 

public class ISSServer { 

    private static Socket androidSocket; 
    private static ServerSocket serverSocket; 
    static ObjectOutputStream out; 
    static BufferedReader in; 

    public static void main(String[] args) { 
     System.out.println("Listen Thread: Waiting for connection"); 
     int port_number = 2012; // The default port 

     try { 
      serverSocket = new ServerSocket(port_number); 
      androidSocket = serverSocket.accept(); 

      System.out.println("Connection established"); 

      out = new ObjectOutputStream(androidSocket.getOutputStream()); 
      out.flush(); 
      // in = new BufferedReader(new 
      // InputStreamReader(androidSocket.getInputStream())); 

      out.writeObject(1337); 
      out.flush(); 
      out.reset(); 
      System.out.println("1337 sent"); 
      Thread.sleep(2000); 

      out.writeObject(9999); 
      out.flush(); 
      out.reset(); 
      System.out.println("9999 sent"); 
      Thread.sleep(2000); 

      out.writeObject(1234); 
      out.flush(); 
      out.reset(); 
      System.out.println("1234 sent"); 
      Thread.sleep(2000); 

     } catch (Exception ex) { 
      ex.printStackTrace(); 
     } 
    } 
} 
+0

Пожалуйста, взгляните на это. http://stackoverflow.com/questions/7947559/calling-javascript-from-eclipse-for-phonegap –

ответ

7

Вы делаете так тяжело на себя. Если вы используете плагин PhoneGap, вы сможете сохранить идентификатор обратного вызова исходного вызова JavaScript, а затем отправить обратно PluginResult, который вы вызываете result.setKeepCallback (true) и где статус PluginResult.Status.NO_RESULT.

Затем, когда вы получаете и обновляете на стороне Java, вы создаете новый PluginResult. Установите статус на OK, данные на все, что вы хотите отправить, и, конечно же, перед тем, как вернуть его setKeepCallback (true). Затем вызовите this.success (callbackId, result), и ваша JS-сторона получит непрерывные обновления.

+0

Это звучит интересно. Я собираюсь потратить на это время. Если я поместил начальный вызов функции в прослушиватель событий для готовности устройства, что решит проблему обеспечения готовности устройства до установления соединений сокета. Меня интересует NO_RESULT. Первоначально не будет никаких результатов, и я думаю, что это имеет смысл, но позже, когда я фактически выполняю действия, я должен использовать Status.OK. Разве это не перестало бы использовать эту функцию? Или это весь смысл callbackid? это не помешало бы выполнению других операций JS? – Rakshasas

+0

Нет, это не помешает выполнению других операций JS. Запрос async, поэтому он не будет блокировать поток пользовательского интерфейса в JS. Кроме того, до тех пор, пока вы установитеKeepCallback (true), прежде чем вы вернете PluginResult, сторона JavaScript не очистит обратный вызов. Поверьте мне, это то, как Accelerometer и Network Status работают в основном коде Android PhoneGap. –

+0

Спасибо!Сначала я не совсем понял, но между тем, что вы сказали выше, другой [сообщение здесь, в stackoverflow] (http://stackoverflow.com/a/7849762/865868) от вас и этого [учебника] (http: // www .speakingcode.com/2012/05/29/call-native-android-java-code-from-html5javascript-using-phonegap-plugins-and-реализация-async-callbacks /) Я понял это. Спасибо огромное! – Rakshasas

Смежные вопросы