web-dev-qa-db-ja.com

Androidバックグラウンドサービスでcordovaプラグインを実行するには?

cordova で開発されたモバイルアプリケーションに取り組んでいます。オープンソケット接続のようないくつかの作業を実行するバックグラウンドサービスを実装し、ローカルデータベースとリモートデータベースを同期させ、新しいリモートプッシュなどについてユーザーに通知したいと考えています。ポイントは、私はこのコードをjavascriptで実装していますが、バックグラウンドで実行したいということです。

コルドバのバックグラウンドサービスプラグインをインターネットで検索しました。

バックグラウンドサービスに関するいくつかのトピックをAndroidで読みました。これらは私が見つけた便利なものです:

そこで、バックグラウンドでjavascriptコードを実行するためのcordovaプラグイン(主にAndroid)の作成を開始しました。バックグラウンドサービスからjavascriptを実行するwebviewを作成しました。これは、通常のjavascriptを実行すると正常に機能しますが、cordovaプラグインjsに関しては、たとえばデバイスdevice.uuidnullを与えます。

これは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);

     }

Updatelogcatにエラーはありません。だから私は画面上にデバイスオブジェクトを書き込もうとしましたが、それは私が得るものです:

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

そして、これが結果です:

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

標準のwebViewcordovaWebViewに置き換えようとしましたが、同じ結果が得られます。

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

この問題に関するヘルプはありますか?

24
mehsen

標準のWebViewではなく、埋め込みCordova WebViewを使用する必要があります。 Cordovaプラグインを処理するための標準WebViewはセットアップされておらず、デバイス情報はプラグインです。

ウェブビューの埋め込みに関するCordovaドキュメント を参照してください。

4
Jan Misker

WebViewsはバックグラウンドサービスからjavascriptを実行できません。

代わりにネイティブコードを使用することをお勧めします。しかし、javascriptを使用する必要がある場合は、このライブラリを試してみます

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

最初にスクリプトの内容を文字列にロードしてから、engine.eval()メソッドを実行します。

例(アセットから「test.js」を実行):

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

注意!eval関数は、一度に実行されるjavascript関数のみを想定し、この関数の値を返します。

2
Richard

WebViewでCordovaプラグインをバックグラウンドサービスとして使用するために、CordovaInterfaceを実装するクラスを作成しました。ここに例があります

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

}

コルドバの初期化中のエラーを防ぐために、onJsAlertメソッドをオーバーライドしました。時間があれば、もっと良い方法を見つけたかもしれません。

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

}

使い方:

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