File Logger for android apps - java

I want the simplest logger there is to simply log errors, mostly exceptions, to a Log file in the android file system. for exemple, the easiest and most convinient (in my opinion at least) way that i used to log to a file on PC java was by simply printing all exceptions to console and redirecting system out to both console and my file, this doesnt really suffice on android as far as i know i guess its because of how Android OS is designed, so what is the simplest way of doing it in Android?
Note that the project has already lot of code in it and i really wouldnt like to go over it and add log calls on catch blocks or whatever to log my exceptions, as little i need to do for logging those exceptions is best for my use case...
Thanks ahead!

It's not finished but works quite stable. It saves human readable json array with exception name, time, stack trace and additional data. Also you can save logcat's logs.
Using:
ExceptionWriter ew = new ExceptionWriter(new File(Environment.getExternalStorageDirectory(), "debug.txt"));
ew.w(new IllegalArgumentException("some msg"), "additional message");
Source:
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.concurrent.ConcurrentLinkedQueue;
/**
* User: elevenetc
* Date: 10/9/13
* Time: 12:52 PM
*/
public class ExceptionWriter {
private final StringBuilder sb;
private final ExceptionWriter.WriteExceptionTask writeExceptionTask;
private final SimpleDateFormat dataFormat;
private int totalExceptions;
private StringBuilder stackBuilder = new StringBuilder();
public int getTotalExceptions(){return totalExceptions;}
public ExceptionWriter(File file) throws IOException {
if(file != null){
writeExceptionTask = new WriteExceptionTask(file);
sb = new StringBuilder();
dataFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
new Thread(writeExceptionTask).start();
}else{
sb = null;
writeExceptionTask = null;
dataFormat = null;
}
}
public synchronized int wLogcat(){
try {
writeExceptionTask.addStreamToRead(Runtime.getRuntime().exec("logcat -d -v time").getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
return 0;
}
public int w(Exception debugException, String caughtMessage){
return w(debugException, caughtMessage, null);
}
public synchronized int w(Exception debugException, String caughtMessage, String additionalData){
if(writeExceptionTask == null) return -1;
sb.setLength(0);
StackTraceElement[] stackTrace = debugException == null ? null : debugException.getStackTrace();
sb.append("{\"date\":\"");sb.append(getTime());
sb.append("\",\"exceptionClassName\":\"");sb.append(debugException == null ? null : debugException.getClass());
sb.append("\",\"exceptionMessage:\":\"");sb.append(debugException == null ? null : debugException.getMessage());
sb.append("\",\"caughtMessage:\":\"");sb.append(caughtMessage);
if(additionalData != null) {sb.append("\",\"data:\":\"");sb.append(additionalData);}
sb.append("\",\"stack\":");sb.append(stackToString(stackTrace));
sb.append("},");
writeExceptionTask.stringQueue.add(sb.toString());
totalExceptions++;
return 0;
}
public void destroy() {
if(writeExceptionTask != null) {
writeExceptionTask.stop();
}
}
private String getTime(){
return dataFormat.format(System.currentTimeMillis());
}
private String stackToString(StackTraceElement[] stackTrace){
if(stackTrace == null) return null;
stackBuilder.setLength(0);
stackBuilder.append("[");
for (int i = 0; i < stackTrace.length; i++) {
StackTraceElement e = stackTrace[i];
stackBuilder.append("{\"");
stackBuilder.append(e.getLineNumber());
stackBuilder.append("\":\"");
stackBuilder.append(e.getClassName());
stackBuilder.append(".");
stackBuilder.append(e.getMethodName());
stackBuilder.append("\"}");
if(i != stackTrace.length -1) stackBuilder.append(",");
}
stackBuilder.append("]");
return stackBuilder.toString();
}
///////////////////////////////////////////////
/// Static classes
///////////////////////////////////////////////
private class WriteExceptionTask implements Runnable {
private final File file;
private boolean running;
private final ConcurrentLinkedQueue<String> stringQueue;
private final ConcurrentLinkedQueue<InputStream> isQueue;
private final FileWriter writer;
private WriteExceptionTask(File file) throws IOException {
this.file = file;
writer = new FileWriter(this.file, true);
stringQueue = new ConcurrentLinkedQueue<String>();
isQueue = new ConcurrentLinkedQueue<InputStream>();
running = true;
}
public void addStreamToRead(InputStream is){
if(is != null){
isQueue.add(is);
}
}
#Override
public void run() {
while(running){
if(!stringQueue.isEmpty()){
//TODO check file existence
try {
writer.append(stringQueue.poll());
writer.flush();
} catch (IOException e) {
e.printStackTrace();
running = false;
}
}
if(!isQueue.isEmpty()){
InputStream is = isQueue.poll();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder builder = new StringBuilder("{\"catLog\":\"");
String aux;
try {
while ((aux = reader.readLine()) != null) {
//TODO view like array or \n
builder.append(aux);
}
} catch (IOException e) {
e.printStackTrace();
}
builder.append("\"},");
stringQueue.add(builder.toString());
}
}
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public void stop() {
running = false;
}
}
}

Related

java, sonar, Cyclomatic Complexity

can anyone help me to reduce cylomatic complexity for below method upto 10..also considering no nesting of if else is allow as it will also cause sonar issue.
It will be great help for me
private void processIntransitFile(String fileName) {
if (StringUtils.isNotBlank(fileName))
return;
// read Intransit folder and do the processing on these files
try (BufferedReader bufferedReader = new BufferedReader(new FileReader(intransitDir + fileName))) {
TokenRangeDTO tokenRangeDTO = new TokenRangeDTO();
int count = 0;
String header = "";
String next;
String line = bufferedReader.readLine();
LinkedHashSet<String> tokenRanges = new LinkedHashSet<>();
int trCount = 0;
boolean first = true;
boolean last = line == null;
while (!last) {
last = (next = bufferedReader.readLine()) == null;
if (!first && !last) {
tokenRanges.add(line);
}
// read first line of the file
else if (first && line.startsWith(H)) {
header = line;
first = false;
} else if (first && !line.startsWith(H)) {
tokenRangeDTO.setValidationMessage(HEADER_MISSING);
first = false;
}
// read last line of the file
else if (last && line.startsWith(T)) {
trCount = getTrailerCount(tokenRangeDTO, line, trCount);
} else if (last && !line.startsWith(T)) {
tokenRangeDTO.setValidationMessage(TRAILOR_MISSING);
}
line = next;
count++;
}
processInputFile(fileName, tokenRangeDTO, count, header, tokenRanges, trCount);
} catch (IOException e) {
LOGGER.error(IO_EXCEPTION, e);
} catch (Exception e) {
LOGGER.error("Some exception has occured", e);
} finally {
try {
FileUtils.deleteQuietly(new File(intransitDir + fileName));
} catch (Exception ex) {
LOGGER.error(STREAM_FAILURE, ex);
}
}
}
can anyone help me to reduce cylomatic complexity for below method upto 10..also considering no nesting of if else is allow as it will also cause sonar issue.
It will be great help for me
You could extract part of your code to methods and/or refactor some variables which could be used in other way. Also, when you have comments explaining your code it is a strong indicator that your logic can be improved there:
private void processIntransitFile(String fileName) {
if (StringUtils.isNotBlank(fileName)) return;
processFromIntransitDirectory(fileName);
}
private void processFromIntransitDirectory(String fileName) {
try (BufferedReader bufferedReader = new BufferedReader(getFileFromIntransitFolder(fileName))) {
TokenRangeDTO tokenRangeDTO = new TokenRangeDTO();
int count = 0;
String header = "";
String next;
String line = bufferedReader.readLine();
LinkedHashSet<String> tokenRanges = new LinkedHashSet<>();
int trCount = 0;
while (!isLastLine(line)) {
next = bufferedReader.readLine();
if (!isFirstLine(count) && !isLastLine(next)) {
tokenRanges.add(line);
}
header = readFirstLine(line, count, tokenRangeDTO);
trCount = readLastLine(line, next, trCount, tokenRangeDTO);
line = next;
count++;
}
processInputFile(fileName, tokenRangeDTO, count, header, tokenRanges, trCount);
} catch (IOException e) {
LOGGER.error(IO_EXCEPTION, e);
} catch (Exception e) {
LOGGER.error("Some exception has occured", e);
} finally {
try {
FileUtils.deleteQuietly(new File(intransitDir + fileName));
} catch (Exception ex) {
LOGGER.error(STREAM_FAILURE, ex);
}
}
}
private boolean isLastLine(String line) {
return line != null;
}
private String readFirstLine(String line, int count, TokenRangeDTO tokenRangeDTO) {
if (isFirstLine(count) && isHeader(line)) {
return line;
} else if (isFirstLine(count) && !isHeader(line)) {
tokenRangeDTO.setValidationMessage(HEADER_MISSING);
}
return StringUtils.EMPTY;
}
private int readLastLine(String line, String next, int trCount, TokenRangeDTO tokenRangeDTO){
if (isLastLine(next) && isTrailor(line)) {
return getTrailerCount(tokenRangeDTO, line, trCount);
} else if (last && !isTrailor(line)) {
tokenRangeDTO.setValidationMessage(TRAILOR_MISSING);
}
return 0;
}
private boolean isTrailor(String line) {
return line.startsWith(T);
}
private boolean isHeader(String line) {
return line.startsWith(H);
}
private boolean isFirstLine(int count) {
return count == 0;
}
private FileReader getFileFromIntransitFolder(String fileName) {
return new FileReader(intransitDir + fileName);
}
Doing this your code will be more readable, you will avoid useless variables using logic and your cyclomatic complexity will decrease.
For more tips, I recommend access refactoring.guru.

How do I save a custom class object data model to a different file each time it is made in java?

I have a custom ListView that uses an object class for its data. The users can add new items to the listview, the arraylist is then saved in SharedPreferences. However, I also want to save each individual item so that I can use it in another Expandable ListView, how could I create a file for each individual item the user creates, or perhaps there is a better why to do it? Thanks in advance. Here is the object class:
public class Item implements Serializable{
String homework, date, classes;
public Item(String homework, String date, String classes){
this.homework = homework;
this.date = date;
this.classes = classes;
}
public String getHomework(){
return homework;
}
public String getDate(){
return date;
}
public String getClasses(){
return classes;
}
}
Why not use a database?There is a bit of setting up, but after the initial set up writing/reading data is very easy.
https://developer.android.com/training/basics/data-storage/databases.html
An example of serialize-deserialize class
public final class Serialize
{
private static final String className = Serialize.class.getName();
public static void save(Object saveThis, String serializeFileName, Context context)
{
FileOutputStream fos = null;
ObjectOutputStream oos = null;
try
{
if(saveThis != null)
{
fos = context.openFileOutput(serializeFileName, Context.MODE_PRIVATE);
oos = new ObjectOutputStream(fos);
oos.writeObject(saveThis);
}
}
catch(Throwable t)
{
//log it
}
finally
{
if(oos != null)
{
try{oos.close();}catch(Throwable t){}
}
if(fos != null)
{
try{fos.close();}catch(Throwable t){}
}
}
}
public static Object read(String serializeFileName, Context context)
{
FileInputStream fis = null;
ObjectInputStream ois = null;
Object readThis = null;
try
{
File file = context.getFileStreamPath(serializeFileName);
if(file != null && file.exists())
{
fis = context.openFileInput(serializeFileName);
ois = new ObjectInputStream(fis);
readThis = ois.readObject();
}
}
catch(Throwable t)
{
//log it
}
finally
{
if(ois != null)
{
try{ois.close();}catch(Throwable t){}
}
if(fis != null)
{
try{fis.close();}catch(Throwable t){}
}
}
return readThis;
}
public static boolean delete(String serializeFileName, Context context)
{
boolean deleted = false;
try
{
File file = context.getFileStreamPath(serializeFileName);
if(file != null && (file.exists()))
{
deleted = file.delete();
}
}
catch(Throwable t)
{
//log it
}
return deleted;
}
public static boolean exist(String serializeFileName, Context context)
{
boolean exist = false;
try
{
File file = context.getFileStreamPath(serializeFileName);
if(file != null && (file.exists()))
{
exist = true;
}
}
catch(Throwable t)
{
//log it
}
return exist;
}
}
Use the save method to save the serializable object in a file and the read method to read it.

Using java export oracle and obtain the status

I want to use Java export Oracle database, and obtain the export status(indicates success or failure), if the operation failed, should return the reason why failed.
But I have trouble in this problem, the export is success,but the label I defined is always false and return [].
What should I do to get the true status or obtain the failure details.
public class DumpFile {
/**
* Default constructor
*/
public DumpFile() {
}
/**
* #return
* #throws InterruptedException
*/
public static boolean LoadToOracle(String Path) throws InterruptedException {
String importStr = "imp scott/tiger#orcl file="+Path+" full=y ignore=y";
Process process_oracle = null;
boolean flag = false;
List<String[]> processListOracle = new ArrayList<String[]>();
try {
process_oracle = Runtime.getRuntime().exec(importStr);
process_oracle.waitFor();
BufferedReader input = new BufferedReader(new InputStreamReader(
process_oracle.getInputStream(), "utf8"));
String line = "";
while ((line = input.readLine()) != null) {
System.out.println(line);
String[] content = line.split("\n");
processListOracle.add(content);
}
int exevalue = process_oracle.waitFor();
System.out.println("exevalue:"+exevalue);
input.close();
} catch (Exception e) {
e.printStackTrace();
}
for (String[] line : processListOracle)
for (String temp : line) {
if (temp.trim().equals("successfully"))
flag = true;
}
return flag;
}
public static String exportFromOracle(String FileName) throws InterruptedException {
String Path="/home/oracle/output/";
String exportStr = "exp scott/tiger#orcl file="+Path+FileName;
Process process_oracle = null;
boolean flag = false;
List<String[]> processListOracle = new ArrayList<String[]>();
try {
process_oracle = Runtime.getRuntime().exec(exportStr);
BufferedReader input = new BufferedReader(new InputStreamReader(
process_oracle.getInputStream(), "utf8"));
String line = "";
while ((line = input.readLine()) != null) {
System.out.println("line:"+line);
String[] content = line.split("\n");
processListOracle.add(content);
}
int exevalue = process_oracle.waitFor();
System.out.println("exevalue:"+exevalue);
input.close();
} catch (Exception e) {
e.printStackTrace();
}
for (String[] line : processListOracle)
for (String temp : line) {
if (temp.trim().equals("successfully"))
flag = true;
}
System.out.println("flag:"+flag);
if (flag==true)
return flag+"test"+Path;
else{
for (String[] line : processListOracle)
System.out.println(line);
}
return processListOracle.toString();
}
public static void main(String[] args) throws Exception {
String a=exportFromOracle("test.dmp");
System.out.println("a.isEmpty:"+a.isEmpty());
System.out.println(a);
}
}
OUTPUT:
exevalue:0
a.isEmpty:false
[]
I have solved this problem by "log file", I use imp export the database and output the log file, then I use Java to read the log file, to obtain the status.

Enumeration<URL> configs.hasMoreElements() gives false

I am developing a voice-based app in android and facing some problems please see below code,
Java File 1
file = .wav file
public static AudioInputStream getAudioInputStream(File file) throws UnsupportedAudioFileException, IOException {
return getAudioInputStreamImpl(file);
}
private static AudioInputStream getAudioInputStreamImpl(Object source) throws UnsupportedAudioFileException, IOException {
GetAudioInputStreamAudioFileReaderAction action = new GetAudioInputStreamAudioFileReaderAction(source);
doAudioFileReaderIteration(action);
AudioInputStream audioInputStream = action.getAudioInputStream();
if (audioInputStream != null) {
return audioInputStream;
}
throw new UnsupportedAudioFileException("format not supported");
}
private static void doAudioFileReaderIteration(AudioFileReaderAction action) throws IOException {
Iterator audioFileReaders = TAudioConfig.getAudioFileReaders();
boolean bCompleted = false;
while (audioFileReaders.hasNext() && !bCompleted) {
AudioFileReader audioFileReader = (AudioFileReader) audioFileReaders.next();
bCompleted = action.handleAudioFileReader(audioFileReader);
}
}
Java file 2 (TAudioConfig)
public static synchronized Iterator<AudioFileReader> getAudioFileReaders() {
Iterator<AudioFileReader> it;
synchronized (TAudioConfig.class) {
it = getAudioFileReadersImpl().iterator();
}
return it;
}
private static synchronized Set<AudioFileReader> getAudioFileReadersImpl() {
Set<AudioFileReader> set;
synchronized (TAudioConfig.class) {
if (sm_audioFileReaders == null) {
sm_audioFileReaders = new ArraySet();
registerAudioFileReaders();
}
set = sm_audioFileReaders;
}
return set;
}
private static void registerAudioFileReaders() {
TInit.registerClasses(AudioFileReader.class, new C00001());
}
Java File 3 (TInit)
public static void registerClasses(Class providerClass, ProviderRegistrationAction action) {
Iterator providers = Service.providers(providerClass);
if (providers != null) {
while (providers.hasNext()) {
try {
action.register(providers.next());
} catch (Throwable e) {
}
}
}
}
Java File 4 (Service)
public static Iterator<?> providers(Class<?> cls) {
String strFullName = "com/example/voiceautomator/AudioFileReader.class";
Iterator<?> iterator = createInstancesList(strFullName).iterator();
return iterator;
}
private static List<Object> createInstancesList(String strFullName) {
List<Object> providers = new ArrayList<Object>();
Iterator<?> classNames = createClassNames(strFullName);
if (classNames != null) {
while (classNames.hasNext()) {
String strClassName = (String) classNames.next();
try {
Class<?> cls = Class.forName(strClassName, REVERSE_ORDER, ClassLoader.getSystemClassLoader());
providers.add(0, cls.newInstance());
} catch (Throwable e) {
}
}
}
return providers;
}
private static Iterator<String> createClassNames(String strFullName) {
Set<String> providers = new ArraySet<String>();
Enumeration<?> configs = null;
try {
configs = Service.class.getClassLoader().getSystemResources(strFullName);
} catch (Throwable e) {
}
if (configs != null) {
while (configs.hasMoreElements()) {
URL configFileUrl = (URL) configs.nextElement();
InputStream input = null;
try {
input = configFileUrl.openStream();
} catch (Throwable e2) {
}
if (input != null) {
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
try {
for (String strLine = reader.readLine(); strLine != null; strLine = reader.readLine()) {
strLine = strLine.trim();
int nPos = strLine.indexOf(35);
if (nPos >= 0) {
strLine = strLine.substring(0, nPos);
}
if (strLine.length() > 0) {
providers.add(strLine);
}
}
} catch (Throwable e22) {
}
}
}
}
Iterator<String> iterator = providers.iterator();
return iterator;
}
getClassLoader().getSystemResources in the Java File 4 (Service) gives me TwoEnumerationsInOne and configs.hasMoreElements() gives false so not able to go into while loop.
AudioFileReader.java is included in the package
Please guide me to resolve this issue?
Please don't forget I am working on this code in an android project
Please see the value of configs here
http://capsicumtech.in/Screenshot_1.png
Thanks in advance.

parse CSV using BaneUtilBean

I am trying to parse a csv and map the fields to a POJO class. However I can see that the mapping is not achieved correctly.
I am trying to map the header from a POJO file to the csv.
public class CarCSVFileInputBean {
private long Id;
private String shortName;
private String Name;
private String Type;
private String Environment;
//getter and setters
}
Can someone please take a look at my code:
public class carCSVUtil {
private static Log log = LogFactory.getLog(carCSVUtil.class);
private static final List<String> fileHeaderFields = new ArrayList<String>();
private static final String UTF8CHARSET = "UTF-8";
static {
for (Field f : carCSVFileInputBean.class.getDeclaredFields()) {
fileHeaderFields.add(f.getName());
}
}
public static List<carCSVFileInputBean> getCSVInputList(InputStream inputStream) {
CSVReader reader = null;
List<carCSVFileInputBean> csvList = null;
carCSVFileInputBean inputRecord = null;
String[] header = null;
String[] row = null;
try {
reader = new CSVReader(new InputStreamReader(inputStream, UTF8CHARSET));
csvList = new ArrayList<carCSVFileInputBean>();
header = reader.readNext();
boolean isEmptyLine = true;
while ((row = reader.readNext()) != null) {
isEmptyLine = true;
if (!(row.length == 1 && StringUtils.isBlank(row[0]))) { // not an empty line, not even containing ','
inputRecord = new carCSVFileInputBean();
isEmptyLine = populateFields(inputRecord, header, row);
if (!isEmptyLine)
csvList.add(inputRecord);
}
}
} catch (IOException e) {
log.debug("IOException while accessing carCSVFileInputBean: " + e);
return null;
} catch (IllegalAccessException e) {
log.debug("IllegalAccessException while accessing carCSVFileInputBean: " + e);
return null;
} catch (InvocationTargetException e) {
log.debug("InvocationTargetException while copying carCSVFileInputBean properties: " + e);
return null;
} catch (Exception e) {
log.debug("Exception while parsing CSV file: " + e);
return null;
} finally {
try {
if (reader != null)
reader.close();
} catch (IOException ioe) {}
}
return csvList;
}
protected static boolean populateFields(carCSVFileInputBean inputRecord, String[] header, String[] row) throws IllegalAccessException, InvocationTargetException {
boolean isEmptyLine = true;
for (int i = 0; i < row.length; i++) {
String val = row[i];
if (!StringUtils.isBlank(val)) {
BeanUtilsBean.getInstance().copyProperty(inputRecord, header[i], val);
isEmptyLine = false;
}
}
return isEmptyLine;
}
}
I found the solution - the headers in the csv file are expected to begin with a lowercase.

Categories