2012-05-26 15 views
5

Tamam, biraz arka plan vermem gerekiyor. Önce PhoneGap 1.7 ile jquery-mobile kullanıyorum. ServerSocket nesnesini kullanan çok basit bir Java sunucusunu kodluyorum. Android telefonda sunucuya bağlanıyorum ve bunu yaparak sunucu veriyi soket üzerinden gönderiyor. Bu bölüm çalışıyor.Android PhoneGap 1.7 javascript işlevini çağırıyor

Sıkıştığım bölüm, veriyi aldıktan sonra jQuery mobil UI'nin güncellenmesini gerektiren bu soket üzerinden veri göndermeyi planlamamdır.


Cevap: Simon büyük yardımı oldu ve ben onun yardım ve this tutorial

gerçekten beni PhoneGap eklentisi kendisi içinde yaratılacak dişe sahip olduğu isabet parçası aşağıdaki ile bunu anladım. Bunu farkettiğimde, her şey yerine oturdu. Ancak, burada ilgilenen herkes için kod. Unutmayın, dersten çok aldım. Bu konsepti test etmek için oluşturduğum çok basit Java sunucusunu da ekledim. Belki de bunun gelecekte birilerine yardım edeceğini düşündüm. Sadece hatırla, bu temelde kavramın bir kanıtıdır.

benim gerçek ihtiyaçlarını karşılamak için bu eklentiyi yenilemek gerekir:

Android Aktivite: ithalat 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 Eklenti:

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

Lütfen buna bir göz atın. http://stackoverflow.com/questions/7947559/calling-javascript-from-eclipse-for-phonegap –

cevap

7

Kendine bu kadar katı bu şekilde yapıyoruz. Bir PhoneGap Plugin kullanırsanız, ilk JavaScript çağrısının geri arama kimliğini kaydedebilir, daha sonra result.setKeepCallback (true) ve PluginResult.Status.NO_RESULT durumunun bulunduğu bir PluginResult geri gönderebilirsiniz.

Ardından Java tarafına her gelip güncellediğinizde yeni bir PluginResult yaratırsınız. Durumu OK (Tamam) olarak, göndermek istediğiniz her şeye ve elbette setKeepCallback (true) vermeden önce verin. Ardından this.success (callbackId, sonuç) çağrısı yapın ve JS tarafınız sürekli güncellemeler alacak.

+0

Bu ilginç görünüyor. Üzerinde zaman harcayacağım. İlk işlev çağrısını, aygıtın soket bağlantıları kurulmadan önce hazır olduğundan emin olma sorununu çözecek bir olay dinleyicisine yerleştirirseniz. Yine de NO_RESULT hakkında merak ediyorum. İlkinin hiçbir sonucu olmayacak, ve bunun mantıklı olduğunu düşünüyorum, ancak daha sonra aslında eylemler gerçekleştirdiğimde Status.OK'u kullanacağım. Bu işlevin daha fazla kullanılmasını istemez miydi? Yoksa o çağıran bütün nokta bu mu? Bu, diğer JS işlemlerinin gerçekleştirmesini engelleyemez miydi? – Rakshasas

+0

Hayır, diğer JS işlemlerinin gerçekleştirilmesini engellemez. İstek, eşzamansızdır, bu nedenle JS'deki UI iş parçacığını engellemez. Ayrıca, PluginResult'u döndürmeden önceKeepCallback (true) değerini ayarladığınız sürece, JavaScript tarafı geri aramayı temizlemez. Güven bana, bu yüzden Accelerometer ve Network Status temel PhoneGap Android kodunda çalışır. –

+0

Teşekkürler!İlk başta tam olarak anlayamadım ama yukarıda söylediğin şey arasında, başka bir [burayı stackoverflow'ta yayınla] (http://stackoverflow.com/a/7849762/865868) sizin ve bu [eğitici] (http: // www) .speakingcode.com/2012/05/29/call-native-android-java-code-from-html5javascript kullanarak-phonegap-eklentileri-ve-araç-async-callbacks /) Ben bunu anladım. Çok teşekkür ederim! – Rakshasas

İlgili konular