Write timestamped logs, exceptions, stack traces, or any form of text to a file for Android debugging purposes.
- Simple single parameter one liners to write stack traces or messages to user defined directories/files.
- Released apps and APKs automatically disable KatScan (no need to comment out or delete for release).
- Single file,
Kat.java
, that can be copied/pasted directly into an Android project or import thekatscan.aar
to use. - Ready to use out of the box and fully configurable for customization.
- Compatible with every Android version API 4 (Android 1.6, Donut) and higher.
- The results of running this sample code can be seen in the screenshot below. The following briefly demonstrates the setup and type of calls that can be made using KatScan.
- This sample code is also found and can be ran in this repo's example project,
/KatScan-ExampleApp/
using Android Studio.
//PERMISSION ADDED TO MANIFEST: <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
//Only pre-req call needed and only called once for the entirety of the application life!
Kat.setup(this, true);//Context and if should write to
//Pass in variables, exceptions, custom messages, or any form of text for KatScan to output to a separate file.
Kat.scan("Setup complete, This custom message written and time stamped to default file/directory:" +
"/storage/emulated/0/KatScan_com.digidemic.katscanexamples/2018-09-30/KatScan_log.txt");
try{
//Explicitly throw an error for this example
String arrayOutOfBounds = new String[]{"KatScan", "error", "example"}[3];
} catch(Exception exception){
//Pass in exception to have its full stack trace written to its default file.
Kat.scan(exception);
//Or have the exception stack trace be prefixed with a custom message.
Kat.scan(exception, "Exception stack trace with this custom message written to default file.");
//Or even have everything written to a new directory & file KatScan creates if does not already exist
Kat.scan("/Errors/log", exception, "Exception stack trace with this custom message written to new subdirectory and file.");
}
//Dozens of configurable settings that can be updated at run-time
Kat.Config.File.lineBreakBetweenEachEntry = true;
Kat.scan("Every Kat.scan() going forward will have a line break between entries");
Kat.Config.createNewThreadForEachKatScanCall = true;
Kat.scan("This custom message was written using a new thread.");
Clone the KatScan repo to your local machine using
https://github.com/digidemic/KatScan
- Download the katscan.aar (17.9kb as of v1.0.0 file from the KatScan repository.
- Launch Android Studio and open the project you wish to add KatScan to.
- Expand the
Project
tab the switch the folder structure toAndroid
- Find the root most node which in many cases is
app
(This contains the manifest, java, and res directory).- Open the
Project Structure
window using one of two methods: Click to highlight theapp
directory > PressF4
or right-click theapp
directory > ClickOpen Module Settings
.- In the
Project Structure
window, press the green plus button > Scroll and selectImport .JAR/.AAR Package
> ClickNext
.- In the
File name
input box enter the full path ofkatscan.aar
from your local machine or click the...
button to the right of the input box then find and select thekatscan.aar
and pressFinish
.- Click
OK
from within theProject Structure
withkatscan
added to theModules
list.- Expand the
Gradle Scripts
node in theProject
tab > Locate and select the build.gradle file forModule: app
(There may be severalbuild.gradle
files, make sure to find the one with your root node name which isapp
in most cases).- Under the dependencies collection, add the following in a new line:
compile project(path: ':katscan')
- Sync Gradle (A bar at the top of your code should appear giving a link to
Sync Now
).- Your Android project is now ready to use KatScan! Go to the Syntax section for the next steps on using KatScan in your application!
- Choose to download either
Kat.java
orKat_(NoJavadoc).java
(42.9kb and 29.2kb respectively as of v1.0.0) file from the KatScan repository. Note:Kat_(NoJavadoc).java
only differs fromKat.java
by having all its comments and Javadocs removed making the file smaller. Functionality and code-wize it is exactly the same.- Copy the file directly into a valid path of your project (preferably a place where Java files are commonly accessed).
- Open the file and update the package name (first line of code) to properly reflect your project's package.
- Add the following permission to your manifest:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- Your Android project is now ready to use KatScan! Go to the Syntax section for the next steps on using KatScan in your application!
The following permission needs to be added to your project's
Manifest.xml
if not usingkatscan.aar
. This permission is needed for KatScan to write to external files.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Each class using KatScan needs the following import if using
katscan.aar
. IfKat.java
was copied/pasted into your project instead, the import needs to be the full package name of your definedKat.java
.
import com.digidemic.katscan.Kat;
Kat.Setup()
is the only pre-req call needed and only called once for the entirety of the application's lifespan. There are 2 overloadedKat.Setup()
methods to choose from: One that requires just the class'Context
to be passed in, the other for theContext
and to set configaddEntriesIntoSubdirectoryCreatedToday
. Either one of the two (never both) needs to be called before the firstKat.scan()
call anywhere Context (Or Activity) can be retrieved in your application. Consider passing in an active Activity in place of Context as devices using API 23 (Android Marshmallow) and higher will need to allow the "Storage" permission via popup. Because of this, it is highly recommended to add yourKat.setup()
call in your main activity'sonCreate()
method passing inthis
for the Context.
For the second parameter, Many would prefer having a main directory sub-folder with all of the current day's
Kat.scan()
entries. To quickly enable this, use theKat.Setup()
method using two parameters passing the second parameter astrue
. This can also be turned on by settingKat.Config.File.addEntriesIntoSubdirectoryCreatedToday = true
.
/**
* Option 1 of 2 for possible setup methods
* Only needs to be called once in the entire lifespan of the application (recommended to be called in the project's main activity onCreate method).
* @param context Context instance from the application to determine the application's package name and if the application version is in debug. Activity must be passed in to request the "WRITE_EXTERNAL_STORAGE" to be granted for devices API 23 and higher.
* @return true if successfully called without error
*/
Kat.setup(this);
//OR
/**
* Option 2 of 2 for possible setup methods
* Only needs to be called once in the entire lifespan of the application (recommended to be called in the project's main activity onCreate method).
* @param context Context instance from the application to determine the application's package name and if the application version is in debug. Activity must be passed in to request the "WRITE_EXTERNAL_STORAGE" to be granted for devices API 23 and higher.
* @param addEntriesIntoSubdirectoryCreatedToday If true will add all entries created from Kat.Scan into a subfolder of the current day. Ex: "/storage/emulated/0/KatScan_com.digidemic.katscanexamples/2018-09-30/KatScan_log.txt" rather than "/storage/emulated/0/KatScan_com.digidemic.katscanexamples/KatScan_log.txt"
* @return true if successfully called without error
*/
Kat.setup(this, true);
The main usage of KatScan is by calling
Kat.scan()
methods. There are 6 overloaded methods here allowing each call to write a message, exception stack track, or combination of the two to an external file (KatScan default or user defined file/directory).
try{
//Some code that throws and Exception
} catch(Exception exception) {
/*
Kat.scan() which writes to KatScan default file
*/
Kat.scan("This String outputted to default file/path: /storage/emulated/0/KatScan_YOUR.PACKAGE.HERE/KatScan_log.txt");
Kat.scan(exception); //Just Exception stack trace outputted to default file/path
Kat.scan(exception, "Message to prefix the Exception stack trace outputted to default file/path");
/*
Kat.scan() which writes to user defined Directory/Files (which will be created at run-time if don't exist)
*/
Kat.scan("/NewFolder/NewTxtFile", "This String outputted to user defined path: /storage/emulated/0/KatScan_YOUR.PACKAGE.HERE/NewFolder/NewFile.txt");
Kat.scan("NewFileInMainDirectory", exception);
Kat.scan("ExceptionFile", exception, "Message to prefix the Exception stack trace outputted to user defined file");
}
Kat.Config
has all the configurable settings that can be updated at run-time. The following are all public configuration settings set to their default value.
/*
Kat.Config.File
*/
Kat.Config.File.rootDirectoryPath = Environment.getExternalStorageDirectory() + "/"; //The absolute path just before the "mainDirectoryName" which stores all Kat.scan() entries for this project.
Kat.Config.File.mainDirectoryName = "KatScan_com.digidemic.katscan"; //NOTE: THIS IS REASSIGNED WHEN Kat.setup() IS CALLED. | The directory name that is created at the very end of the "rootDirectoryPath" which stores all KatScan entries for this project.
Kat.Config.File.defaultFileName = "KatScan_log"; //The name of the default file that Kat.scan() entries are written to if the developer does not pass in their own file/directory to write to instead.
Kat.Config.File.fileExtension = ".txt"; //The file extension for all Kat.scan() files. This includes all instances including default file and user passed in files.
Kat.Config.File.lineBreakBetweenEachEntry = false; //Add a line break between each Kat.scan() entry to the affected file.
Kat.Config.File.writeKatScanEntriesToFileInsteadOfLog = true; //Each Kat.scan() call will be written to an external file on the user's device instead of writing to the console.
Kat.Config.File.writeCountWithEveryEntry = false; //For the lifespan of the running application, each Kat.scan() call increments an internal value by 1 starting with 0. Include this value in the written entry output.
Kat.Config.File.addEntriesIntoSubdirectoryCreatedToday = false; //NOTE: AN OVERLOADED Kat.setup() METHOD CAN BE CALLED TO ASSIGN THIS VALUE TRUE. | To have each Kat.scan() entry written into a subfolder of the current day within "mainDirectoryName".
/*
Kat.Config.Date
*/
Kat.Config.Date.includePrefixedDateForEachFileEntry = true; //Each Kat.scan() call is prefixed with the current date/time when written to the file.
Kat.Config.Date.entryDateFormatPattern = "yy-MM-dd_HH:mm:ss"; //The date format pattern used when "includePrefixedDateForEachFileEntry" is set to true.
Kat.Config.Date.subdirectoryDateFormatPattern = "yyyy-MM-dd"; //The date format pattern used when "addEntriesIntoSubdirectoryCreatedToday" is set to true.
Kat.Config.Date.includePrefixedDateForEachLogEntry = false; //Each KatScan error or Kat.scan() meant to be written to the log instead of a file should have the date/time prefixed to its log entry.
/*
Kat.Config.InternalErrors
*/
Kat.Config.InternalErrors.showPermissionGrantedErrorIfOccurs = true; //If this error has not yet occurred or has not been displayed to the user's console yet.
Kat.Config.InternalErrors.showKatScanInternallyCaughtErrors = true; //If this error has not yet occurred or has not been displayed to the user's console yet.
Kat.Config.InternalErrors.showTheSetupErrorAsLogOnceIfNeededRegardlessIfDebugging = true; //If this error has not yet occurred or has not been displayed to the user's console yet.
Kat.Config.InternalErrors.showKatScanInternallyCaughtErrorsAsLogsOverPrintln = true; //If this error has not yet occurred or has not been displayed to the user's console yet.
Kat.Config.InternalErrors.showKatScanTextInLogsWhenFailureToWriteInFile = true; //If this error has not yet occurred or has not been displayed to the user's console yet.
Kat.Config.InternalErrors.loggingMethod = Kat.Config.InternalErrors.LOG_METHOD.DEBUG; //When anything needs to be logged, whether it be from a KatScan error or a Kat.scan() entry meant for the log, this is the defining log method.
Kat.Config.InternalErrors.logTag = "com.digidemic.katscan_entry"; //The log tag of each log performed in the console.
Kat.Config.InternalErrors.LOG_METHOD = { ERROR, WARNING, INFORMATION, DEBUG, VERBOSE }; //NOTE: THIS IS AN ENUM. | This is used to assign Kat.Config.InternalErrors.loggingMethod
/*
Kat.Config.PermissionRequest
*/
Kat.Config.PermissionRequest.codeID = 65496; //The request code used when requesting KatScan needed permissions dialog for devices API 23 and higher.
Kat.Config.PermissionRequest.millisecondsPerAcceptPermissionsCheck = 1000; //When showing the request permissions dialog a callback listener was not defined solely to not interfere with the main application. A timer is used in its place to determine if the permission has been accepted during the time to popup is on screen. This variable is how frequently the timer should check if the permission has been accepted.
Kat.Config.PermissionRequest.maxWaitTimeForUserToAcceptPermissions = 60000; //When showing the request permissions dialog a callback listener was not defined solely to not interfere with the main application. A timer is used in its place to determine if the permission has been accepted during the time to popup is on screen. This variable is the max duration the timer will check for before ending and assuming the permission has been revoked.
/*
Kat.Config
*/
Kat.Config.spaceSeparator = " - "; //Spacing put in between entry date and message.
Kat.Config.createNewThreadForEachKatScanCall = false; //Create a new thread for each Kat.scan() call.
Kat.Config.hasKatScanBeenEnabledRegardlessIfRunningInDebug(); //If the "enableKatScanRegardlessIfRunningInDebug" variable has manually been set to true
Kat.Config.isApplicationRunningInDebugMode(); //If KatScan detected that the application is running in debug mode, not release mode
Kat.Config.isKatScanEnabled(); //KatScan is enabled either by "applicationRunningInDebug" being true or "enableKatScanRegardlessIfRunningInDebug" being true
/**
* Allows the application to enable KatScan to write entries regardless if debug or release, useful for applications released and want a way to manually enable KatScan through the application
* @param enable enable KatScan regardless of if debug or release
*/
Kat.Config.enableKatScanRegardlessIfRunningInDebug(boolean enable);
/**
* Allows the application to enable KatScan to write entries regardless if debug or release, useful for applications released and want a way to manually enable KatScan through the application
* @param enable enable KatScan regardless of if debug or release
* @param activity pass in the application's Activity instance if device needs to grant Storage permissions still.
*/
Kat.Config.enableKatScanRegardlessIfRunningInDebug(boolean enable, Activity activity);
- SemVer is used for versioning.
- Given a version number MAJOR . MINOR . PATCH
- MAJOR version - Incompatible API changes.
- MINOR version - Functionality added in a backwards-compatible manner.
- PATCH version - Backwards-compatible bug fixes.
KatScan created by Adam Steinberg of DIGIDEMIC, LLC
- KatScan licensed under Apache License 2.0
- Copyright 2018 © DIGIDEMIC, LLC.