2012-05-26 12 views
5

Dobrze, więc muszę podać trochę tła. Najpierw używam jquery-mobile z PhoneGap 1.7. Mam kodowany bardzo prosty serwer Java, który używa obiektu ServerSocket. Na telefonie z systemem Android łączę się z serwerem, a serwer wysyła dane przez gniazdo. Ta część działa.Android PhoneGap 1.7 wywoływanie funkcji javascript

Część, z którą utknąłem, polega na tym, że zamierzam przesłać dane przez to gniazdo, które będą wymagały aktualizacji interfejsu użytkownika jQuery po otrzymaniu danych.


Odpowiedź: Simon był ogromny pomoc i wyobraziłem go z jego pomocy i po this tutorial

część, która naprawdę uderza mnie było to, że wątek zrodził we wtyczce samego PhoneGap. Kiedy zdałem sobie z tego sprawę, wszystko się ułożyło. Jednak dla każdego zainteresowanego tutaj jest kod. Należy pamiętać, że dużo wziąłem z samouczka. Dodałem także bardzo prosty serwer Java, który stworzyłem, aby przetestować tę koncepcję. Pomyślałem, że może to pomoże komuś w przyszłości. Pamiętajcie, to jest po prostu dowód koncepcji.

muszę zreorganizować tej wtyczki, aby spełnić swoje rzeczywiste potrzeby:

Android aktywny: import 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 Plugin:

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

Proszę spojrzeć na to. http://stackoverflow.com/questions/7947559/calling-javascript-from-eclipse-for-phonegap –

Odpowiedz

7

Robisz ten sposób ciężko na siebie. Jeśli użyjesz wtyczki PhoneGap, będziesz mógł zapisać identyfikator wywołania zwrotnego początkowego wywołania JavaScript, a następnie odesłać PluginResult, który nazywasz result.setKeepCallback (true) i gdzie status PluginResult.Status.NO_RESULT.

Następnie, gdy tylko uzyskasz i aktualizujesz stronę Java, utworzysz nowy PluginResult. Ustaw status na OK, dane na wszystko, co chcesz wysłać, i oczywiście przed zwróceniem go setKeepCallback (true). Następnie wywołaj this.success (callbackId, result), a strona JS otrzyma ciągłe aktualizacje.

+0

To brzmi interesująco. Poświęcę na to czas. Jeśli umieszczę początkowe wywołanie funkcji w detektorze zdarzeń dla urządzenia gotowego, to rozwiąże to problem, upewniając się, że urządzenie jest gotowe przed ustanowieniem połączeń gniazda. Zastanawiam się jednak co do NO_RESULT. Początkowe nie przyniosą żadnych rezultatów i myślę, że ma to sens, ale później, kiedy faktycznie wykonuję operacje perforowania, używam Status.OK. Czy to nie zaprzestałoby dalszego korzystania z tej funkcji? Czy jest to cały punkt callbackid? to by nie przeszkodziło w wykonaniu innych operacji JS? – Rakshasas

+0

Nie, nie uniemożliwi to wykonywania innych operacji JS. Żądanie jest asynchroniczne, więc nie blokuje wątku UI w JS. Tak długo, jak ustawisz KeepCallback (true), zanim zwrócisz PluginResult, strona JavaScript nie usunie wywołania zwrotnego. Zaufaj mi, tak działa akcelerometr i stan sieci w głównym kodzie Android PhoneGap. –

+0

Dziękujemy!Początkowo nie rozumiałem, ale między tym, co powiedziałeś powyżej, innym [post tutaj na stackoverflow] (http://stackoverflow.com/a/7849762/865868) przez ciebie i ten [tutorial] (http: // www .speakingcode.com/2012/05/29/call-native-android-java-code-from-html5javascript-using-phonegap-plugins-and-implementac-async-callbacks /) Rozgryzłem to. Dziękuję bardzo! – Rakshasas

Powiązane problemy