com.lillicoder.newsblurry.util.FileLogger.java Source code

Java tutorial

Introduction

Here is the source code for com.lillicoder.newsblurry.util.FileLogger.java

Source

/**
 * Copyright 2012 Scott Weeden-Moody
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.lillicoder.newsblurry.util;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

import junit.framework.Assert;

import org.json.JSONException;
import org.json.JSONObject;

import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Environment;
import android.text.TextUtils;
import android.util.Log;

/**
 * Utility class that can dump strings and {@link JSONObject}
 * values to a file in the app storage directory.
 * @author lillicoder
 */
public class FileLogger {

    private static final String TAG = FileLogger.class.getSimpleName();

    private static final String DEBUG_WRITING_JSON_TO_FILE = "Writing JSON to file %s: %s";

    private static final String DEBUG_WRITING_TEXT_TO_FILE = "Writing text to file %s: %s";

    private static final String EXCEPTION_FAILED_TO_WRITE_OR_CLOSE_STREAM = "Failed to write to or close output stream, text was not logged.";

    private static final String WARNING_FAILED_TO_GET_APPLICATION_INFO = "Failed to get application info for package name %s, return false for debug mode.";

    private static final String WARNING_FAILED_TO_WRITE_DEBUG = "Failed to write data to debug stream, log operation will not be logged.";

    private Context _context;

    /**
     * Instantiates this object with the given {@link Context}.
     * @param context {@link Context} to get file directory access with.
     */
    public FileLogger(Context context) {
        this._context = context;
    }

    /**
     * Gets this instance's {@link Context}.
     * @return {@link Context} for this instance.
     */
    private Context getContext() {
        return this._context;
    }

    /**
     * Gets a {@link File} object for the given filename. If the indicated
     * file already exists, it will be overwritten by a new file. The returned file 
     * lives in this app's external cache directory by default (when external
     * media is not available, the internal cache is used instead).
     * @param filename Filename of the file to get.
     * @return {@link File} object for the given filename.
     */
    private File getLogFile(String filename) {
        Assert.assertTrue(!TextUtils.isEmpty(filename));

        // Use cache directory so that files are removed on uninstall.
        Context context = this.getContext();

        // Check for external media availability. If available,
        // write to that directory. Otherwise get the internal cache
        // directory and write there.
        File rootDirectory;
        if (this.isExternalStorageAvailable())
            rootDirectory = context.getExternalCacheDir();
        else
            rootDirectory = context.getCacheDir();

        // If the file to write already exists, delete it.
        File logFile = new File(rootDirectory, filename);
        if (logFile.exists())
            logFile.delete();

        return logFile;
    }

    /**
     * Determines if this app is running in debug mode. This value is
     * automatically set via the build process.
     * @return <code>true</code> if the app is running in debug mode,
     *          <code>false</code> otherwise.
     */
    private boolean isDebugMode() {
        boolean isDebugMode = false;

        Context context = this.getContext();
        PackageManager packageManager = context.getPackageManager();
        try {
            ApplicationInfo appInfo = packageManager.getApplicationInfo(context.getPackageName(), 0);
            isDebugMode = (0 != (appInfo.flags &= ApplicationInfo.FLAG_DEBUGGABLE));
        } catch (NameNotFoundException e) {
            Log.e(TAG, String.format(WARNING_FAILED_TO_GET_APPLICATION_INFO, context.getPackageName()));
        }

        return isDebugMode;
    }

    /**
     * Determines if the external storage media is available for writing.
     * @return <code>true</code> if external storage is available for writing,
     *          <code>false</code> otherwise.
     */
    private boolean isExternalStorageAvailable() {
        String externalMediaState = Environment.getExternalStorageState();
        return Environment.MEDIA_MOUNTED.equals(externalMediaState);
    }

    /**
     * Dumps the given {@link JSONObject} to a file with the given 
     * filename in the app storage directory.
     * @param filename Filename of the file to dump to. If the specified file already
     *                exists, its contents will be overwritten.
     * @param jsonToDump {@link JSONObject} to write to a file.
     * @return <code>true</code> if the log was successfully written,
     *          <code>false</code> otherwise.
     */
    public boolean logJson(String filename, JSONObject jsonToDump) {
        Assert.assertTrue(!TextUtils.isEmpty(filename) && jsonToDump != null);

        try {
            if (this.isDebugMode())
                Log.d(TAG, String.format(DEBUG_WRITING_JSON_TO_FILE, filename, jsonToDump.toString(4)));
        } catch (JSONException e) {
            Log.w(TAG, WARNING_FAILED_TO_WRITE_DEBUG);
        }

        File logFile = this.getLogFile(filename);
        return this.writeLog(logFile, jsonToDump.toString());
    }

    /**
     * Dumps the given {@link CharSequence} to a file with the given
     * filename in the app storage directory.
     * @param filename Filename of the file to dump to. If the specified file already
     *                exists, its contents will be overwritten.
     * @param textToDump {@link CharSequence} to write to file.
     * @return <code>true</code> if the log was successfully written,
     *          <code>false</code> otherwise.
     */
    public boolean logText(String filename, CharSequence textToDump) {
        Assert.assertTrue(!TextUtils.isEmpty(filename) && !TextUtils.isEmpty(textToDump));

        if (this.isDebugMode())
            Log.d(TAG, String.format(DEBUG_WRITING_TEXT_TO_FILE, filename, textToDump));

        File logFile = this.getLogFile(filename);
        return this.writeLog(logFile, textToDump.toString());
    }

    /**
     * Writes the given string to the given log {@link File}.
     * @param logFile {@link File} to write to.
     * @param textToLog String to write to file.
     * @return <code>true</code> if file was successfully written,
     *          <code>false</code> if there was an error writing to the file.
     */
    private boolean writeLog(File logFile, String textToLog) {
        Assert.assertTrue(logFile != null && !TextUtils.isEmpty(textToLog));

        boolean hasWrittenLog = false;
        try {
            // Write the string to the log and close.
            BufferedWriter buffer = new BufferedWriter(new FileWriter(logFile, false));
            buffer.write(textToLog);
            buffer.close();

            hasWrittenLog = true;
        } catch (IOException e) {
            Log.e(TAG, EXCEPTION_FAILED_TO_WRITE_OR_CLOSE_STREAM);
        }

        return hasWrittenLog;
    }

}