Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to run cordova plugin in Android background service?

I am working on mobile application developed on cordova . I want to implement a background service that do some work like open socket connection syncronise local database with remote one and notify the users on new remote pushes etc . The point is I have this code implemented in javascript but I want execute it i background.

I searched internet for a cordova background service plugin.

  • katzer/cordova-plugin-background-mode

  • jocull/phonegap-backgroundjs

  • red-folder

    The best one I think is red-folder but it is just for android and it does not let me to write javascript to be executed in background. but just exchange json between java and javascript.

I have read some topics about background service in android these are useful ones I found:

  • create-a-service-on-android-with-phonegap-application
  • simple-android-service-example-code-description-start-stop-service
  • android-using-webview-outside-an-activity-context

So I started writing cordova plugin (primarily on android) to execute the javascript code in background. I created a webview from the background service to execute the javascript from it. This works fine when I execute normal javascript but when it comes to cordova plugins js it fails for example the device device.uuid gives null.

This is the java service code:

      public void onStart(Intent intent, int startId) {       Toast.makeText(this, "My Happy Service Started", Toast.LENGTH_LONG).show();                    createBackGroundView();            super.onStart(intent,startId);     }         public void createBackGroundView(){                    WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);        LayoutParams params = new WindowManager.LayoutParams(                    android.view.ViewGroup.LayoutParams.WRAP_CONTENT,                    android.view.ViewGroup.LayoutParams.WRAP_CONTENT,                    WindowManager.LayoutParams.TYPE_PHONE,                    WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,                    PixelFormat.TRANSLUCENT            );                   params.gravity = Gravity.TOP | Gravity.LEFT;         params.x = 0;         params.y = 0;         params.width = 200;         params.height = 200;                 LinearLayout view = new LinearLayout(this);                     view.setLayoutParams(new RelativeLayout.LayoutParams(                     android.view.ViewGroup.LayoutParams.MATCH_PARENT,                      android.view.ViewGroup.LayoutParams.MATCH_PARENT             ));                     WebView wv = new WebView(this);         wv.setLayoutParams(new LinearLayout.LayoutParams(                     android.view.ViewGroup.LayoutParams.MATCH_PARENT,                     android.view.ViewGroup.LayoutParams.MATCH_PARENT             ));              view.addView(wv);         wv.getSettings().setJavaScriptEnabled(true);         wv.setWebChromeClient(new WebChromeClient());             wv.loadUrl("file:///android_asset/www/background.html");         wv.setWebViewClient(new WebViewClient() {              @Override             public void onReceivedError(final WebView view, int errorCode,                     String description, final String failingUrl) {                 Log.d("Error","loading web view");                 super.onReceivedError(view, errorCode, description, failingUrl);             }         });          windowManager.addView(view, params);         }          

Update There is no error in the logcat. So I tried to write the device object on the screen and thats what I get :

  document.write(JSON.stringify(window.device)) 

And this is the result :

  { available : false,      plaform : null ,      version : null ,      uuid : null ,       cordova : null ,     model : null     } 

I tried to replace the standard webView with cordovaWebView But the same result is given.

       //WebView wv = new WebView(this);  Commented out        CordovaWebView wv = new CordovaWebView(this);     

Any help about this problem ?

like image 687
mehsen Avatar asked Jul 05 '14 09:07

mehsen


2 Answers

You should use an embedded Cordova WebView, not a standard WebView. A standard WebView is not set up to handle Cordova plugins, and the device info is a plugin.

See the Cordova docs on embedding webviews.

like image 51
Jan Misker Avatar answered Sep 29 '22 13:09

Jan Misker


WebViews can not execute javascript from a background service.

I would recommend using native code instead. But if you must use javascript, i would try this library

https://code.google.com/p/jav8/

ScriptEngineManager factory = new ScriptEngineManager(); ScriptEngine engine = factory.getEngineByName("jav8");    try {     engine.eval("print('Hello, world!')");   } catch (ScriptException ex) {       ex.printStackTrace();   }  

First load the contens of your script into a string and then run engine.eval() method.

Example (Run "test.js" from assets):

AssetManager am = context.getAssets(); InputStream is = am.open("test.js"); BufferedReader r = new BufferedReader(new InputStreamReader(is)); StringBuilder total = new StringBuilder(); String line; while ((line = r.readLine()) != null) {     total.append(line); }  ScriptEngineManager factory = new ScriptEngineManager(); ScriptEngine engine = factory.getEngineByName("jav8");    try {     engine.eval(total.toString());   } catch (ScriptException ex) {       ex.printStackTrace();   } 

Notice! The eval function expects only a javascript function to be executed at a time and returns the value of this function.

like image 35
Richard Avatar answered Sep 29 '22 12:09

Richard