Reading file logged via slf4android? - android

I'm writing logs using slf4android (https://github.com/bright/slf4android) but it is not obvious how to read them (ideally I would just like to download them to my computer). The internal storage of the app is not accessible to other apps. Can I configure the slf4android to log to a shared directory? I've tried this but I get NOENT:
FileLogHandlerConfiguration fileHandler = LoggerConfiguration.fileLogHandler(this);
File lol = this.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS);
fileHandler.setFullFilePathPattern(fileHandler.toString() + "/my_log.%g.%u.log");
LoggerConfiguration.configuration().addHandlerToRootLogger(fileHandler);

Once you configured logging to a file by:
FileLogHandlerConfiguration fileHandler = LoggerConfiguration.fileLogHandler(this);
fileHandler.setFullFilePathPattern("/sdcard/your.package/my_log.log");
LoggerConfiguration.configuration().addHandlerToRootLogger(fileHandler);
There are two (both simple) ways to get a log file:
Using NotifyDeveloperHandler (my favourite)
slf4android has a very nice feature (for some reason undocumented) which allows sending an email to a given address with logs and screenshot included in an attachment.
NotifyDeveloperHandler handler = LoggerConfiguration.configuration().notifyDeveloperHandler(this, "example#gmail.com");
handler.notifyWhenDeviceIsShaken();
LoggerConfiguration.configuration().addHandlerToRootLogger(handler);
it's really handy to use (literally) because you can trigger a send action by shaking your device.
Using adb
Run adb pull /sdcard/your.package/my_log.log ~/my_log.log in terminal to copy log file from the device to home directory.

The official docs says you can do this:
FileLogHandlerConfiguration fileHandler = LoggerConfiguration.fileLogHandler(this);
fileHandler.setFullFilePathPattern(SOMEPATH);
LoggerConfiguration.configuration().addHandlerToRootLogger(fileHandler);
and the log file would be located into SOMEPATH. I would recommend you use a regular environment directory instead of an arbitrary string, like
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS).getPath()+File.pathSeparator+"appLogs"
Now, if you want to copy some existing logs to an outher destination, you can just copy the files.
if(BuildConfig.DEBUG) {
File logs = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS).getPath(), "logs");
FileLogHandlerConfiguration fileHandler = LoggerConfiguration.fileLogHandler(this);
LoggerConfiguration.configuration().addHandlerToRootLogger(fileHandler);
File currentLogs = fileHandler.getCurrentFileName();
if (currentLogs.exists()) {
FileChannel src = new FileInputStream(currentLogs).getChannel();
FileChannel dst = new FileOutputStream(logs).getChannel();
dst.transferFrom(src, 0, src.size());
src.close();
dst.close();
}
}
Finally, keep in mind nothing will work if you don't get the proper storage permissions!
Hope it helps. Happy coding!

In code example your provided you don't actually use "File lol" you've defined.
So it probably fails because you try to create another log on top of the first one (e.g. in "/sdcard/your.package/my_log.%g.%u.log/my_log.%g.%u.log");
Try:
File lol = this.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS);
fileHandler.setFullFilePathPattern(lol.getAbsolutePath() + "/my_log.%g.%u.log");
But you can also just add a menu option clicking which would find the logs, may be zip them (together with db or whatever) and send by email, upload to server or just copy to another folder.

Related

How can I write a public file for my service to pick up on Android?

