8

Developing on Android Studio 1.0.1, API 21. Following is the folder structure - enter image description here

It's essentially an AngularJS based app that I want to wrap inside a webview container and run on Android.

My Android side of code is -

 WebView myWebView = (WebView) findViewById(R.id.webview);
 WebSettings webSettings = myWebView.getSettings();
 webSettings.setJavaScriptEnabled(true);
 webSettings.setDomStorageEnabled(true);
 myWebView.setWebChromeClient(new WebChromeClient());

 String filePath = "file:///android_asset/www/index.html";
 myWebView.loadUrl(filePath);

The references in html are all relative -

<script src="lib/jquery.min.js"></script>
<script src="lib/angular.min.js"></script>
<script src="lib/angular-route.min.js"></script>
<script src="lib/bootstrap.min.js"></script>

But interestingly enough, I've searched most places, and I'm not sure where am I going wrong. My references aren't working at all! So I can't access my lib files, my scripts, my css. Also, if I run an external angular web page inside the webview, with the same Java code, it runs perfectly!

Any help is appreciated.

Note : Please don't suggest using Cordova/PhoneGap. It's a project requirement to go native(and I frankly don't understand why, but I'm only a developer who has no say in it).

On a side note : I'm facing the same problem with the iOS webview. References aren't working!


UPDATE

Tried the following things :

Tried loadDataWithBaseURL(), doesn't work.

Tried all possible scenarios for paths. Nothing worked.

Removed all the scripts from the folder and put them at the root level, and modified links to have no paths, simply file names. Still doesn't work. And this is way too weird.

Kazekage Gaara
  • 14,972
  • 14
  • 61
  • 108

5 Answers5

15

I managed to do something similar in the following way:

WebView webView = (WebView) findViewById(R.id.webview);

WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setDomStorageEnabled(true);
webView.setWebChromeClient(new WebChromeClient());

try {
    String html = readAssetFile("www/index.html");
    webView.loadDataWithBaseURL("file:///android_asset/www/", html, "text/html", "UTF-8", null);
} catch (IOException e) {
}

Where 'readAssetFile' is:

private String readAssetFile(String fileName) throws IOException {
    StringBuilder buffer = new StringBuilder();
    InputStream fileInputStream = getAssets().open(fileName);
    BufferedReader bufferReader = new BufferedReader(new InputStreamReader(fileInputStream, "UTF-8"));
    String str;

    while ((str=bufferReader.readLine()) != null) {
        buffer.append(str);
    }
    fileInputStream.close();

    return buffer.toString();
}

Also, my page is a simple one - just to test an image, the angularjs lib and a css stylesheet:

<!DOCTYPE html>
<html>

<head>
<link rel="stylesheet" type="text/css" href="css/mystyle.css">
<script src="libs/angular.min.js"></script>
</head>

<body>

<img src="images/IMG_7765.JPG" alt="De nada" width="200" height="300">

<div ng-app="">

<p>Input something in the input box:</p>
<p>Name: <input type="text" ng-model="name" value="John"></p>
<p ng-bind="name"></p>

</div>

</body>
</html>

Also, my file structure is the following

enter image description here

Hope it helps :)

Spiri
  • 1,283
  • 11
  • 24
  • This should work, seems very logical. But what's funny is that, it doesn't work. I should probably try on Eclipse rather than Android Studio. – Kazekage Gaara Jan 28 '15 at 19:08
  • There has to be something seriously wrong with my dev system, it doesn't work on Eclipse too. – Kazekage Gaara Jan 28 '15 at 19:47
  • Strange (tested on 4.3, 4.4.4 and 5.0 and seems to work ok) - dindn't test with gradle though. The asset html page is shown, right? (only the references don't work) Taught that maybe the assets folder doesn't get into the apk as it should. – Spiri Jan 29 '15 at 09:39
  • Yea. It's really strange. And it's happening for both Android and iOS. What I'm thinking now is to test this on a couple of different machines and see what happens. – Kazekage Gaara Jan 29 '15 at 20:35
  • I finally found out the problem, please see my answer. It was the base tag. I'm awarding you the bounty as your HTML template was what made me realize that the extra thing I have is the base tag. Thanks. – Kazekage Gaara Jan 31 '15 at 22:18
  • You saved my day! Thanks a lot! – flame3 Feb 23 '17 at 07:07
  • the DOM enabled made it work... thank you, my friend. – Zach Bublil Feb 04 '18 at 12:08
