83

My app is using JSoup to download the HTML of a message board page (let's say in this case it is a page containing the posts of a given thread). I'd like to take this HTML, strip out unwanted items, and apply custom CSS to style it to be 'mobile' in a WebView.

Should I inject the styles into the HTML as I process it (since I will be processing it anyway) or is there a good way to add a CSS file to my app's assets and simply refer to it. I figure the latter would be ideal, but unsure how to go about it.

I see hints in WebView's loadDataWithBaseURL that you can refer to local assets, but not sure how to utilize it.

thedude19
  • 2,643
  • 5
  • 34
  • 43

7 Answers7

135

You could use WebView.loadDataWithBaseURL

htmlData = "<link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\" />" + htmlData;
// lets assume we have /assets/style.css file
webView.loadDataWithBaseURL("file:///android_asset/", htmlData, "text/html", "UTF-8", null);

And only after that WebView will be able to find and use css-files from the assets directory.

ps And, yes, if you load your html-file form the assets folder, you don't need to specify a base url.

Community
  • 1
  • 1
unorsk
  • 9,371
  • 10
  • 36
  • 42
  • 10
    Thanks! That was just what I needed. (Incidentally, you can use single quotes for the attributes in the inline HTML instead of double-quotes; that way you won't need to backslash them. Always looks a bit tidier to me...) – Matt Gibson Jan 06 '12 at 17:57
  • 2
    Nice. I would put the PS as the direct answer: If you load your html file with WebView.loadUrl("file:///android_asset/fname.html"); you can simply use relative urls within it. – fortboise Jan 31 '14 at 23:19
  • 2
    How can we use the loadDataWithBaseURL() if the stylesheet is in file storage? can we use 'data/data/etc/"? – Yasir May 08 '14 at 01:22
  • 1
    @Yasir, it works even if your `style.css` file is saved away in the the android file storage. You just need to make sure that `baseUrl` is perfect and matches the `css` files relative path. – Sakiboy Apr 13 '16 at 20:53
  • Thank you @AndresD. – anup Sep 20 '16 at 09:21
  • 2
    If your files are the raw folder and not in assets ([which](http://stackoverflow.com/a/43663133/3918479) gives you Android Localization), the base URL would be "file:///android_res/raw/" – Sebastian May 03 '17 at 08:38
  • How to this by avoiding the reload of the already loaded html? I have an HTML loaded from the server and I also try to load another local CSS file, but it seems the html is gone afterward. – X-HuMan May 30 '17 at 16:31
  • Good job. But what if I want to load css from another module location? may it is impossible so can i pass the style.css class it self to module? – Mahdi Apr 10 '18 at 11:56
  • I think this doesn't work with dynamic JS generated webpages, at least it doesn't for me. – c0dehunter Jun 16 '18 at 20:01
  • What if you want to load css and js from an external server? – Mike6679 Mar 15 '21 at 01:18
37

I assume that your style-sheet "style.css" is already located in the assets-folder

  1. load the web-page with jsoup:

    doc = Jsoup.connect("http://....").get();
    
  2. remove links to external style-sheets:

    // remove links to external style-sheets
    doc.head().getElementsByTag("link").remove();
    
  3. set link to local style-sheet:

    // set link to local stylesheet
    // <link rel="stylesheet" type="text/css" href="style.css" />
    doc.head().appendElement("link").attr("rel", "stylesheet").attr("type", "text/css").attr("href", "style.css");
    
  4. make string from jsoup-doc/web-page:

    String htmldata = doc.outerHtml();
    
  5. display web-page in webview:

    WebView webview = new WebView(this);
    setContentView(webview);
    webview.loadDataWithBaseURL("file:///android_asset/.", htmlData, "text/html", "UTF-8", null);
    
Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Robert
  • 371
  • 3
  • 2
  • nice practical solution, do not forget to not to use that in UI (Main) thread. – Ata Iravani Feb 15 '17 at 07:02
  • I want to access style.css from another module. If this is impossible, is there another way to load style as string then pass to library module class? – Mahdi Apr 10 '18 at 11:59
22

here is the solution

Put your html and css in your /assets/ folder, then load the html file like so:

    WebView wv = new WebView(this);

    wv.loadUrl("file:///android_asset/yourHtml.html");

then in your html you can reference your css in the usual way

<link rel="stylesheet" type="text/css" href="main.css" />
longhairedsi
  • 3,133
  • 2
  • 28
  • 28
9

It's as simple as is:

WebView webview = (WebView) findViewById(R.id.webview);
webview.loadUrl("file:///android_asset/some.html");

And your some.html needs to contain something like:

<link rel="stylesheet" type="text/css" href="style.css" />
Chadwick
  • 12,555
  • 7
  • 49
  • 66
egore911
  • 438
  • 3
  • 9
2

If you have your CSS in the internal file storage you can use

//Get a reference to your webview
WebView web = (WebView)findViewById(R.id.webby);

// Prepare some html, it is formated with css loaded from the file style.css
String webContent = "<!DOCTYPE html><html><head><meta charset=\"UTF-8\"><link rel=\"stylesheet\" href=\"style.css\"></head>"
                      + "<body><div class=\"running\">I am a text rendered with INDIGO</div></body></html>";

//get and format the path pointing to the internal storage
String internalFilePath = "file://" + getFilesDir().getAbsolutePath() + "/";

//load the html with the baseURL, all files relative to the baseURL will be found 
web.loadDataWithBaseURL(internalFilePath, webContent, "text/html", "UTF-8", "");
lejonl
  • 1,453
  • 15
  • 20
1

Is it possible to have all the content rendered in-page, in a given div? You could then reset the css based on the id, and work on from there.

Say you give your div id="ocon"

In your css, have a definition like:

#ocon *{background:none;padding:0;etc,etc,}

and you can set values to clear all css from applying to the content. After that, you can just use

#ocon ul{}

or whatever, further down the stylesheet, to apply new styles to the content.

Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
daveyfaherty
  • 4,585
  • 2
  • 27
  • 42
0

You can Use Online Css link To set Style over existing content.

For That you have to load data in webview and enable JavaScript Support.

See Below Code:

   WebSettings webSettings=web_desc.getSettings();
    webSettings.setJavaScriptEnabled(true);
    webSettings.setDefaultTextEncodingName("utf-8");
    webSettings.setTextZoom(55);
    StringBuilder sb = new StringBuilder();
    sb.append("<HTML><HEAD><LINK href=\" http://yourStyleshitDomain.com/css/mbl-view-content.css\" type=\"text/css\" rel=\"stylesheet\"/></HEAD><body>");
    sb.append(currentHomeContent.getDescription());
    sb.append("</body></HTML>");
    currentWebView.loadDataWithBaseURL("file:///android_asset/", sb.toString(), "text/html", "utf-8", null);

Here Use StringBuilder to append String for Style.

sb.append("<HTML><HEAD><LINK href=\" http://yourStyleshitDomain.com/css/mbl-view-content.css\" type=\"text/css\" rel=\"stylesheet\"/></HEAD><body>");
sb.append(currentHomeContent.getDescription());
Nimesh Patel
  • 1,394
  • 13
  • 26