I have two parts to this question: 1) what is the best solution to my need, and 2) how do I do this?
1) I have a client app which sends bundles to a service app. the bundles can break the limit on bundle size, so I need to write the actual request out and read it in on the service side. Because of this, I can't write to my private internal storage. I've used these pages heavily, and haven't had luck: http://developer.android.com/guide/topics/data/data-storage.html
http://developer.android.com/training/basics/data-storage/files.html
My current understanding is that my best path is to use this to get a public dir:
File innerDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
I then add in my filename:
String fileName = String.valueOf(request.timestamp + "_avoidRoute"+count+++".ggr");
Combing these two results in the full file path:
/storage/emulated/0/Download/GroundGuidance/Route/1425579692169_avoidRoute1.ggr
Which I write to disk like this:
fos = context.openFileOutput(fullPath, Context.MODE_WORLD_WRITEABLE);
fos.write(routeString.getBytes());
fos.close();
When I try to write this to disk I get the error
java.lang.IllegalArgumentException: File /storage/emulated/0/Download/GroundGuidance/Route/1425579692169_avoidRoute1.ggr contains a path separator
Of course it does - I need it to have a path. I've searched online for solutions to this error which tell me to us FileOutputStream to write a full path. I did, but while my app doesn't error and appears to create the file, I'm also not able to view it on my phone in Windows Explorer, leading me to believe that it is creating a file with private permissions. So this brings me to my post and two questions:
1) Is there a different approach I should be trying to take to share large amounts of data between my client and service apps?
2) If not, what am I missing?
Thanks all for reading and trying to help!
Combing these two results in the full file path:
/storage/emulated/0/Download/GroundGuidance/Route/1425579692169_avoidRoute1.ggr
Which I write to disk like this:
fos = context.openFileOutput(fullPath, Context.MODE_WORLD_WRITEABLE);
This is not an appropriate use of Context's openFileOutput() method as that does not take a full path, but rather a filename within an app's private storage area.
If you are going to develop a full path yourself, as you have, then use
fos = new FileOutputStream(fullPath)
The Sharing permission setting is not applicable to the External Storage, though you will need a manifest permission to write (and implicitly read) on your creator, and the one for reading on your consumer.
Or, instead of constructing a full path, you could use your private storage with a filename and Context.MODE_WORLD_WRITEABLE (despite the being deprecated as an advisory) and pass the absolute path of the result to the other app to use with new FileInputStream(path).
Or you could use any of the other data interchange methods - content providers, local sockets, etc.

Check if a file has been written to in Android

I have a question about Android programming. Basically, I am unsure of where to check where my file is, and if I wrote to it correctly. I want to locate where the file is, and I also want to know whether or not I wrote to it correctly. Below is the code I have come up with:
String lsNow = "testing";
try {
fos = openFileOutput("output.txt", Context.MODE_APPEND);
fos.write(lsNow.getBytes());
fos.close();
}
catch{
...
}
Where can I find output.txt? Might anyone know how to check this all out? if so, that would be great! I am using an emulator by the way. If I were to do this on a real Android, how would one approach this also? (Just for future reference)
You Test it in Two ways
Using File Explorer
Go to DDMS perspective--> Open File Explorer-->location of the file
Pragrammatically by using exits() method
File file = new File(context.getFilesDir(), filename);
if(file.exists())
Using openFileOutput(...) means the file will be written to internal storage on the Android device in an area which is secure from access by other apps.
If you want to make sure the file is written correctly then make sure your catch block handles any failures (if it is called then the file writing has failed).
To access the file once it has been written use openFileInput(...).

Slashes removed from calls to File.mkdirs()

As the title suggests, I am trying to create a folder on Android, but all of the slashes have been removed from it.
For some more background information:
Specifically, I am trying to create a directory to store my application's users' files. These files must be accessible to the user from a file manager (such as File Manager HD) because the application does not support full file management. Using the standard from API level 8+, I reference the root of the publicly accessible folder with Environment.getExternalStoragePublicDirectory(). I then try to create a folder located at DCIM > Sketchbook > [the name of the sketch] using File.mkdirs(). For more information, see the code below.
I have already:
checked to make sure that the SD card is mounted, readable, and writable
enabled the permission WRITE_EXTERNAL_STORAGE
tried using File.mkdir() for every file in the hierarchy up to the folder location
tried using /, \\, File.separatorChar, and File.separator as folder separators
Code:
boolean success = true;
//The public directory
File publicDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
//The location of the sketchbook
File sketchbookLoc = new File(publicDir + "Sketchbook" + File.separator);
//The location of the sketch
//getGlobalState().getSketchName() returns the name of the sketch: "sketch"
File sketchLoc = new File(sketchbookLoc + getGlobalState().getSketchName() + File.separator);
if(!sketchLoc.mkdirs()) success = false;
//Notify the user of whether or not the sketch has been saved properly
if(success)
((TextView) findViewById(R.id.message)).setText(getResources().getText(R.string.sketch_saved));
else
((TextView) findViewById(R.id.message)).setText(getResources().getText(R.string.sketch_save_failure));
With various incarnations of the aforementioned tests (the ones that actually worked), I have received a consistent result: I get a new folder in DCIM whose name corresponds to the combination of all of the folders that should have been hierarchical parents of it. In other words, I have created a new directory, but all of the folder separators have been removed from it.
Now, I ask you:
Am I attempting to save the user data in the correct location? Is there another way that I should be doing this?
Is it even possible to create new folders in the DCIM folder? Does Android prevent it?
Is this problem specific to me? Is anyone else able to create a folder in the DCIM folder?
Am I using the right folder separators?
Is there something else that I am absolutely, completely, and utterly missing?
Now that I am done typing, and you are done reading my (excessively long) question, I hope that I can find some sort of answer. If you need clarification or more information, please say so.
EDIT: An example of the created folder is "DCIMSketchbooksketch", where it should be "DCIM/Sketchbook/sketch".
don't use
File sketchbookLoc = new File(publicDir + "Sketchbook" + File.separator);
but
File sketchbookLoc = new File(publicDir , "Sketchbook");
because publicDir.toString() will not end with a file separator (even if you declared it that way). toString() gives the canonical name of the file.
So your source becomes :
//The location of the sketchbook
File sketchbookLoc = new File(publicDir , "Sketchbook" );
//The location of the sketch
File sketchLoc = new File(sketchbookLoc , getGlobalState().getSketchName() );

