Something went wrong on our end
-
Peter Joseph De Jonckheere CESM2014 authoredPeter Joseph De Jonckheere CESM2014 authored
SaveFile.java 26.96 KiB
package com.notificationFramework.sedentary.frontEnd;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Environment;
import android.support.annotation.NonNull;
import android.util.Log;
import com.google.android.gms.awareness.Awareness;
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;
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.List;
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.
* <p>
* 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 line;
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();
//Checks for external storage
if (isExternalStorageMounted()) {
File dir = getDirectory(context);
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){
Log.e("SPLIT", "NULL POINTER");
}
}
//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;
int nm = 0;
int na = 0;
//Checks if external storage is present
if (isExternalStorageMounted()) {
File dir = getDirectory(context);
if (dir.isDirectory()) {
File file = new File(dir, "NOTLOG.txt");
//Creates a new file if one does not already exist
try {
if (!file.exists()) {
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());
} catch (NumberFormatException e) {
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;
nm += movement;
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);
getExtraData(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) {
File file = null;
//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
try {
if (file.exists()) {
file.delete();
}
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();
}
} finally {
zos.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()) {
File file = new File(dir, "TYPELOG.txt");
//If the file does not exist it is created
try {
if (!file.exists()) {
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));
String places = "";
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);
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();
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) {
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);
}
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.exists()) {
if (!file.mkdirs()) {
Log.e("DIRERROR", "Directory not created");
}
}
return file;
}
}