2012-05-26 1 views
5

Ok quindi ho bisogno di dare un po 'di background. Per prima cosa sto usando jquery-mobile con PhoneGap 1.7. Ho codificato un server Java molto semplice che utilizza l'oggetto ServerSocket. Sul telefono Android, mi collego al server, e così facendo il server invia i dati tramite il socket. Questa parte sta funzionando.Android PhoneGap 1.7 chiama una funzione javascript

La parte su cui sono bloccato è che intendo inviare dati su quel socket che richiederà l'interfaccia utente jquery mobile per essere aggiornata alla ricezione dei dati.


Risposta: Simon è stato un aiuto enorme e ho pensato che con il suo aiuto e seguendo this tutorial

La parte che veramente mi ha colpito è stato avere il filo deposto le uova nel plugin PhoneGap stesso. Una volta capito, tutto andò a posto. Tuttavia, per chiunque sia interessato ecco il codice. Tenete a mente, ho preso molto dal tutorial. Ho anche incluso il semplicissimo server Java che ho creato per testare questi concetti. Ho pensato che forse questo avrebbe aiutato qualcuno in futuro. Basta ricordare, questa è fondamentalmente una prova di concetto.

ho bisogno di rinnovare questo plugin per soddisfare le mie esigenze effettive:

Android attività: 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

Si prega di dare un'occhiata a questo. http://stackoverflow.com/questions/7947559/calling-javascript-from-eclipse-for-phonegap –

risposta

7

Si stanno facendo in questo modo al duro con te stesso. Se si utilizza un Plugin PhoneGap, sarà possibile salvare l'ID di callback della chiamata JavaScript iniziale, quindi inviare un PluginResult che si chiama result.setKeepCallback (true) e dove lo stato PluginResult.Status.NO_RESULT.

Quindi ogni volta che ottieni e aggiorni da Java, crei un nuovo PluginResult. Impostare lo stato su OK, i dati su qualunque cosa si voglia inviare e, naturalmente, prima di restituirlo, setKeepCallback (true). Quindi chiama this.success (callbackId, result) e il tuo lato JS riceverà aggiornamenti continui.

+0

Sembra interessante. Ho intenzione di trascorrere del tempo su di esso. Se inserisco la chiamata di funzione iniziale in un listener di eventi per dispositivo pronto, risolverò il problema di verificare che il dispositivo sia pronto prima che vengano stabilite le connessioni socket. Mi chiedo però NO_RESULT. L'iniziale non avrà risultati, e penso che abbia senso, ma più tardi, quando in realtà sto perfezionando le azioni, userò Status.OK. Non smetterebbe di usare ulteriormente quella funzione? O è questo il punto intero del callbackid? questo non impedirebbe ad altre operazioni di JS di eseguirlo? – Rakshasas

+0

No, non impedirà l'esecuzione di altre operazioni JS. La richiesta è asincrona quindi non bloccherà il thread dell'interfaccia utente in JS. Inoltre, se si imposta KeepCallback (true) prima di restituire PluginResult, il lato JavaScript non cancellerà la richiamata. Fidati di me, questo è il modo in cui Accelerometer e Network Status funzionano nel codice core di PhoneGap Android. –

+0

Grazie!All'inizio non ho capito bene, ma tra quello che hai detto sopra, un altro [post qui su StackOverflow] (http://stackoverflow.com/a/7849762/865868) da te e questo [tutorial] (http: // www .speakingcode.com/2012/05/29/call-native-android-java-code-from-html5javascript-using-phonegap-plugins-and-implement-async-callback /) L'ho capito. Grazie mille! – Rakshasas