package org.witness.informacam.app;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import org.witness.informacam.InformaCam;
import org.witness.informacam.app.utils.Constants.Codes;
import org.witness.informacam.json.JSONArray;
import org.witness.informacam.models.j3m.ISensorCapture;
import org.witness.informacam.models.media.IMedia;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.media.ExifInterface;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.preference.PreferenceManager;
import android.util.Log;
import android.util.TypedValue;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.TextView;
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.utils.ColorTemplate;
import com.github.mikephil.charting.utils.Utils;
import com.github.mikephil.charting.utils.ValueFormatter;
public class ChartsActivity extends Activity {
private InformaCam informaCam;
private LinearLayout viewChartGroup;
private IMedia media;
private Bitmap bmMap;
private ArrayList<LineChart> listCharts = new ArrayList<LineChart>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(PreferenceManager.getDefaultSharedPreferences(this).getBoolean("prefBlockScreenshots", false))
{
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE,
WindowManager.LayoutParams.FLAG_SECURE);
}
setContentView(R.layout.activity_charts);
viewChartGroup = (LinearLayout)findViewById(R.id.chartGroup);
viewChartGroup.setVisibility(View.GONE);
viewChartGroup.setDrawingCacheEnabled(true);
informaCam = (InformaCam) getApplication();
media = informaCam.mediaManifest.getById(getIntent().getStringExtra(Codes.Extras.EDIT_MEDIA));
setTitle(media._id);
Utils.init(getResources());
initCharts();
viewChartGroup.setVisibility(View.VISIBLE);
}
private void addMap (ArrayList<String> alPoints)
{
String baseMap = "https://maps.googleapis.com/maps/api/staticmap?size=600x400";
String basePath = "&path=color:0x0000ff|weight:5";
StringBuffer mapUrl = new StringBuffer();
mapUrl.append(baseMap);
mapUrl.append(basePath);
int max = 20;
for (int i = 0; i < alPoints.size()&& i < max; i++)
{
mapUrl.append('|');
mapUrl.append(alPoints.get(i));
}
ImageView iv = new ImageView(this);
int dpHeight = 300;
int height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpHeight, getResources().getDisplayMetrics());
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LayoutParams.MATCH_PARENT, height);
viewChartGroup.addView(iv,params);
new DownloadImageTask(iv).execute(mapUrl.toString());
}
private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
ImageView bmImage;
public DownloadImageTask(ImageView bmImage) {
this.bmImage = bmImage;
}
protected Bitmap doInBackground(String... urls) {
String urldisplay = urls[0];
Log.d("Map","getting map: " + urldisplay);
try {
InputStream in = new java.net.URL(urldisplay).openStream();
bmMap = BitmapFactory.decodeStream(in);
} catch (Exception e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return bmMap;
}
protected void onPostExecute(Bitmap result) {
bmImage.setImageBitmap(result);
}
}
private void initCharts ()
{
try
{
((IMedia) media).buildJ3M(this, false, null);
ArrayList<ISensorCapture> listSensorEvents = new ArrayList<ISensorCapture>(media.data.sensorCapture);
Collections.sort(listSensorEvents,new Comparator<ISensorCapture>()
{
@Override
public int compare(ISensorCapture lhs, ISensorCapture rhs) {
if (lhs.timestamp < rhs.timestamp)
return -1;
else if (lhs.timestamp == rhs.timestamp)
return 0;
else
return 1;
}
});
DateFormat dateFormat = SimpleDateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.LONG);
ArrayList<String> alPoints = new ArrayList<String>();
//do map
for (ISensorCapture sensor : listSensorEvents)
{
if (sensor.sensorPlayback.has("gps_coords"))
{
String latLon = (String)sensor.sensorPlayback.get("gps_coords");
alPoints.add(latLon.substring(1,latLon.length()-1));
}
}
if (alPoints.size() > 0)
addMap(alPoints);
//do charts
final String[] sensorLabels = {getString(R.string.gps_accuracy),getString(R.string.gps_speed),getString(R.string.gps_altitude),getString(R.string.light),getString(R.string.air_pressure),getString(R.string.orientation),getString(R.string.motion),getString(R.string.wifi_networks)};
final String[][] sensorTypes = {{"gps_accuracy"},{"gps_speed"},{"gps_altitude"},{"lightMeterValue"},{"pressureHPAOrMBAR"},{"pitch","roll","azimuth"},{"acc_x","acc_y","acc_z"},{"visibleWifiNetworks"}};
int labelIdx = 0;
for (String[] sensorTypeSet : sensorTypes)
{
ArrayList<LineDataSet> dataSets = new ArrayList<LineDataSet>();
int[] colors = ColorTemplate.JOYFUL_COLORS;
int colorIdx = 0;
ArrayList<String> xVals = null;
for (String sensorType : sensorTypeSet)
{
xVals = new ArrayList<String>(); //only the last time through will set the values
int i = 0;
ArrayList<Entry> yVals = new ArrayList<Entry>();
long lastTimeStamp = -1;
for (ISensorCapture sensor : listSensorEvents)
{
if (sensor.sensorPlayback.has(sensorType))
{
Object val = sensor.sensorPlayback.get(sensorType);
lastTimeStamp = sensor.timestamp;
xVals.add(dateFormat.format(new Date(sensor.timestamp)));
if (val instanceof Integer)
{
yVals.add(new Entry(((Integer)val).intValue(), i++));
}
else if (val instanceof Double)
{
yVals.add(new Entry(((Double)val).floatValue(), i++));
}
else if (val instanceof Float)
{
yVals.add(new Entry(((Float)val).floatValue(), i++));
}
else if (val instanceof JSONArray)
{
yVals.add(new Entry(((JSONArray)val).length(), i++));
}
else
{
try
{
float fval = Float.parseFloat(((String)val));
yVals.add(new Entry(fval, i++));
}
catch (Exception e)
{
//couldn't parse double
Log.w("Chart","couldn't parse value: " + val,e);
}
}
}
}
if (!yVals.isEmpty())
{
if (yVals.size()==1)
{
xVals.add(dateFormat.format(new Date(lastTimeStamp+1)));
Entry entry = yVals.get(0).copy();
entry.setXIndex(entry.getXIndex()+1);
yVals.add(entry);
}
LineDataSet dataSet = addLineDataSet(sensorType, yVals);
dataSet.setColor(colors[colorIdx++]);
dataSets.add(dataSet); // add the datasets
}
}
if (!dataSets.isEmpty())
{
// create a data object with the datasets
LineData data = new LineData(xVals, dataSets);
LineChart chart = addChart(sensorLabels[labelIdx],data);
/*
LimitLine limitCapture = new LimitLine(media.dcimEntry.timeCaptured, "Capture");
limitCapture.setLineColor(Color.RED);
limitCapture.setLineWidth(4f);
limitCapture.enableDashedLine(10f, 10f, 0f);
limitCapture.setTextSize(10f);
chart.getXAxis().addLimitLine(limitCapture);
*/
listCharts.add(chart);
}
labelIdx++;
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
private LineDataSet addLineDataSet (String dataset, ArrayList<Entry> yVals)
{
// create a dataset and give it a type
LineDataSet set1 = new LineDataSet(yVals, dataset);
// set the line to be drawn like this "- - - - - -"
// set1.enableDashedLine(10f, 5f, 0f);
set1.setLineWidth(3f);
set1.setCircleSize(0f);
//set1.setCircleSize(5f);
//set1.setDrawCircleHole(false);
//set1.setValueTextSize(9f);
//set1.setFillAlpha(65);
return set1;
}
private LineChart addChart (String label, LineData data)
{
LineChart chart = new LineChart(this);
//chart.setOnChartGestureListener(this);
//chart.setOnChartValueSelectedListener(this);
chart.getAxisLeft().setStartAtZero(false);
// no description text
chart.setDescription("");
chart.setNoDataTextDescription("");
// enable value highlighting
chart.setHighlightEnabled(true);
// enable touch gestures
chart.setTouchEnabled(true);
// enable scaling and dragging
chart.setDragEnabled(true);
chart.setScaleEnabled(true);
// chart.setScaleXEnabled(true);
// chart.setScaleYEnabled(true);
// if disabled, scaling can be done on x- and y-axis separately
chart.setPinchZoom(true);
// set data
chart.setData(data);
TextView tv = new TextView (this);
tv.setText(label);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
viewChartGroup.addView(tv,params);
int dpHeight = 300;
int height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpHeight, getResources().getDisplayMetrics());
params = new LinearLayout.LayoutParams(
LayoutParams.MATCH_PARENT, height);
int dpMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 3, getResources().getDisplayMetrics());
params.setMargins(dpMargin,dpMargin,dpMargin,dpMargin);
chart.setLayoutParams(params);
viewChartGroup.addView(chart,params);
return chart;
}
public File saveBitmap(Bitmap b, String name) throws IOException {
File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
if (!path.canWrite())
{
path = getExternalFilesDir(null);
if (!path.canWrite())
path = getFilesDir();
}
File imageFile = new File(path, name+ ".jpg");
FileOutputStream fileOutPutStream = new FileOutputStream(imageFile);
b.compress(Bitmap.CompressFormat.JPEG, 80, fileOutPutStream);
fileOutPutStream.flush();
fileOutPutStream.close();
imageFile.setReadable(true, false);
return imageFile;
}
private void shareGraphic ()
{
try {
ArrayList<Bitmap> listBitmap = new ArrayList<Bitmap>();
int chartWidth = listCharts.get(0).getWidth();
listBitmap.add(media.getThumbnail(chartWidth));
listBitmap.add(bmMap);
for (LineChart chart : listCharts)
{
Bitmap b = chart.getChartBitmap();
listBitmap.add(b);
}
Bitmap bmOut = combineImageIntoOne(listBitmap);
File fileImage = saveBitmap(bmOut,media._id);
String summary = media.buildSummary(this, null);
Intent intent = new Intent(Intent.ACTION_SEND);
Uri uriData = Uri.fromFile(fileImage);
intent.setData(uriData);
intent.putExtra(Intent.EXTRA_TITLE,media._id);
intent.putExtra(Intent.EXTRA_TEXT, summary);
intent.putExtra(Intent.EXTRA_STREAM, uriData);
intent.setType("image/jpeg");
startActivity(intent);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private Bitmap combineImageIntoOne(ArrayList<Bitmap> bitmap) {
int w = 0, h = 0;
for (int i = 0; i < bitmap.size()-1; i++) {
if (bitmap.get(i)!=null) {
if (i < bitmap.size() - 1) {
w = bitmap.get(i).getWidth() > bitmap.get(i + 1).getWidth() ? bitmap.get(i).getWidth() : bitmap.get(i + 1).getWidth();
}
h += bitmap.get(i).getHeight();
}
}
Bitmap temp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(temp);
int top = 0;
for (int i = 0; i < bitmap.size(); i++) {
if (bitmap.get(i)!=null) {
Rect dest = new Rect(0, top, w, top + bitmap.get(i).getHeight());
canvas.drawBitmap(bitmap.get(i), null, dest, null);
top += bitmap.get(i).getHeight();
}
}
return temp;
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.activity_charts, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
{
case R.id.menu_share:
{
shareGraphic();
return true;
}
}
return super.onOptionsItemSelected(item);
}
private Bitmap loadMediaBitmap () throws IOException
{
Bitmap result;
BitmapFactory.Options bfo = new BitmapFactory.Options();
bfo.inJustDecodeBounds = true;
bfo.inPreferredConfig = Bitmap.Config.RGB_565;
InputStream is = InformaCam.getInstance().ioService.getStream(media.dcimEntry.fileAsset.path, media.dcimEntry.fileAsset.source);
if (is == null)
return null;
BitmapFactory.decodeStream(is, null, bfo);
is.close();
bfo.inSampleSize = 4;
bfo.inJustDecodeBounds = false;
is = InformaCam.getInstance().ioService.getStream(media.dcimEntry.fileAsset.path, media.dcimEntry.fileAsset.source);
result = BitmapFactory.decodeStream(is, null, bfo);
is.close();
if (media.dcimEntry.exif.orientation == ExifInterface.ORIENTATION_ROTATE_90) {
// Log.d(LOG, "Rotating Bitmap 90");
Matrix rotateMatrix = new Matrix();
rotateMatrix.postRotate(90);
result = Bitmap.createBitmap(result,0,0,result.getWidth(),result.getHeight(),rotateMatrix,false);
} else if (media.dcimEntry.exif.orientation == ExifInterface.ORIENTATION_ROTATE_270) {
Matrix rotateMatrix = new Matrix();
rotateMatrix.postRotate(270);
result = Bitmap.createBitmap(result,0,0,result.getWidth(),result.getHeight(),rotateMatrix,false);
}
return result;
}
}