4

try putting a forwardslash in front of "lib" in the path of your sources like this (since it is a relative call the browser will complete it for you http://domain/lib/jquery.min.js instead of http://domain.comlib/jquery.min.js).

UPDATE - I believe AngularJS uses the ng-src directive for including external sources:

<script ng-src="/lib/jquery.min.js"></script>
<script ng-src="/lib/angular.min.js"></script>
<script ng-src="/lib/angular-route.min.js"></script>
<script ng-src="/lib/bootstrap.min.js"></script>

Alternatively you could also complete the path yourself if you don't really need the code to be dynamic like this (this is also a quick test to make sure everything is actually working):

<script ng-src="http://domain.com/lib/jquery.min.js"></script>
<script ng-src="http://domain.com/lib/angular.min.js"></script>
<script ng-src="http://domain.com/lib/angular-route.min.js"></script>
<script ng-src="http://domain.com/lib/bootstrap.min.js"></script>
Max Worg
  • 2,932
  • 2
  • 20
  • 35
4

I haven't tried this but put your index.html page into a string and pass it in as data. the baseUrl is then http://domain.com

public void loadDataWithBaseURL (String baseUrl, String data, String mimeType, String encoding, String historyUrl)

Webview with both local and interweb (internet and intranet) resources. You have to use loadDataWithBaseURL and all of the interweb resources have to be http:// or all of the file access has to be file:// resources in anything from the web also have to be specified with http:// that is the links and such in anything that comes from the web can not be //i/image.jpg they have to be http://www.example.com/i/image.jpg. That is web or file system have to be completely qualified.

Below I'm using a local directory in the file system by passing in the complete pathname of a file (it works to get a directory) The html is put into a string. Because I'm using loadDataWithBaseURL I can also access the interweb when it is prefixed by http://

StringBuilder sb = new StringBuilder();
                sb.append("<html><body><div style=\"width:100%; text-align:center; font-size:large;\">");
                sb.append(kmlmo.markeroptions.getTitle());
                sb.append("</div>");

                sb.append("<a href = \"http://www.example.com/link.html\">mylink</a>");

                sb.append(kmlmo.markeroptions.getSnippet());
                sb.append("</body></html>");
                View v = getView();
                if (v != null) {
                    wv = (WebView) v.findViewById(R.id.webView1);
                    if (wv != null) {
                        String localPath = "file://" + kmlmo.path;
                        String temp = sb.toString();
                        wv.loadDataWithBaseURL(localPath, temp, "text/html",
                                "UTF-8", "");
                    }
danny117
  • 5,581
  • 1
  • 26
  • 35
2

After a lot of poking around, and a lot of help from the people who answered, the culprit in my code was the base tag. I removed it and also removed the html5mode thing. So, to sum it up, I removed the following :

 <base href="/">  

and

$locationProvider.html5Mode(true);

And everything started working.

Kazekage Gaara
  • 14,972
  • 14
  • 61
  • 108
0

It's simple :

  1. Add this code in app.module.ts
//in App.module.ts : 

//import these packages  

import { APP_BASE_HREF, LocationStrategy, HashLocationStrategy } from '@angular/common';


// add these packages into providers as below : 

@NgModule({
    imports: 
     [
      .....
     ],
    declarations: 
     [
     ....
     ],
    providers: 
      [
        ....
        { provide: APP_BASE_HREF, useValue: '/' },
        { provide: LocationStrategy, useClass: HashLocationStrategy },
        
        ....
       ]
   ....
   
   })
   
   export class Appmodule{}
  1. remove <base href="/"> from index.html file
  2. run command npm run build
  3. double click the index.html file from dist folder.

Your app will run.

Anmol Jain
  • 336
  • 4
  • 12