web-dev-qa-db-fra.com

Comment exécuter le plugin cordova dans Android?

Je travaille sur une application mobile développée sur cordova . Je veux implémenter un service d'arrière-plan qui effectue certains travaux comme la connexion locale de connexion de socket ouverte avec la base de données distante et avertit les utilisateurs des nouvelles poussées à distance, etc. Le fait est que j'ai ce code implémenté en javascript mais je veux l'exécuter en arrière-plan.

J'ai cherché sur Internet un plugin de service d'arrière-plan Cordova.

J'ai lu quelques sujets sur le service d'arrière-plan dans Android ce sont des sujets utiles que j'ai trouvés:

J'ai donc commencé à écrire le plugin cordova (principalement sur Android) pour exécuter le code javascript en arrière-plan. J'ai créé une vue Web à partir du service d'arrière-plan pour exécuter le javascript à partir de celui-ci. Cela fonctionne très bien lorsque j'exécute du javascript normal, mais en ce qui concerne les plugins cordova js, il échoue, par exemple, le périphérique device.uuid donne null.

Voici le code de service Java:

      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);

     }

Mise à jour Il n'y a aucune erreur dans le logcat. J'ai donc essayé d'écrire l'objet périphérique sur l'écran et c'est ce que j'obtiens:

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

Et voici le résultat:

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

J'ai essayé de remplacer la norme webView par cordovaWebView Mais le même résultat est donné.

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

Une aide sur ce problème?

24
mehsen

Vous devez utiliser une Cordova WebView intégrée, et non une WebView standard. Une WebView standard n'est pas configurée pour gérer les plugins Cordova, et les informations sur l'appareil sont un plugin.

Voir les documents Cordova sur l'intégration de vues Web .

4
Jan Misker

WebViews ne peut pas exécuter javascript à partir d'un service d'arrière-plan.

Je recommanderais plutôt d'utiliser du code natif. Mais si vous devez utiliser javascript, j'essaierais cette bibliothèque

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();
  } 

Commencez par charger le contenu de votre script dans une chaîne, puis exécutez la méthode engine.eval().

Exemple (exécutez "test.js" à partir des ressources):

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();
  }

Remarque! La fonction eval ne s'attend à ce qu'une fonction javascript soit exécutée à la fois et renvoie la valeur de cette fonction.

2
Richard

Pour travailler avec les plugins Cordova dans WebView en tant que service d'arrière-plan, j'ai créé une classe qui implémente CordovaInterface. Voici un exemple

 private class CordovaBackground extends Activity implements CordovaInterface {
    private ArrayList pluginEntries = new ArrayList();
    private CordovaPreferences preferences;
    private Context context;
    private Whitelist internalWhitelist;
    private Whitelist externalWhitelist;
    private CordovaWebViewBackground webView;
    protected LinearLayout root;
    private WindowManager serviceWindowManager;
    private final ExecutorService threadPool = Executors.newCachedThreadPool();

    public CordovaBackground(Context context, WindowManager windowManager) {
        attachBaseContext(context);
        this.context = context;
        this.serviceWindowManager = windowManager;
    }

    private void loadConfig() {
        ConfigXmlParser parser = new ConfigXmlParser();
        parser.parse(this);
        preferences = parser.getPreferences();
        internalWhitelist = parser.getInternalWhitelist();
        externalWhitelist = parser.getExternalWhitelist();;
        ArrayList<PluginEntry> allPluginEntries = parser.getPluginEntries();
        String[] backgroundPluginNames = {"File"};//not all plugins you need in service, here is the list of them
        ArrayList<String> backgroundPlugins = new ArrayList<String>(
            Arrays.asList(backgroundPluginNames));
        for (PluginEntry pluginEntry : allPluginEntries) {
            if (backgroundPlugins.contains(pluginEntry.service)) {
                pluginEntries.add(pluginEntry);
            }
        }
    }

    public void loadUrl(String url) {
        init();
        webView.loadUrl(url);
    }

    public void init() {
        loadConfig();
        webView = new CordovaWebViewBackground(context);
        if (webView.pluginManager == null) {
            CordovaWebViewClient webClient = webView.makeWebViewClient(this);
            CordovaChromeClientBackground webChromeClient = webView.makeWebChromeClient(this);
            webView.init(this, webClient, webChromeClient,
                    pluginEntries, internalWhitelist, externalWhitelist, preferences);
        }
    }

    public WindowManager getWindowManager() {
        return serviceWindowManager;
    }

    @Override
    public void startActivityForResult(CordovaPlugin command, Intent intent, int requestCode) {
    }

    @Override
    public void setActivityResultCallback(CordovaPlugin plugin) {
    }

    @Override
    public Activity getActivity() {
        return this;
    }

    @Override
    public Object onMessage(String id, Object data) {
        return null;
    }

    @Override
    public ExecutorService getThreadPool() {
        return threadPool;
    }

    @Override
    public Intent registerReceiver(Android.content.BroadcastReceiver receiver, Android.content.IntentFilter filter) {
        return  getIntent();
    }

    @Override
    public String getPackageName() {
        return context.getPackageName();
    }

}

Pour éviter les erreurs lors de l'initialisation de cordova, j'ai remplacé la méthode onJsAlert. Si vous avez du temps, vous avez peut-être trouvé une meilleure façon.

 private class CordovaWebViewBackground extends CordovaWebView {

    public CordovaWebViewBackground(Context context) {
        super(context);
    }

    public CordovaChromeClientBackground makeWebChromeClient(CordovaInterface cordova) {
        return new CordovaChromeClientBackground(cordova, this);
    }

}

private class CordovaChromeClientBackground extends CordovaChromeClient {

    public CordovaChromeClientBackground(CordovaInterface ctx, CordovaWebView app) {
        super(ctx, app);
    }

    public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
        //super.onJsAlert(view, url, message, result);
        return true;
    }

}

Comment utiliser:

WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
CordovaBackground cordovaBackground = new CordovaBackground(this, wm);
cordovaBackground.setIntent(intent);
String url = "file:///Android_asset/www/test.html";
cordovaBackground.loadUrl(url);
2
CruorVult