2011-10-24 54 views
8

我試圖做出的PhoneGap(安卓)的一個插件,可以讓我的JavaScript從服務發送和接收消息/一個Android的服務回報消息。 我確切的問題是,因爲消息返回異步,我不能發送PluginResult到插件的執行功能。如何獲得從PhoneGap的插件

這是插件代碼:

public class ServiceClient_plugin extends Plugin { 
    Messenger messenger_service=null; 
    boolean connected_to_service=false; 
    final Messenger messenger_receive = new Messenger(new IncomingHandler()); 

    @Override 
    public PluginResult execute(String action, JSONArray data, String callbackId) { 
     PluginResult result = null; 

     try { 
      if (action.toUpperCase().equals("CONNECT")) { 
       result = ConnectService(); 
      } else if (action.toUpperCase().equals("DISCONNECT")) { 
       result = DisconnectService(); 
      } else if (action.toUpperCase().equals("IS_CONNECTED")) { 
       result = new PluginResult(Status.OK,connected_to_service); 
      } else if (action.toUpperCase().equals("COMMAND")) { 
       sendMSG (data.getString(0)); 
       result = new PluginResult(Status.OK); 
      } else { 
       result = new PluginResult(Status.INVALID_ACTION); 
      } 
     } catch(JSONException e) { 
      result= new PluginResult(PluginResult.Status.JSON_EXCEPTION); 
     } 
     return result; 
    } 

    private PluginResult ConnectService() { 
     doBindService(); 
     return new PluginResult(Status.OK); 
    } 
    private PluginResult DisconnectService() { 
     doUnbindService(); 
     return new PluginResult(Status.OK); 
    } 

    class IncomingHandler extends Handler { 
    @Override 
    public void handleMessage(Message msg) { 
     switch (msg.what) { 
      case MoMe_Service.MSG_COMMAND: 
       Log.i("CLIENT","Received from service: " + msg.getData().getString("MSG")); 
       break; 
      default: 
       super.handleMessage(msg); 
     } 
    } 
} 

private ServiceConnection service_connection = new ServiceConnection() { 
    public void onServiceConnected(ComponentName className, IBinder service) { 
     messenger_service = new Messenger(service); 
     connected_to_service=true; 
     try { 
      Message msg = Message.obtain(null, My_Service.MSG_REGISTERED); 
      msg.replyTo = messenger_receive; 
      messenger_service.send(msg); 
     } catch (RemoteException e) { 
      // In this case the service has crashed before we could even 
      // do anything with it; we can count on soon being 
      // disconnected (and then reconnected if it can be restarted) 
      // so there is no need to do anything here. 
     } 

    } 

    public void onServiceDisconnected(ComponentName className) { 
     // This is called when the connection with the service has been 
     // unexpectedly disconnected -- that is, its process crashed. 
     messenger_service = null; 
     connected_to_service=false; 
    } 
};  

private void doBindService() { 
    // Establish a connection with the service. We use an explicit 
    // class name because there is no reason to be able to let other 
    // applications replace our component. 
    this.ctx.bindService(new Intent(this.ctx, My_Service.class), service_connection, Context.BIND_AUTO_CREATE); 
} 

private void doUnbindService() { 
    if (connected_to_service) { 
     if (messenger_service != null) { 
      try { 
       Message msg = Message.obtain(null, My_Service.MSG_UNREGISTERED); 
       msg.replyTo = messenger_receive; 
       messenger_service.send(msg); 
      } catch (RemoteException e) { 
       // There is nothing special we need to do if the service 
       // has crashed. 
      } 
     } 

     // Detach our existing connection. 
     this.ctx.unbindService(service_connection); 
     connected_to_service = false; 
    } 
} 

private void sendMSG (String message) { 
    try { 
     Message msg=Message.obtain(null, My_Service.MSG_COMMAND); 
     Bundle msg_bundle=new Bundle(); 
     msg_bundle.putString("MSG", message); 
     msg.setData(msg_bundle); 
     messenger_service.send(msg); 
    } catch (RemoteException e) { 
     doUnbindService(); 
    } 
} 

} 

