Newer
Older
package com.notificationFramework.sedentary.frontEnd;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Environment;
import android.support.annotation.NonNull;
import android.util.Log;
import com.google.android.gms.awareness.Awareness;

Peter Joseph De Jonckheere CESM2014
committed
import com.google.android.gms.awareness.AwarenessStatusCodes;
import com.google.android.gms.awareness.snapshot.HeadphoneStateResponse;
import com.google.android.gms.awareness.snapshot.LocationResponse;
import com.google.android.gms.awareness.snapshot.PlacesResponse;
import com.google.android.gms.awareness.snapshot.WeatherResponse;
import com.google.android.gms.awareness.state.Weather;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.places.Place;
import com.google.android.gms.location.places.PlaceLikelihood;
import com.google.android.gms.tasks.OnCompleteListener;

Peter Joseph De Jonckheere CESM2014
committed
import com.google.android.gms.tasks.RuntimeExecutionException;
import com.google.android.gms.tasks.Task;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
* Created by Peter De Jonckheere on 12/02/2018.
* Contains the static methods which record various information about the notifications in the log
* files stored in the external storage of the device.
*/
public class SaveFile {
/**
* Saves a general timestamp which logs that a notification was either sent, clicked or
* acknowledged. The timestamp is saved in standard Android calendar format with 2 bits after.
* "00" - acknowledged
* "01" - clicked
* "10" - sent
* "11" - goal notification
*
* @param sent 1 if a notification has been sent, 1 if a goal notification has been sent,
* 0 otherwise
* @param clicked 1 if a notification has been clicked on, 1 if a goal notification has been
* sent, 0 otherwise
* @param context the application context which the method has been called from and which will
* be used to access and write to the external storage of the device
private static void recordTimeStamp(int sent, int clicked, int movement, int acknowledged, Context context) {
Calendar cal = Calendar.getInstance();
ArrayList<String> contents = new ArrayList<String>();
String prevLine = null;
String[] items;
SharedPreferences shared = context.getSharedPreferences(context.getString(R.string.preference_file_key), Context.MODE_PRIVATE);
SharedPreferences.Editor editor = shared.edit();
editor.putInt(context.getString(R.string.store_last_ack), acknowledged);
editor.commit();
if (isExternalStorageMounted()) {
File dir = getDirectory(context);

Peter Joseph De Jonckheere CESM2014
committed
File file = new File(dir, "TIMESTAMPLOG.txt");
//Creates a new file if one doesn't already exist
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
Log.e("FILE_ERROR", "COULDN'T CREATE NEW FILE");
}
}
//Reads the current contents of the log file
try {
if (file.isFile() && file.canRead()) {
BufferedReader br = new BufferedReader(new FileReader(file));
while ((line = br.readLine()) != null) {
contents.add(line + '\n');
prevLine = line;
}
try {
items = prevLine.split(" ");
if (items[6].equals("10") && (movement == 1)){
if(DataAnalysis.analyse(prevLine, cal, context)){
recordNotification(0,0,0,1, context);
}
}
}catch(NullPointerException e){
//Adds the new log to the file up to 1000 items. At 1000 items the oldest is removed
if (file.isFile() & file.canWrite()) {
BufferedWriter bw = new BufferedWriter(new FileWriter(file));
if (contents.size() > 999) {
contents.remove(0);
}
for (String ts : contents) {
bw.write(ts);
}
bw.write(cal.getTime().toString() + " " + sent + "" + clicked + " " + acknowledged);
bw.close();
}
} catch (IOException e) {
Log.e("FILEERROR", "COULD NOT WRITE TO FILE");
}
}
}
/**
* Keeps track of the number of each type of record stored in a file. Three integers only are
* written to the file used in this method. The first is the number of notifications sent, the
* second is the number clicked on and the third is the number of movements registered.
*
* @param sent 1 if a notification has been sent, 1 if a goal notification has been
* sent 0 otherwise
* @param clicked 1 if a notification has been clicked on, 1 if a goal notification has
* been sent, 0 otherwise
* @param movement 1 if a movement has been registered, 0 otherwise
* @param acknowledged 1 if a notification has been acknowledged by a movement, 0 otherwise
* @param context the application context which the method has been called from and which
* will be used to access and write to the external storage of the device
public static void recordNotification(int sent, int clicked, int movement, int acknowledged, Context context){
int ns = 0;
int nc = 0;
if (isExternalStorageMounted()) {
File dir = getDirectory(context);
if (dir.isDirectory()) {

Peter Joseph De Jonckheere CESM2014
committed
File file = new File(dir, "NOTLOG.txt");
//Creates a new file if one does not already exist
file.createNewFile();
}
//Reads the current contents of the file
if (file.isFile() & file.canRead()) {
BufferedReader br = new BufferedReader(new FileReader(file));
try {
ns = Integer.parseInt(br.readLine());
nc = Integer.parseInt(br.readLine());
nm = Integer.parseInt(br.readLine());
na = Integer.parseInt(br.readLine());
Log.e("FILEERROR", "COULD NOT READ FILE");
//Writes the modified values to the file based on the parameters
if (file.isFile() & file.canWrite()) {
BufferedWriter bw = new BufferedWriter(new FileWriter(file));
ns += sent;
nc += clicked;
na += acknowledged;
bw.write(String.valueOf(ns));
bw.newLine();
bw.write(String.valueOf(nc));
bw.newLine();
bw.write(String.valueOf(nm));
bw.newLine();
bw.write(String.valueOf(na));
bw.close();
} catch (IOException e) {
Log.e("FILEERROR", "WRITE FILE ERROR");
}
recordTimeStamp(sent, clicked, movement, acknowledged, context);
/**
* Compresses the files present in the log directory into a single zipped folder.
*
* @param context the application context from which this method was called
* @return the zip folder created
*/
static File zipFiles(Context context) {
//Checks for presence of external storage
if (isExternalStorageMounted()) {
File dir = getDirectory(context);
if (dir.isDirectory()) {
file = new File(dir, "ZIPFILE.zip");
//Deletes any old zip folder and creates a new one
if (file.createNewFile()) {
FileOutputStream fos = new FileOutputStream(file);
ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(fos));
File[] files = dir.listFiles();
try {
//For each file in the directory buffer the file the write into the zip
//folder by byte
for (int i = 0; i < files.length; i++) {
byte[] buffer = new byte[1024];
FileInputStream fis = new FileInputStream(files[i]);
zos.putNextEntry(new ZipEntry(files[i].getName()));
int length;
while ((length = fis.read(buffer)) > 0) {
zos.write(buffer, 0, length);
}
zos.closeEntry();
fis.close();
}
}
} catch (IOException e) {
Log.e("ZIPERROR", "COULDN'T ZIP FOLDER");
}
}
}
return file;
}
/**
* Records the type of preferences which were present when a notification was sent.
*
* @param context the application context which this method was called from
*/
public static void recordNotificationType(Context context) {
SharedPreferences shared =
context.getSharedPreferences(context.getString(R.string.preference_file_key), Context.MODE_PRIVATE);
int sound = 0;
int led = 0;
int vibration = 0;
//Checks if external storage is available
if (isExternalStorageMounted()) {
File dir = getDirectory(context);
if (dir.isDirectory()) {

Peter Joseph De Jonckheere CESM2014
committed
File file = new File(dir, "TYPELOG.txt");
//If the file does not exist it is created
file.createNewFile();
}
//Reads the current contents of the file
if (file.isFile() & file.canRead()) {
BufferedReader br = new BufferedReader(new FileReader(file));
try {
sound = Integer.parseInt(br.readLine());
led = Integer.parseInt(br.readLine());
vibration = Integer.parseInt(br.readLine());
} catch (NumberFormatException e) {
Log.e("FILEERROR", "CANNOT READ FILE");
//Writes new information to file based on parameters
if (file.isFile() & file.canWrite()) {
BufferedWriter bw = new BufferedWriter(new FileWriter(file));
if (shared.getBoolean(context.getString(R.string.audio), false)) {
sound++;
}
if (shared.getBoolean(context.getString(R.string.led), false)) {
led++;
}
if (shared.getBoolean(context.getString(R.string.vibration), false)) {
vibration++;
}
bw.write(String.valueOf(sound));
bw.newLine();
bw.write(String.valueOf(led));
bw.newLine();
bw.write(String.valueOf(vibration));
bw.close();
}
} catch (IOException e) {
Log.e("FILEERROR", "COULD NOT WRITE TO FILE");
}
}
}
public static void recordData(Context context) {
SharedPreferences preferences = context.getSharedPreferences(context.getString(R.string.preference_file_key),
Context.MODE_PRIVATE);
double latitude = Double.longBitsToDouble(preferences.getLong(context.getString(R.string.store_lat), 0));
double longitude = Double.longBitsToDouble(preferences.getLong(context.getString(R.string.store_long), 0));
for(int i = 0 ; i < 3; i++) {
try {
String place = preferences.getString(context.getString(R.string.store_place) + String.valueOf(i), "");
place = place.replace( " ", "");
String placeType = String.valueOf(preferences.getInt(context.getString(R.string.store_place_type) + String.valueOf(i), 0));
String placeLikelihood = String.valueOf(preferences.getFloat(context.getString(R.string.store_place_like) + String.valueOf(i), 0));
places = places + place + " " + placeType + " " + placeLikelihood + " ";
}catch(NullPointerException | IndexOutOfBoundsException e){
}
}
float temperature = preferences.getFloat(context.getString(R.string.store_temp), 0);
String line;
ArrayList<String> contents = new ArrayList<String>();
String writeLine = String.valueOf(latitude) + " " + String.valueOf(longitude) + " " + places
+ String.valueOf(temperature);
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
if (isExternalStorageMounted()) {
File dir = getDirectory(context);
File file = new File(dir, "DATALOG.txt");
//Creates a new file if one doesn't already exist
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
Log.e("FILE_ERROR", "COULDN'T CREATE NEW FILE");
}
}
//Reads the current contents of the log file
try {
if (file.isFile() && file.canRead()) {
BufferedReader br = new BufferedReader(new FileReader(file));
while ((line = br.readLine()) != null) {
contents.add(line + '\n');
}
}
//Adds the new log to the file up to 1000 items. At 1000 items the oldest is removed
if (file.isFile() & file.canWrite()) {
BufferedWriter bw = new BufferedWriter(new FileWriter(file));
if (contents.size() > 999) {
contents.remove(0);
}
for (String ts : contents) {
bw.write(ts);
}
bw.write(writeLine);
bw.close();
}
} catch (IOException e) {
Log.e("FILEERROR", "COULD NOT WRITE TO FILE");
}
}
DataAnalysis.placeAnalysis(context);
private static void getExtraData(final Context context){
GoogleApiClient client;
client = new GoogleApiClient.Builder(context)
.addApi(Awareness.getSnapshotClient(context).getApi()).build();
client.connect();
try {
Awareness.getSnapshotClient(context).getHeadphoneState().addOnCompleteListener(new OnCompleteListener<HeadphoneStateResponse>() {
@Override
public void onComplete(@NonNull Task<HeadphoneStateResponse> task) {
task.getResult().getHeadphoneState().getState();
}
});
Awareness.getSnapshotClient(context).getLocation().addOnCompleteListener(new OnCompleteListener<LocationResponse>() {
@Override
public void onComplete(@NonNull Task<LocationResponse> task) {
SharedPreferences preferences = context.getSharedPreferences(context.getString(R.string.preference_file_key),
Context.MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();

Peter Joseph De Jonckheere CESM2014
committed
editor.putLong(context.getString(R.string.store_lat), Double.doubleToLongBits(task.getResult().getLocation().getLatitude()));
editor.putLong(context.getString(R.string.store_long), Double.doubleToLongBits(task.getResult().getLocation().getLongitude()));
editor.commit();
}
});
Awareness.getSnapshotClient(context).getPlaces().addOnCompleteListener(new OnCompleteListener<PlacesResponse>() {
@Override
public void onComplete(@NonNull Task<PlacesResponse> task) {
SharedPreferences preferences = context.getSharedPreferences(context.getString(R.string.preference_file_key),
Context.MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();
List<PlaceLikelihood> placeLikelihoods = task.getResult().getPlaceLikelihoods();
for(int i = 0; i < 3; i++) {
try {
PlaceLikelihood placeLikelihood = placeLikelihoods.get(i);
Place place = placeLikelihood.getPlace();
editor.putFloat(context.getString(R.string.store_place_like) +
String.valueOf(i), placeLikelihood.getLikelihood());
editor.putString(context.getString(R.string.store_place)
+ String.valueOf(i), String.valueOf(place.getName()));
editor.putInt(context.getString(R.string.store_place_type)
+ String.valueOf(i), place.getPlaceTypes().get(i));
} catch (NullPointerException | IndexOutOfBoundsException e) {
editor.commit();
}
});
Awareness.getSnapshotClient(context).getWeather().addOnCompleteListener(new OnCompleteListener<WeatherResponse>() {
@Override
public void onComplete(@NonNull Task<WeatherResponse> task) {
SharedPreferences preferences = context.getSharedPreferences(context.getString(R.string.preference_file_key),
Context.MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();
editor.putFloat(context.getString(R.string.store_temp),task.getResult().getWeather().getTemperature(Weather.CELSIUS));
editor.commit();
}
});
recordData(context);
}catch(SecurityException e){
Intent i = new Intent(context, RequestPermission.class);
context.startActivity(i);
}
}
static List<com.notificationFramework.sedentary.frontEnd.Place> getPlaces(Context context){
String line = "";
String[] items;
List<com.notificationFramework.sedentary.frontEnd.Place> places = new ArrayList<>();
if (isExternalStorageMounted()) {
File dir = getDirectory(context);
File file = new File(dir, "DATALOG.txt");
//Creates a new file if one doesn't already exist
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
Log.e("FILE_ERROR", "COULDN'T CREATE NEW FILE");
}
}
//Reads the current contents of the log file
try {
if (file.isFile() && file.canRead()) {
BufferedReader br = new BufferedReader(new FileReader(file));
while ((line = br.readLine()) != null) {
items = line.split(" ");
for(int i = 0; i < 3; i++) {
try {
com.notificationFramework.sedentary.frontEnd.Place place = new com.notificationFramework.sedentary.frontEnd.Place(
items[i + 2], Float.parseFloat(items[i + 4]), Integer.parseInt(items[i + 3]));
places.add(place);
}catch(NumberFormatException | IndexOutOfBoundsException e){
}
}
}catch(IOException e){
}
}
return places;
}
static void writePopularType(Context context, int popularType, int acknowledged) {
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
String line = "";
ArrayList<String> contents = new ArrayList<String>();
boolean matched = false;
if (isExternalStorageMounted()) {
File dir = getDirectory(context);
File file = new File(dir, "POPLOG.txt");
//Creates a new file if one doesn't already exist
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
Log.e("FILE_ERROR", "COULDN'T CREATE NEW FILE");
}
}
//Reads the current contents of the log file
try {
if (file.isFile() && file.canRead()) {
BufferedReader br = new BufferedReader(new FileReader(file));
while ((line = br.readLine()) != null) {
contents.add(line + '\n');
}
}
if (file.isFile() & file.canWrite()) {
BufferedWriter bw = new BufferedWriter(new FileWriter(file));
for (String s : contents) {
String[] items = s.split(" ");
if (items[0].equals(String.valueOf(popularType))) {
int no = Integer.parseInt(items[1].trim());
no++;
int ack = Integer.parseInt(items[2].trim());
ack += acknowledged;
SharedPreferences shared = context.getSharedPreferences(context.getString(R.string.preference_file_key), Context.MODE_PRIVATE);
SharedPreferences.Editor editor = shared.edit();
editor.putInt(context.getString(R.string.place_ack_total), ack );
editor.apply();
bw.write(items[0] + " " + String.valueOf(no) + " " + ack);
matched = true;
}else{
bw.write(s);
}
}
if(!matched){
bw.write(String.valueOf(popularType) + " " + String.valueOf(1) + " " + acknowledged);
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
}
bw.close();
}
}catch(IOException e){
}
}
}
static int findMostPopularType(Context context) {
String line = "";
ArrayList<String> contents = new ArrayList<String>();
if (isExternalStorageMounted()) {
File dir = getDirectory(context);
File file = new File(dir, "POPLOG.txt");
//Creates a new file if one doesn't already exist
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
Log.e("FILE_ERROR", "COULDN'T CREATE NEW FILE");
}
}
//Reads the current contents of the log file
try {
if (file.isFile() && file.canRead()) {
BufferedReader br = new BufferedReader(new FileReader(file));
while ((line = br.readLine()) != null) {
contents.add(line + '\n');
}
if(contents.size() >= 100) {
return mostPopular(contents);
}
}
}catch(IOException e){
}
}
return -1;
}
private static int mostPopular(List<String> contents){
int count = 1;
int tempCount;
String[] items = contents.get(0).split(" ");
int popular = Integer.parseInt(items[0]);
int temp;
for (int i = 0; i < (contents.size() - 1); i++)
{
items = contents.get(i).split(" ");
temp = Integer.parseInt(items[0]);
tempCount = Integer.parseInt(items[1]);
if (tempCount > count){
popular = temp;
count = tempCount;
}
}
return popular;
}
/**
* Checks if external storage is available on the device.
*
* @return true if external storage is available, false otherwise
*/
private static boolean isExternalStorageMounted() {
return (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()));
}
/**
* Gets the directory for the application where data files should be stored. This ensures each
* file uses the same directory and makes compresssion of data easier also.
*
* @param context the application context from which this method was called
* @return the directory for files to be placed in
*/
private static File getDirectory(Context context) {
File file = new File(context.getExternalFilesDir(
Environment.DIRECTORY_DOCUMENTS), "NOTLOGS");
if (!file.mkdirs()) {
Log.e("DIRERROR", "Directory not created");
return file;
}
}