Android, simplexml serial.read from an empty file woes - android

Following suggestions on this site, I have adopted SimpleXML from org.simpleframework.xml.
I use this code to deserialize my class from a file on disk:
try {
myPoints = serial.read(Points.class, new File(getFilesDir(), "points.xml"));
Log.i(TAG, "Number of Points: " + myPoints.getSize());
} catch (FileNotFoundException e) {
Log.d(TAG, "No data found!");
} catch (Exception e) {
Log.d(TAG, "Uncaught exception: ", e.getMessage());
}
In the event the contents of file "points.xml" is not legal xml (in my case it's an empty file), serial.read breaks (an exception occurs in Persister.class, sorry I don't have simplexml sources...).
Should I check for xml consistency beforehand?
Can anybody help?

No need to validate before-hand since you won't be able to fix the problem. Just make sure it fails gracefully (as your code appears to be doing).
You may, however, want to see if the file is empty or not in the case of a deserialization error. An empty file is likely not a problem where as a malformed XML file is!

Related

Ktor: delete temporary file after response is sent

I'm sending a temporary file as a response to a request using the ktor library on a android tablet, but I can't find a way to safe delete it after being sent (or something went wrong).
How can I make sure that this file was delete without interrupting the sending process? Maybe using some callback or method that I´m not aware of.
Update: answering comments:
my code:
try {
call.response.headers.append("entity-count", entityCount)
call.response.headers.append("sync-length", lenght)
call.respondFile(FileContent(file) // need to delete this file after sent OR failed
} catch (e: Exception) {
Log.e(TAG, e)
}
should I just add a file.delete() line inside a finally block?
I think my main question/confusion (coming from java world) its if respondFile is a blocking call or not. If it its, just adding file.delete on finally block will be fine, otherwise I need to register somme kind of onCompleted callback.
You can use finally: it will be called after sending the file or in case of an error
try {
call.response.headers.append("entity-count", entityCount)
call.response.headers.append("sync-length", lenght)
call.respondFile(FileContent(file) // need to delete this file after sent OR failed
} catch (e: Exception) {
Log.e(TAG, e)
} finally {
file.delete()
}

Exception when downloading file from box.com - Android

I am trying to download a file using the Box android SDK. The problem seems to be with the destinationFile parameter. The box.com call is checking whether the destinationFile exists - but why? I get java.io.FileNotFoundException.
destinationFile = new File(getFilesDir(), "myfile.crs");
// destinationFile = new File(getFilesDir(),"/");
try {
BoxDownload fileDownload = mFileApi.getDownloadRequest(destinationFile, fileID)
// Optional: Set a listener to track download progress.
.setProgressListener(new ProgressListener() {
#Override
public void onProgressChanged(long numBytes, long totalBytes) {
// Update a progress bar, etc.
}
})
.send();
} catch (BoxException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
To do All the checks
Log.i(getClass().getName(),"Does File exists:"+(destinationFile.exists()?"Yes":"No"));
Log.i(getClass().getName(),"Is it A file:"+(destinationFile.isFile()?"Yes":"No"));
Log.i(getClass().getName(),"Is it Writable:"+(destinationFile.canWrite()?"Yes":"No"));
Log.i(getClass().getName(),"Is it A Readable:"+(destinationFile.canRead()?"Yes":"No"));
Log.i(getClass().getName(),"Path:"+destinationFile.getAbsolutePath());
you are most likely to found file does not exists then do this before using it.
if(!destinationFile.exists()){
try {
destinationFile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
The answer was to create a new File. Then call .createNewFile() on the File instance. Then call all of the code I posted except to put run it in the background. That's why I was asking here - I was wondering if I was doing something incorrect for Android and I was. Box networking operations need to be done on a thread.
Too bad they never show this for downloading a file. Too bad there's not one example of downloading a file with the Android DSK on the web.

Android: Intentionally Blank Lines in EditText Are Not Getting Saved

In the app that I'm making, my goal for it is to be a quick and easy notes/documents app. However, a problem that I have is that when the user saves the text they enter into an EditText, if there are extra lines that they put in, for basic formatting, those lines don't get saved into the text file. How could I remedy this? Here's the code for the saving process. Thanks!
String itemName = fileSaveListView.getItemAtPosition(position).toString();
File myExistingFile = new File(savedFilesDir, itemName);
if (myExistingFile.exists()){
myExistingFile.mkdirs();
}
try {
FileOutputStream fosForExistingFiles = new FileOutputStream(myExistingFile);
OutputStreamWriter myOutWriterExistingFiles = new OutputStreamWriter(fosForExistingFiles);
myOutWriterExistingFiles.append(textEntryEditText.getEditableText().toString());
myOutWriterExistingFiles.close();
fosForExistingFiles.close();
Toast.makeText(getBaseContext(), "Finished writing " + itemName + " to the folder", Toast.LENGTH_SHORT).show();
final AlertDialog thefileSaver = fileSaver.create();
thefileSaver.dismiss();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
OK, I finally figured it out, and got it working. For anyone else that is having this problem, here's what you need to do. When grabbing the text from your EditText, convert it to Html with the Html.toHtml function, like below.
myOutWriter.append(Html.toHtml(textEntryEditText.getText()));
Now, your text file will be saved WITH any linebreaks you have entered. The next thing to do, if you wish to display your saved file in the EditText, you just need to convert back from Html. Like so.
textEntryEditText.setText(Html.fromHtml(String.valueOf(<your file reader>)));
I have been trying to fix this problem for a VERY long time, so if anyone else was suffering like I was, I hope this helps you! :D

Android File Logging

I'm planning to implement a logging mechanism for security-related messages in Android. I want to be able to use it in the Android source code like the Log class, e.g. SecuLog.log(String msg);
It shall in the following ways differ from the normal Log
No levels like DEBUG, INFO, etc...
Output should directly go into a File on the device. There must not be the need of redirecting Logcat output for example.
As multiple processes shall be able to log security-related messages I failed with just implementing a LoggingClass in com.android.util with a static PrintWriter.
static {
try {
writer = new PrintWriter("data/secu.log");
} catch (FileNotFoundException e) {
Log.e(TAG, "Exception initializing SecuLog.", e);
}
}
This did not work, because Android is designed to run multiple dalvik-VMs that all try to access the given file. So i need some kind of non-blocking File I/O.
Is there a way to reuse any logging mechanism from Android without the need to explicitly redirect logcat output?
How else can I achieve a simple file logging mechanism, that can be called from every other process? Should I implement a logging Service? Does this service has to be a bound service or a started service? Do I have to use AIDL?
After following the comments to my question I chose the following solution:
created multiple log files
one file for each process
used processId as suffix for log files
designed a log viewing app, that puts all logs togheter
For my logging class I used the following code:
static {
try {
File file = new File("data/secu" + android.os.Process.myPid() + ".log");
file.createNewFile();
file.setReadable(true, false);
file.setExecutable(true, false);
writer = new PrintWriter(file);
} catch (IOException e) {
Log.e(TAG, "Exception initializing SecuLog.", e);
}
}
This post is quite old by now. But I recently did this work and want to share it.
Suggestions are welcome.
Multiple libs are available for this purpose, but if you want to do it yourself, here you go.
fun log(tag: String?, message: String) {
try {
val direct = File("${Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)}/$DIRECTORY_NAME")
if (!direct.exists()) {
direct.mkdir()
}
val fileNameTimeStamp = "${SimpleDateFormat("dd-MM-yyyy", Locale.getDefault()).format(Date())}"
val logTimeStamp = SimpleDateFormat("E MMM dd yyyy 'at' hh:mm:ss:SSS aaa", Locale.getDefault()).format(Date())
val fileName = "$fileNameTimeStamp.html"
val file = File("${Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)}/$DIRECTORY_NAME" + File.separator + fileName)
file.createNewFile()
if (file.exists()) {
val fileOutputStream = FileOutputStream(file, true)
//Here I have added a html tag to beautify/highlight the output in file.
fileOutputStream.write("<p style=\"background:lightgray;\"><strong style=\"background:lightblue;\">&nbsp&nbsp$logTimeStamp :&nbsp&nbsp</strong>&nbsp&nbsp$message</p>".toByteArray())
fileOutputStream.close()
}
} catch (e: Exception) {
Log.e(TAG, "Error while logging into file : $e")
}
}
The purpose of keeping it html file is to open it browser and could highlight different items. Becuase log searching and debugging is very boring and beautifying could reduce the mental stress.
Output file looks like:

Writing to and Reading from a file in Android

I am having a hard time figuring out how to write to and read from files on an Android device. The file will be formatted as XML and I already have parsers and data structures built that can format the XML into objects and objects into XML, but the last hurdle is reading the XML from a non-resource file (I know the data structures work because I it works when reading from a resource file) and also writing to a non-resource file. I am terrible at using tools to debug (not sure how to print a stack trace) but I know for a fact the problem is that I cannot read from or write to this files. I have no experience writing to files in Java which may be why I am having a rough time with this.
Write code:
File scoresFile = new File(getExternalFilesDir(null), "scores.xml");
if (!scoresFile.exists())
{
scoresFile.createNewFile();
}
OutputStream os = new FileOutputStream(scoresFile);
os.write(writer.toString().getBytes());
os.flush();
os.close();
Read Code:
XmlPullParserFactory xmlFac = XmlPullParserFactory.newInstance();
XmlPullParser qXML = xmlFac.newPullParser();
InputStream is = null;
File scoresFile = new File(c.getExternalFilesDir(null), "scores.xml");
if (!scoresFile.exists())
{
try {
scoresFile.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
is = new FileInputStream(scoresFile);
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
if (is != null)
qXML.setInput(is,null);
else
qXML = c.getResources().getXml(R.xml.scores);
UPDATE: The last if clause in the read section always evaluates to false. So, the InputStream is null... that appears to be the root of my problem.
I would take a look at these two links: Using Internal Storage and Using External Storage
Both link to the same page, just different portions. Really, it depends on whether or not you want to save this file to the devices memory, or to an external medium (such as an SDcard).
Internal - Sandboxed, so that only your app can access it.
External - Anyone can access it.

Categories

Resources