blob: 2095d4a53ecfd6306d3a80f5275590c974db9ffc [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package io.v.android.apps.reader;
import android.content.Context;
import android.util.Log;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVPrinter;
import java.io.Closeable;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import io.v.android.apps.reader.model.DeviceInfoFactory;
/**
* A utility class for logging user actions, such as touch gestures and button presses.
* Writes the user actions into a CSV file.
*
* This class implements {@link Closeable} interface, but closing this logger is not necessary to
* get the full logs, because the log printing streams are flushed right after each row is written.
*/
public class UserActionLogger implements Closeable {
private static final String TAG = GestureListener.class.getSimpleName();
private static volatile UserActionLogger instance;
private String mDeviceId;
private CSVPrinter mTouchPrinter;
private CSVPrinter mNavigationPrinter;
/**
* Singleton accessor of the UserActionLogger class.
*/
public static UserActionLogger getInstance(Context context) {
UserActionLogger result = instance;
if (instance == null) {
synchronized (UserActionLogger.class) {
result = instance;
if (result == null) {
instance = result = new UserActionLogger(context);
}
}
}
return result;
}
private UserActionLogger(Context context) {
mDeviceId = DeviceInfoFactory.getDeviceId(context);
if (Utils.hasExternalStoragePermission(context)) {
initPrinters();
}
}
public void initPrinters() {
File dir = Utils.getLogDirectory();
Log.i(TAG, "User action logs are saved at: " + dir.getAbsolutePath());
String startTime = Utils.getTimeString();
File touchLogFile = new File(dir,
String.format("reader-%s-touch-%s.log", mDeviceId, startTime));
File navigationLogFile = new File(dir,
String.format("reader-%s-navigation-%s.log", mDeviceId, startTime));
try {
mTouchPrinter = CSVFormat.DEFAULT
.withHeader("ACTION", "TIMESTAMP")
.print(new FileWriter(touchLogFile));
mNavigationPrinter = CSVFormat.DEFAULT
.withHeader("ACTION", "VALUE", "TIMESTAMP")
.print(new FileWriter(navigationLogFile));
} catch (IOException e) {
handleException(e);
try {
close();
} catch (IOException e2) {
// Nothing to do here.
}
}
}
@Override
public void close() throws IOException {
IOException ex = null;
if (mTouchPrinter != null) {
try {
mTouchPrinter.close();
} catch (IOException e) {
ex = e;
} finally {
mTouchPrinter = null;
}
}
if (mNavigationPrinter != null) {
try {
mNavigationPrinter.close();
} catch (IOException e) {
if (ex != null) {
ex.addSuppressed(e);
} else {
ex = e;
}
} finally {
mNavigationPrinter = null;
}
}
if (ex != null) {
throw ex;
}
}
/**
* Writes the given touch action to the CSV file.
*
* @param action name of the touch action.
*/
public void writeTouchAction(String action) {
if (mTouchPrinter == null) {
return;
}
try {
mTouchPrinter.printRecord(action, timestamp());
mTouchPrinter.flush();
} catch (IOException e) {
handleException(e);
}
}
/**
* Writes the given navigation action to the CSV file.
*
* @param action name of the navigation action.
* @param value the value associated with the action.
*/
public void writeNavigationAction(String action, int value) {
if (mNavigationPrinter == null) {
return;
}
try {
mNavigationPrinter.printRecord(action, value, timestamp());
mNavigationPrinter.flush();
} catch (IOException e) {
handleException(e);
}
}
private String timestamp() {
return Long.toString(System.currentTimeMillis());
}
private static void handleException(Exception e) {
Log.e(TAG, e.getMessage(), e);
}
}