從這個插件的真正的麻煩自帶的這部分代碼,它處理返回的消息和插件回報(肚裏的JavaScript):

@Override 
    public PluginResult execute(String action, JSONArray data, String callbackId) { 
     PluginResult result = null; 

     try { 
      result = new PluginResult(Status.ok); 
      } 
     } catch(JSONException e) { 
      result= new PluginResult(PluginResult.Status.JSON_EXCEPTION); 
     } 
     return result; 
    } 

    class IncomingHandler extends Handler { 
    @Override 
    public void handleMessage(Message msg) { 
     switch (msg.what) { 
      case MoMe_Service.MSG_COMMAND: 
       msg.getData().getString("MSG")); // THIS IS THE DATA I NEED RETURNED 
       break; 
      default: 
       super.handleMessage(msg); 
     } 
     } 
    } 

我能想到的唯一的解決辦法,是存儲數據庫或一個變量的響應和具有的JavaScript做的setInterval繼續檢查更改。但是我不太喜歡這個解決方案。我想使用某種回調函數讓JavaScript知道消息已經返回,但我不知道如何。我將不勝感激任何幫助和想法。

謝謝 弗拉德

回答

6

callbackId這可能是一個遲到的答案,但我開始使用科爾多瓦插件大約5個月ag o我剛剛看到你的問題。既然你沒有選擇正確的答案,我想回答你的問題。

假設你有異步進程,並且你有一個監聽器和方法,成功和失敗,我們稱之爲onSuccess()onFail()。只要您發送真正與pluginResult.setKeepCallback(true),該過程將繼續未完成的,所以你可以以後再發送,當你與後臺進程做了你的插件結果數據。下面是一個例子。

@Override 
public boolean execute(String action, JSONArray data, String callbackId) throws JSONException { 
     if (action.equals("start")) { 

       start(); 
     } else { 
      PluginResult pluginResult = new PluginResult(PluginResult.Status.INVALID_ACTION); 
      callbackContext.sendPluginResult(pluginResult); 
      return false; 
     } 
} 


    private boolean start() throws JSONException { 

     MyClass.startProcess(new MyInterface() { 

      @Override 
      public void onSuccess(String data) { 

       PluginResult result = new PluginResult(PluginResult.Status.OK, data); 
       result.setKeepCallback(false); 
       callbackContext.sendPluginResult(result); 
      } 

      @Override 
      public void onFail() { 

       PluginResult result = new PluginResult(PluginResult.Status.ERROR); 
       result.setKeepCallback(false); 
       callbackContext.sendPluginResult(result); 
      } 

     }); 

    PluginResult.Status status = PluginResult.Status.NO_RESULT; 

    PluginResult pluginResult = new PluginResult(status); 
    pluginResult.setKeepCallback(true); 
    callbackContext.sendPluginResult(pluginResult); 
    return true; 

    } 
1

通用的解決這個問題是有服務店的響應到永久存儲(如數據庫),然後把火關廣播意圖。然後,只需在您的ServiceClient_plugin類的BroadcastReciever中監聽廣播。這樣你就不必保持輪詢,看看數據是否已經到達。

+0

感謝您的快速回復,您的BroadcastReciever答案引導我到github.com上的一些示例插件,我實際上找到了我在那裏尋找的東西。 –

4

回答我的問題,實際上在該PluginResult對象和成功的方法。 我發現一個插件,不得不面對同樣的問題,爲了工作,並從這個代碼我能找出我的answer.This是onPhoneStatusChange插件,它可以發現here

奧祕在於這些行:

PluginResult res = new PluginResult(PluginResult.Status.OK, obj); 
res.setKeepCallback(true); 
success(res, callbackId); 
1

可以使用success()功能像這樣送PluginResult

public PluginResult execute(String action, JSONArray data, String callbackId) {} 
private BroadcastReceiver Wifi_Receiver = new BroadcastReceiver() { 
    @Override 
    public void onReceive(Context context, Intent intent) { 
     MyClass.this.success(new PluginResult(PluginResult.Status.OK,"count"+count),callback); 
    } 
} 

這裏callback是​​功能