How to create an XWalkView within a service?
Asked Answered
W

2

8

I am working towards replacing the native webview in our Android app with Crosswalk's implementation.

We have been able to get most of the functionality of the app working but creating an XWalkView within a service is still an issue we are trying to get past. Creating a Webview is not an issue but an XWalkView requires an activity context to be used. If anyone here has run across this problem and knows of a possible solution or work-around, I would appreciate it greatly. Thanks, and if you need any other information please ask away.

Whicker answered 6/1, 2016 at 22:40 Comment(2)
are you working on android studio or eclipse? and where exactly is the problem since using XWalkView is very simple and similar to WebView, are you having trouble with the configuration? embedding stuff? specific html5 snippets?Gauvin
I have XWalkView working correctly in an Activity. However, using it within a Service is where I am having trouble since there is no Activity to pass to the constructor.Whicker
A
3

From butelo in GitHub:

So, what is crosswalk and why do I care? Take a look at the website: https://crosswalk-project.org/

CrossWalk is a HTML5 runtime, you can use it to create HTML5 applications with 'native features' You can use CrossWalk to create HTML5-only applications for Android (x86 and arm architectures) and Tizen but you can also use CrossWalk as a View within an android project.

This means you can replace Android WebView with XWalkView and get some extra features like:

-WebGl

-WebRTC

-WebAudio

http://software.intel.com/en-us/html5/articles/crosswalk-application-runtime

How do I embed a CrossWalk WebView, from now on a XWalkView, inside an Android application to have all this goodies on my hybrid application (Android Native with html5 features)

First you have to download the runtime:

https://crosswalk-project.org/#documentation/downloads

Download any of the Android(ARM) versions.

Inside the file is everything you need to start working in an html5 application.

For this test we'll need to import the xwalk-core-library project inside our Eclipse

Create a new Android project with a basic Activity link it with the library and put this code in the Activity:

package com.example.xwalkwithlibrary;
import org.xwalk.core.XWalkView;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.widget.LinearLayout;

public class XWalkEmbedLib extends Activity {
    private LinearLayout commentsLayout;
    private XWalkView xWalkWebView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_xwalk_embed_lib);
         commentsLayout=(LinearLayout)findViewById(R.id.principal);
         xWalkWebView = new XWalkView(this, this);
         xWalkWebView.load("file:///android_asset/www/index.html", null);
         commentsLayout.addView(xWalkWebView);
    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.xwalk_embed_lib, menu);
        return true;
    }
}

Put this on your main layout

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".XWalkMain" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />

    <LinearLayout
                android:id="@+id/principal"

        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/textView1"
        android:layout_below="@+id/textView1"
        android:layout_marginLeft="35dp"
        android:layout_marginTop="86dp"
        android:orientation="vertical" >
    </LinearLayout>

</RelativeLayout>

finally inside your /assets/www folder put your html stuff and that's it

Ansate answered 14/1, 2016 at 14:27 Comment(1)
Thanks for the thorough write up. However, I completely understand what you just explained. Our issue is not with creating an XWalkView in normal circumstances but to create one within a service where an Activity may or may not have been created is our problem.Whicker
H
1

I looked for the XWalkView.java code so I can make something useful but it is not published yet. But there is at least a good solution that can work: Create for the first time the XWalkView instance inside an activity. then find a way to store it in a service and reuse that same instance whenever your activity connects to the service (this way, your html and js are not reloaded ;) )

After googling, I understood that the XWalkView instance needed and activity so it registers some life cycle listeners. so when the activity is destroyed for example the XwalkView.onDestroy method is called (so I had to disable it in my case to keep the same instance and reuse it)

Here is My simple example: MainActivity.Java

import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.MutableContextWrapper;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import java.util.logging.Logger;
import org.xwalk.core.XWalkView;


public class MainActivity extends Activity implements ServiceConnection {

    private Logger logger = Logger.getLogger("com.tr");
    private XWalkView view;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        startService(new Intent(this, MyService.class));
        bindService(new Intent(this, MyService.class), this, BIND_AUTO_CREATE);
    }

    @Override
    public void setContentView(View view) {
        final ViewParent parent = view.getParent();
        if (parent != null) {
            ViewGroup group = (ViewGroup) parent;
            group.removeView(view);
        }
        super.setContentView(view);
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
    }

    private boolean bound;

    @Override
    protected void onStop() {
        super.onStop();
        if (bound) {
            unbindService(this);
            bound = false;
        }
    }


    public void onServiceConnected(ComponentName name, IBinder s) {
        bound = true;
        MyService.MyBinder binder = (MyService.MyBinder) s;
        if (binder.getView() != null) {
            view = binder.getView();

            ((MutableContextWrapper) view.getContext()).setBaseContext(this);
            view.onShow();
        } else {
            view = new XWalkView(new MutableContextWrapper(this), this) {
                @Override
                public void onDestroy() {
                    // super.onDestroy();
                    //disable this method to keep an insatce in memory
                }
            };
            view.load("http://10.110.23.198:8080/mdl/templates/android-dot-com/", null);
            binder.setView(view);
        }
        setContentView(view);
    }

    public void onServiceDisconnected(ComponentName name) {

    }

}

The service class

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import org.xwalk.core.XWalkView;

/**
 *
 * @author Ramdane
 */
public class MyService extends Service {

    @Override
    public IBinder onBind(Intent intent) {
        return new MyBinder(this);
    }

    public class MyBinder extends Binder {

        private MyService service;
        private XWalkView view;

        public MyBinder(MyService service) {
            this.service = service;
        }

        public MyBinder() {
        }

        public void setService(MyService service) {
            this.service = service;
        }

        public MyService getService() {
            return service;
        }

        public XWalkView getView() {
            return view;
        }

        public void setView(XWalkView view) {
            this.view = view;
        }

    }


    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return Service.START_STICKY;
    }

}

I hope it will work for you.

Hypothyroidism answered 1/2, 2016 at 20:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.