I want to dynamically load and interact with SVG image into Android WebView using javascript and HTML5. The below is the html source code
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="obj_idset.js"></script>
<script type="text/javascript" src="global.js"></script>
<script type="text/javascript" src="map_zoom_pan_effects.js"></script>
<script type="text/javascript" src="client-menu_position.js"></script>
<script type="text/javascript" src="client-menu_routing.js"></script>
<script type="text/javascript" src="obj_positionpoint.js"></script>
<script type="text/javascript" src="obj_borderline.js"></script>
<script type="text/javascript" src="obj_borderpoint.js"></script>
<script type="text/javascript" src="obj_edge.js"></script>
<script type="text/javascript" src="obj_polygon.js"></script>
<script type="text/javascript" src="obj_stepmarker.js"></script>
<script type="text/javascript" src="obj_vertex.js"></script>
<script type="text/javascript" src="obj_category.js"></script>
<script type="text/javascript" src="obj_gpsmarker.js"></script>
<script type="text/javascript" src="menu_import.js"></script>
<script type="text/javascript" src="routing.js"></script>
<script type="text/javascript" src="affiliation_match.js"></script>
<script type="text/javascript" src="android.js"></script>
<script type="text/javascript" src="interface.js"></script>
<script type="text/javascript" src="demowalk.js"></script>
<script type="text/javascript" src="convertCoordinates.js"></script>
<script>
$("embed").ready(function() {
// Replaces onload () for initialization may take place only after the DOM has been built completely.
console.log('version 24');
//G.loadMaps(false);
G.init();
G.loadMaps(0);
console.log("???");
});
</script>
</head>
<body>
<div id="location"></div>
<!-- Inside this div the map will be rendered -->
<div id="map_container"></div>
<!-- <div id="page-wrapper">
<h1>Text File Reader</h1>
<div>
Select a text file:
<input type="file" id="fileInput">
</div>
<pre id="fileDisplayArea"><pre>
</div>
-->
<div id="mainmenu">
<p>Set the position</p>
<!-- <button onclick="menu('top');">top</button> -->
<button onclick="Interface.position_setSVG (125,125,0);">Set postion</button>
</div>
</body>
</html>
As above html script, the html web page includes a render SVG map which is dynamically load into element and a "Set position" button as below in desktop Chrome.
Now I want to display the same in Android WebView (all java script files and svg files are placed in Android assests folder). The below is Android code in main Fragment
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
private SvgWebView mWebView;
private Button positionBtn;
private Button destinationBtn;
private Button routingBtn;
private Button clearBtn;
public PlaceholderFragment() {
}
@Override
@SuppressLint({ "JavascriptInterface", "SetJavaScriptEnabled" })
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container,
false);
mWebView = new SvgWebView((WebView) rootView.findViewById(R.id.webView1));
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.getSettings().setBuiltInZoomControls(false);
mWebView.getSettings().setUseWideViewPort(true);
mWebView.getSettings().setSupportZoom(true);
mWebView.getWebView().setInitialScale(0);
mWebView.getWebView().setWebChromeClient(new WebChromeClient());
// http://stackoverflow.com/questions/2378800/clicking-urls-opens-default-browser
mWebView.getWebView().setWebViewClient(new WebViewClient(){
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
});
CustomJavaScriptHandler js = new CustomJavaScriptHandler(getActivity());
mWebView.getWebView().addJavascriptInterface(js, "svgapp");
js.addInstructor(new CustomJavaScriptHandler.JSInstructor() {
@Override
public void jsinstruct(String s) {
String parts[] = s.split(":");
if (parts[0].equals("position")) {
//nodeSelected(Integer.valueOf(parts[1]));
}
}
});
CopyFilesAsyncTask copyTask = new CopyFilesAsyncTask();
copyTask.execute();
positionBtn = (Button) rootView.findViewById(R.id.positionBtn);
positionBtn.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
mWebView.svgPositionBySvg(100.0, 200.0, 0);
}
});
destinationBtn = (Button) rootView.findViewById(R.id.destinationBtn);
routingBtn = (Button) rootView.findViewById(R.id.routingBtn);
clearBtn = (Button) rootView.findViewById(R.id.clearBtn);
return rootView;
}
/* the function is called after copying files from assest folder to external device */
public void copyFinished() {
try {
Toast.makeText(getActivity(), "Copy done", Toast.LENGTH_LONG).show();
String htmlPath = Utils.getSdDir(Utils.SVG_MAP_DATA_EXT_FOLDER).toURI().toURL().toString() + File.separator + Utils.ANDROID_HTML;
// load the android.html
mWebView.loadUrl(htmlPath);
} catch (MalformedURLException e) {
Log.e(TAG, "Error ", e);
}
}
class CopyFilesAsyncTask extends AsyncTask<Void, Void, Void> {
public CopyFilesAsyncTask() {
}
@Override
protected Void doInBackground(Void... arg0) {
AssetManager assetManager = getActivity().getAssets();
copyAssestsToExtDir(assetManager, Utils.SVG_MAP_DATA_ASSEST_FOLDER);
return null;
}
@Override
protected void onPostExecute(Void arg0) {
copyFinished();
}
}
/* copy files in assest to external dir when the application start */
private void copyAssestsToExtDir(AssetManager assetManager, String subfolder) {
String[] files = null;
try {
files = assetManager.list(subfolder);
} catch (IOException e) {
Log.e(TAG, "Failed to get asset file list.", e);
}
for(String filename : files) {
Log.i(TAG, "File: " + filename);
// this is file, hence copy
InputStream instr = null;
OutputStream outstr = null;
try {
instr = assetManager.open(subfolder + File.separator + filename);
File out_dir = Utils.getSdDir(Utils.SVG_MAP_DATA_EXT_FOLDER);
File outFile = new File(out_dir, filename);
outstr = new FileOutputStream(outFile);
byte[] buffer = new byte[1024];
int read;
while ((read = instr.read(buffer)) != -1) {
outstr.write(buffer, 0, read);
}
outstr.flush();
instr.close();
outstr.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
}
The thing is that when running in Android, the WebView does not load svg image into its element. It calls default Android Web Browser to display the svg image as below pictures
As above pictures, the WebView only display the "Set postion" button, it call Android web Browser to display SVG. Hence, I could not interact with loaded SVG because SVG does not include any javascript itself (javascript files are embeded into html file not svg).
Am I missing something? Could anyone give me the solution to solve this problem?