How to read file that belongs to other app from external storage?

I want to read text file, that was written by other my app. It's saved ad "Android/data/MyPackageName/files/"
I use this code:
File file = new File("//Android//data//MyPackageName//files//", "filename.txt");
FileInputStream is = new FileInputStream(file);
but i get exception "no such file or directory"
I am sure that solution is pretty simple, but i can't find it yet.
Thank you for your help!
I don't think it is right to use the double backslash "//", one is enough. Also, the path should be "/mnt/sdcard/Android/data....". I am not sure the "/mnt/sdcard" is applicable on every device, so my suggestion is to use Environment.getExternalStorageDirectory to get the root dir on sd card.

Backup /data/system/xxxx.bin to /sdcard

I'm fairly new to apk development. So far, after a book purchase and with a lot of Googling I've managed to make an application that controls some features of my custom ROM. I'm currently trying to implement 2 backup features. I want to backup /data/system/batterystats.bin to /sdcard and also i want to backup launcher.db of my touchwiz launcher to /sdcard.
For the first part i haven't actually found anything. I've searched a lot about how to restore a file, not much has come up. It's mostly about SQL .db files. I've also looked for the possibility to run a shell script via the apk just to perform this backup. With a shell script it's easy work, but doing this via .java, i honestly have no clue.
Also, i've tried quite a lot of code to get my sqlite database file to backup, but i was quite unsuccessful. Here's my code for you to look at:
public class Backup extends Activity {
public void exportDB(){
try {
File sd = Environment.getExternalStorageDirectory();
if (sd.canWrite()) {
String currentDBPath = "data/data/com.sec.android.app.twlauncher/databases/launcher.db";
String backupDBPath = sd + "/launcher.db";
File currentDB = new File(currentDBPath);
File backupDB = new File(backupDBPath);
if (currentDB.exists()) {
FileChannel src = new FileInputStream(currentDB).getChannel();
FileChannel dst = new FileOutputStream(backupDB).getChannel();
dst.transferFrom(src, 0, src.size());
src.close();
dst.close();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
I have added permissions for external storage write, of course in the androidmanifest, but nothing happens. No FC, it just sits there doing nothing. And when I check my sdcard, there's nothing there.
Any help would be greatly appreciated. Thanks
Download RootTools (the jar file).
You can then run linux commands like this:
RootTools.sendShell(command);
For example to backup, you could do:
RootTools.sendShell("cp -f /data/data/com.sec.android.app.twlauncher/databases/launcher.db /sdcard/directory/");
And to restore the file:
RootTools.sendShell("cp -f /sdcard/directory/launcher.db /data/data/com.sec.android.app.twlauncher/databases/");
cp is the copy command, and -f is what allows it to overwite the file if it already exists.
RootTools are great, and for the commands, just google how to do linux commands and then place them into the sendShell
I have no idea how to do it with java. I personally think that using the linux commands are 10 times easier, though.
And to note, it is actually good to get sdcard location like this:
Environment.getExternalStorageDirectory();
and then append the rest of the storage location info to the end of that.

Categories

Resources