I am trying to create an interactive visualization within an android app.
The data that will be visualized will be stored locally in a sqlite database and will be queried to generate visualizations.
I have not yet decided whether to build a native app or a web app.
Based on my research d3.js seems to fit the needs very well but I am unsure about how to use it in a mobile environment.
D3 is a JavaScript library and framework for creating visualizations. D3 creates visualizations by binding the data and graphical elements to the Document Object Model. D3 associates (binding) the data (stuff you want to visualize) with the DOM. This allows the user to manipulate, change or add to the DOM.
The JavaScript ecosystem has completely changed during this time, in terms of libraries, best practices and even language features. Nevertheless, D3 is still here. And it's more popular than ever.
D3 is released under a BSD license, so you may use, modify, and adapt the code for noncommercial or commercial use at no cost. D3's official home on the Web is d3js.org.
D3 is often preferred over other data visualization tools as it is a very flexible tool that can provide dynamic properties to most of its functions. With D3, there are no standard visualization formats.
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)
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):
<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>
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; });
}
<?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>
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");
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With