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.
Le meilleur que je pense est dossier rouge mais c'est juste pour Android et il ne me permet pas d'écrire du javascript pour être exécuté en arrière-plan. Mais juste d'échanger json entre Java et javascript.
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?
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.
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.
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);