Steven Wexler
Steven Wexler

Reputation: 17279

Invoke Cordova callback from remote process

Is it possible to invoke a javascript callback with cordova from a remote process?

Plugin.xml:

<service android:name="MyLocationListeningService" android:process=":remote" />

MyLocationService.java:

public MyLocationListeningService extends Service implements LocationListener {
    public void onLocationChanged(Location location) {
        //invoke a javascript callback with cordova
    }
}

Upvotes: 1

Views: 289

Answers (1)

Steven Wexler
Steven Wexler

Reputation: 17279

I believe I found my own answer. No you cannot invoke a javascript callback with Cordova from a remote process. To invoke a callback you'll need to keep the CallbackContext. The CallbackContext is only provided via CordovaPlugin.execute which is only invoked on the "main" application process (i.e. the process the webview runs in).

However, you can communicate between Processes in native android code. So you can invoke a callback on the original process as prompted by a remote process.

There are many ways to communicate between processes in Android. One is to broadcast an action for a receiver that runs in the original process.

AndroidMaifest.xml

<service android:name="MyLocationListeningService" android:process=":remote" />
<receiver android:enabled="true" android:exported="true" android:label="MyReceiver" android:name="my.package.MyReceiver">
  <intent-filter>
    <action android:name="Success" />
  </intent-filter>
</receiver>

Plugin

public class MyPlugin extends CordovaPlugin {

  public static CallbackContext myCallbackContext;

  public boolean execute(String action, JSONArray data, final CallbackContext callbackContext) {

    if ("SaveCallbackContext".equalsIgnoreCase(action)) {
      myCallbackContext = callbackContext;
      //Note: we must return true so Cordova doesn't invoke the error
      //callback from the provided callbackContext.
      return true;
    }
  }
}

Receiver (executed in same process as plugin)

public class MyReceiver extends BroadcastReceiver {

  @Override
  public void onReceive(Context context, Intent intent) {
    if ("Success".equals(intent.getAction()) {
      MyPlugin.callbackContext.success();
    }
  }

}

Services (executed in different process from plugin)

public MyLocationListeningService extends Service implements LocationListener {
    public void onLocationChanged(Location location) {
        Intent i = new Intent(this.getApplicationContext(), MyReceiver.class);
        i.setAction("Success");
        this.getApplicationContext().sendBroadcast(i);
    }
}

Note: This answer doesn't account for the case when the original process has been terminated.

Also, you may be interested in Keep callback context in PhoneGap plugin? if you want to invoke your callback more than once.

And you'll be interested in http://docs.phonegap.com/en/4.0.0/guide_platforms_android_plugin.md.html#Android%20Plugins if your callback effects the UI.

Upvotes: 1

Related Questions