Can i use d3.js for creating interactive visualizations inside an android app?
You can easily embed Javascript into an Android app using the WebView component or you can use PhoneGap or a similar platform. Unfortunately, before Android 3.0 the native android browser did not display svg and D3 is based on SVG, so it will not work in the android 2.3 (or below) browser. It does however work in the Firefox browser.
Another option would be to use InfoVis Toolkit in a WebView or in phone gap. InfoVis Toolkit seems to work better on Android.
I don't know of a comparable Android visualization platform, but D3, and it's predecessors Protovis, Flare, and Prefuse are all open source. You could try porting one of them to Android perhaps.
Here is a related question: visualization tool for mobile (tablet)
As far as I'm aware, Android apps are java only. So to use d3, you would need either a java javascript engine/wrapper (like Rhino, or apparently PhoneGap) or to just make an HTML5 application (not an Android app as such).
That link about PhoneGap seems to be about generating an app from HTML5, but you'll need to check you can include arbitrary additonal libraries.
Does it have to be an app? D3 is better suited to writing an HTML5 site rather than an app.
I got D3 to work on my Android app by following this tutorial. From there, it was easy to extend the tutorial's code to fit my needs.
Here is a slightly modified version of the tutorial (I added zoom controls and scaling):
- Create a JS assets folder (ProjectName/app/src/main/assets/js)
- Download D3 (https://d3js.org/) and copy the minified d3.min.js source file into ProjectName/app/src/main/assets/js
- Create a directory for HTML assets: (ProjectName/app/src/main/assets/html)
- Create file ProjectName/app/src/main/assets/html/graph.html. Copy this code into the new file:
<html>
<head>
<script type="text/javascript" src="file:///android_asset/js/d3.min.js"></script>
<script type="text/javascript" src="file:///android_asset/js/drawGraph.js"></script>
<meta name="viewport" content="width=device-width, user-scalable=yes" />
</head>
<body>
<svg id="piechart"></svg>
</body>
</html>
- Create the JS file that will run D3: ProjectName/app/src/main/assets/js/drawGraph.js. Add the following code to it:
function initGraph(dataset, pHeight, pWidth) {
var height = parseInt(pHeight);
var width = parseInt(pWidth);
var svg = d3.select("#piechart");
var textLabelSuffix = "%";
showPieChart(dataset, svg, height, width,
textLabelSuffix);
}
function showPieChart(dataset, svg, height, width,
textLabelSuffix)
{
var outerRadius = width / 2;
var innerRadius = 0;
// set height/width to match the SVG element
svg.attr("height", height).attr("width", width);
// create a new pie layout
var pie = d3.layout.pie();
// initialize arcs/wedges to span
// the radius of the circle
var arc = d3.svg.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius);
// create groups
var arcs = svg.selectAll("g.arc")
// bind dataset to pie layout
.data(pie(dataset))
// create groups
.enter()
// append groups
.append("g")
// create arcs
.attr("class", "arc")
// position each arc in the pie layout
.attr("transform", "translate(" +
outerRadius + "," +
outerRadius + ")");
// initialize color scale - refer to
// https://github.com/mbostock/d3/wiki/Ordinal-Scales
var color = d3.scale.category10();
arcs.append("path")
.attr("fill", function(d,i) { return color(i); })
.attr("d", arc);
arcs.append("text")
.attr("transform", function(d) {
return "translate(" + arc.centroid(d) + ")";
})
.attr("text-anchor", "middle")
.text(function(d) { return d.value +
textLabelSuffix; });
}
- Create an activity layout that will host D3 code:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<WebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/tvOutgoing"
android:layout_alignParentBottom="true"/>
</RelativeLayout>
- Initialize the webview in your activity:
public class VisualizationActivity extends AppCompatActivity {
private WebView webview;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_visualization);
// Prepare webview: add zoom controls and start zoomed out
webview = (WebView) findViewById(R.id.webview);
final WebSettings webSettings = webview.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setBuiltInZoomControls(true);
webSettings.setSupportZoom(true);
webSettings.setUseWideViewPort(true);
webview.setWebChromeClient(new WebChromeClient());
webview.setInitialScale(1);
webview.setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
// after the HTML page loads, run JS to initialize graph
int dataset[] = new int[] {5,10,15,20,35};
String text = Arrays.toString(dataset);
webview.loadUrl("javascript:initGraph(" +
text + ", "
(webview.getHeight()) + ", "
+ (webview.getWidth()) + ")");
}
});
// Load base html from the assets directory
webview.loadUrl("file:///android_asset/html/graph.html");
}
}