2012-05-26 11 views
5

Ok, also muss ich ein wenig Hintergrund geben. Zuerst benutze ich jquery-mobile mit PhoneGap 1.7. Ich habe einen sehr einfachen Java-Server, der das ServerSocket-Objekt verwendet, codiert. Auf dem Android-Telefon stelle ich eine Verbindung zum Server her, und der Server sendet dabei Daten über den Socket. Dieser Teil funktioniert.Android PhoneGap 1.7 Aufruf einer Javascript-Funktion

Der Teil, an dem ich festhalte, ist, dass ich beabsichtige, Daten über diesen Socket zu senden, der erfordert, dass die jquery mobile UI beim Empfang von Daten aktualisiert wird.


Antwort: Simon war eine massive Hilfe und ich dachte, es mit seiner Hilfe und folgenden this tutorial

Der Teil, der wirklich traf ich den Faden in der PhoneGap Plugin selbst hervorgebracht habe. Als ich das erkannte, fiel alles zusammen. Für alle Interessierten ist hier jedoch der Code. Denken Sie daran, ich habe viel aus dem Tutorial genommen. Ich habe auch den sehr einfachen Java-Server, den ich erstellt habe, um dieses Konzept zu testen. Ich dachte, das würde vielleicht in Zukunft jemandem helfen. Denken Sie daran, dies ist im Grunde ein Beweis für das Konzept.

Ich brauche dieses Plugin neu zu beleben meine tatsächlichen Bedürfnisse anzupassen:

Android Aktivität: 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

Bitte sehen Sie sich das an. http://stackoverflow.com/questions/7947559/calling-javascript-from-eclipse-for-phonegap –

Antwort

7

Sie machen auf diese Weise auf sich selbst zu hart. Wenn Sie ein PhoneGap Plugin verwenden, können Sie die Callback-ID des ursprünglichen JavaScript-Aufrufs speichern und dann ein PluginResult zurücksenden, das Sie result.setKeepCallback (true) und den Status PluginResult.Status.NO_RESULT aufrufen.

Dann, wann immer Sie auf der Java-Seite erhalten und aktualisieren, erstellen Sie ein neues PluginResult. Setzen Sie den Status auf OK, die Daten auf das, was Sie senden möchten und natürlich, bevor Sie es zurückgeben setKeepCallback (true). Rufen Sie dann this.success (callbackId, result) auf und Ihre JS-Seite wird fortlaufend aktualisiert.

+0

Das klingt interessant. Ich werde Zeit damit verbringen. Wenn ich den ersten Funktionsaufruf in einen Ereignis-Listener für das Gerät einbereite, wird das Problem gelöst, dass das Gerät bereit ist, bevor die Socket-Verbindungen hergestellt werden. Ich wundere mich über NO_RESULT obwohl. Die Initiale wird keine Ergebnisse haben, und ich denke, das macht Sinn, aber später, wenn ich tatsächlich Aktionen durchführe, soll ich Status.OK verwenden. Würde das nicht aufhören, diese Funktion weiter zu nutzen? Oder ist das der ganze Sinn der Callbackid? das würde andere JS-Operationen nicht davon abhalten, es auszuführen? – Rakshasas

+0

Nein, dies verhindert nicht, dass andere JS-Vorgänge ausgeführt werden. Die Anfrage ist asynchron, sodass der UI-Thread in JS nicht blockiert wird. Solange Sie KeepCallback (true) setzen, bevor Sie das PluginResult zurückgeben, löscht die JavaScript-Seite den Rückruf nicht. Vertrauen Sie mir, so funktionieren Accelerometer und Network Status im Core PhoneGap Android Code. –

+0

Danke!Ich habe zuerst nicht ganz verstanden, aber zwischen dem, was Sie oben gesagt haben, einem anderen [http://stackoverflow.com/a/7849762/865868] von Ihnen und diesem [Tutorial] (http: // www .speakingcode.com/2012/05/29/call-native-android-java-code-from-html5javascript-using-phonegap-plugins-und-implementieren-async-callbacks /) Ich fand es heraus. Ich danke dir sehr! – Rakshasas

Verwandte Themen