Android - Remove the last incomplete line in .txt file - android

The app records the sensor data and write the data into a .txt file into the phone SD card.
During the data collection process, one may press the stop button anytime to stop writing.
The relevant writing part is as follows:
myFile = new File("/sdcard/ResearchData/"
+ txtData.getText() + ".txt");
myFile.createNewFile();
fOut = new FileOutputStream(myFile);
myOutWriter = new OutputStreamWriter(fOut);
myBufferedWriter = new BufferedWriter(myOutWriter);
myPrintWriter = new PrintWriter(myBufferedWriter);
myPrintWriter.write(currentTime - startTime + " " + acceleration[0]
+ " " + acceleration[1] + " " + acceleration[2] + "\n");
Once the STOP button is pressed, the following codes are executed.
myOutWriter.close();
fOut.close();
The codes are functioning okay, but the only problem is that because one may press STOP anytime, so the last line of the .txt file is always INCOMPLETE. Due to the need for data analysis, I need the data to be a nice rectangular matrix. Thus, I need to remove the last incomplete line. How may I do it?
Or solve this question from another angle. Can I make the STOP button synchronous to the writing process? i.e., after one line has been completely written in, then the STOP is checked.

You need a variable of bool type which is initially false and let's call it isStopPressed.
In button's down event, you should assign it to true.
I assume you create your file inside a top function, and modify this file inside onSensorChanged() function.
Then, after this line
myPrintWriter.write(currentTime - startTime + " " + acceleration[0]
+ " " + acceleration[1] + " " + acceleration[2] + "\n");
you need a conditional like,
if(isStopPressed) {
mSensorManager.unregisterListener([Your Sensor Listener]);
myOutWriter.close();
fOut.close();
}
This will provide you the most comprehensive, valid interval for your needs.

You may try setting up a boolean flag, like isStopped to indicate the STOP button is pressed.
When the STOP button is pressed, set the isStopped flag to true.
In your file writing part, check the isStopped flag. if it's true, exit the loop and close the file. Otherwise, the code can continue writing lines to the file.

Related

I Build a Brain Trainer app but Not Showing my TEXTVIEW when i run my app and warning is showing do not concatenate text display with setText

sumTextView.setText(Integer.toString(a) + " + " + Integer.toString(b));
This Line show warning you see in pic..
Use String.format();
sumTextView.setText(String.format("%1$d + %2$d", a, b));
With this you can format a string correctly with multiple variables, no matter whether they are strings or integers. This example takes the value of variable a and replaces the placeholder %1$d with it. Same goes for the other variable.
take an string copy whole line in it, then show string in setText
String str = (Integer.toString(a) + " + " + Integer.toString(a));
sumTextView.setText(str);
1. The First String Says that do not concate string with setText property.
String txt = String.valueOf(a) + " + " + String.valueOf(b);
sumTextView.setText(str);
2. Second warning says that your program have possibility to crash or genearte an exception in case if value of a or b is null or not an integer.
So check condition if(a!=null and b!=null) then display text in if condition.

How to get CSVWriter to add blob data into cell

I have an application that allows the user to sign the tablet and an image will be produced. That part I have working with confirmation as I am able to view the images after they are created and saved.
I am writing them to a .csv file with the following code.
//region - Create CSV file
writer = new CSVWriter(new FileWriter(sdCardPath + "Orders_Summary_Report.csv"), ',', CSVWriter.NO_QUOTE_CHARACTER, CSVWriter.DEFAULT_ESCAPE_CHARACTER, "\r\n");
//writer.writeNext(CSVcursor.getColumnNames()); //Write the column headings first before the looping starts
String [] headings = ("Order Id,Item ID,Item Name,Item Price,Item Count,Item Total,Paid Amount,VOID Order,Payment Method,Order Signature,Member/Authorization,Tab Number,Order Time").split(",");
writer.writeNext(headings);
for(CSVcursor.moveToFirst(); !CSVcursor.isAfterLast(); CSVcursor.moveToNext()) //Loop through all results (use row count of table)
{
String[] entries = (CSVcursor.getInt(CSVcursor.getColumnIndex("orderId"))+ ","
+CSVcursor.getInt(CSVcursor.getColumnIndex("itemId"))+ ","
+CSVcursor.getString(CSVcursor.getColumnIndex("itemName"))+ ","
+CSVcursor.getString(CSVcursor.getColumnIndex("itemPrice")) + ","
+CSVcursor.getInt(CSVcursor.getColumnIndex("itemCount"))+ ","
+CSVcursor.getString(CSVcursor.getColumnIndex("itemTotal"))+ ","
+CSVcursor.getString(CSVcursor.getColumnIndex("orderPaid"))+ ","
+CSVcursor.getInt(CSVcursor.getColumnIndex("orderVoid"))+ ","
+CSVcursor.getString(CSVcursor.getColumnIndex("orderType"))+ ","
+CSVcursor.getBlob(CSVcursor.getColumnIndex("orderSignature"))+ ","
+CSVcursor.getString(CSVcursor.getColumnIndex("referenceId"))+ ","
+CSVcursor.getInt(CSVcursor.getColumnIndex("orderTab"))+ ","
+CSVcursor.getString(CSVcursor.getColumnIndex("orderTime"))).split(","); //Split the string by the delimiter
writer.writeNext(entries); //Write current row of DB to file
writer.flush(); //Flush the stream
}
writer.close();
The file is getting written to successfully, but when I view the .csv file, the column that is saving the blob data looks like this.
B#2342342
B#2123982
B#3952929
It looks like I'm just saving the signature or some other attribute of the file rather than the file itself.
Do I need to stream the blob by bit/buffer into the csv file?
Just echoing #CommonsWare. The right thing to do is save the blob to the disk as am image. That way it can be easily retrieved for embedding into a file if needed. I still save my images to the db as blobs and just display them in a view. If you want to put these files into a csv, I would consider another type like pdf.

Managing data in android cache?

I'm trying to finish the 'backbone' of my app in the next 3 weeks, however, one of the few obstacles I stutter at is saving data. I've had a look at saving data internally, but there is limited tutorials from what I can find of reading and writing multiple lines to files in the apps cache directory.
Basically what I'm trying to do is save the values stored inside a fragment. This fragment resets all its values when the user clicks a button and changes text to match a page number. (A number of duplicates that contain various values.) I would do multiple fragments, however, thought it would be beneficial to use just one fragment to minimize storage space needed.
I've only got round to writing to the files, and created two methods to manage this which are then called on the click of a button. One creates these files and the other writes to them. Unfortunately I'm inexperienced using adb and could only find that the files are created, but don't know if they are being correctly written to. Is there any chance someone could review this and possibly assist with re-reading the files? Help is much appreciated.
The two methods (Warning: A great number of lines ahead):
public void createEmptyFiles() {
try {
outputTempExerciseFileE1 = File.createTempFile("temp_exercise_1",
".txt", outputTempExerciseDir);
outputTempExerciseFileE2 = File.createTempFile("temp_exercise_2",
".txt", outputTempExerciseDir);
outputTempExerciseFileE3 = File.createTempFile("temp_exercise_3",
".txt", outputTempExerciseDir);
} catch (IOException e) {
e.printStackTrace();
Log.w("rscReporter", "Encountered an error when creating empty files!");
}
}
public void writeTemporaryFiles() {
try {
if (counterAnotherExercise == 1) {
writerTemp = new FileWriter(outputTempExerciseFileE1);
writerTemp
.write(editTextExerciseName.getText().toString() + "\n"
+ counterNoSets + "\n" + counterRepsPerSet
+ "\n" + counterMeanRepTime + "\n"
+ counterMeanRepTimeRefined + "\n"
+ counterSetInterval);
writerTemp.close();
} else if (counterAnotherExercise == 2) {
writerTemp = new FileWriter(outputTempExerciseFileE2);
writerTemp
.write(editTextExerciseName.getText().toString() + "\n"
+ counterNoSets + "\n" + counterRepsPerSet
+ "\n" + counterMeanRepTime + "\n"
+ counterMeanRepTimeRefined + "\n"
+ counterSetInterval);
writerTemp.close();
} else if (counterAnotherExercise == 3) {
writerTemp = new FileWriter(outputTempExerciseFileE3);
writerTemp
.write(editTextExerciseName.getText().toString() + "\n"
+ counterNoSets + "\n" + counterRepsPerSet
+ "\n" + counterMeanRepTime + "\n"
+ counterMeanRepTimeRefined + "\n"
+ counterSetInterval);
writerTemp.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
Any of the text files should look like:
editTextExerciseName
counterNoSets
counterRepsPerSet
counterMeanRepTime
counterMeanRepTimeRefined
counterSetInterval
Where the two methods are called:
// In a switch statement as there are around 15 buttons
case R.id.button_another_exercise_foreground:
// Increases page number in fragment
counterAnotherExercise++;
// This then checks the page number and changes text
checkPageNo();
// Writing to files is called, files were created in onCreateView()
writeTemporaryFiles();
// Resets all the counters, giving the imitation it is a completely new fragment
counterReset();
// default array exercise is then set to the page number which is then displayed as title
// For example: Exercise 1, Exercise 2, Exercise 3...
textViewExerciseTitle.setText(defaultArrayExercise);
break;
I only know the basics of Java and Android, for myself this is ambitious, however, you gotta learn somewhere! Additional suggestion for saving values are welcomed.
You don't really need files as you are only writing and then reading a handful of fixed data. Use SharedPreferences like this:
to write:
PreferenceManager.getDefaultSharedPreferences(YourActivity.this).edit().putString("editTextExerciseName", "my exercise").commit();
to read:|
PreferenceManager.getDefaultSharedPreferences(YourActivity.this).getString("editTextExerciseName");

Android PDF Writer(APW) Enconding

I am using Android PDF Write(APW) to create a PDF, but it doesn't work with some special characters(portuguese).
mypdf.addText(170, 50, 40,"Coração");
The standard enconding is:
mypdf.setFont(StandardFonts.SUBTYPE, StandardFonts.COURIER, StandardFonts.WIN_ANSI_ENCODING);
outputToFile("helloworld.pdf",pdfcontent,"ISO-8859-1");
I'v tried
outputToFile("helloworld.pdf",pdfcontent,"UTF-8");
outputToFile("helloworld.pdf",pdfcontent,"UTF-16");
outputToFile("helloworld.pdf",pdfcontent,"Cp1252");
and didn't succeed.
Any ideas what should I do?
EDIT
The method outputToFile is defined as:
private void outputToFile(String fileName, String pdfContent, String encoding) {
File newFile = new File(Environment.getExternalStorageDirectory() + "/" + fileName);
try {
newFile.createNewFile();
try {
FileOutputStream pdfFile = new FileOutputStream(newFile);
pdfFile.write(pdfContent.getBytes(encoding));
pdfFile.close();
} catch(FileNotFoundException e) {
//
}
} catch(IOException e) {
//
}
}
The method addText is defined as:
public void addText(int leftPosition, int topPositionFromBottom, int fontSize, String text, String transformation) {
addContent(
"BT\n" +
transformation + " " + Integer.toString(leftPosition) + " " + Integer.toString(topPositionFromBottom) + " Tm\n" +
"/F" + Integer.toString(mPageFonts.size()) + " " + Integer.toString(fontSize) + " Tf\n" +
"(" + text + ") Tj\n" +
"ET\n"
);
}
Besides, I change the font color to white adding the following rawcontent:
mypdf.addRawContent("1 1 1 rg\n");
Then I come back to the black font color:
mypdf.addRawContent("0 0 0 rg\n");
I took all the information provided, wrote the following simple unit test method and ran it.
public void test19192108()
{
PDFWriter mPDFWriter = new PDFWriter(PaperSize.FOLIO_WIDTH, PaperSize.FOLIO_HEIGHT);
mPDFWriter.setFont(StandardFonts.SUBTYPE, StandardFonts.COURIER, StandardFonts.WIN_ANSI_ENCODING);
mPDFWriter.addText(170, 50, 40,"Coração");
String pdfcontent = mPDFWriter.asString();
outputToFile("helloworld19192108.pdf",pdfcontent,"ISO-8859-1");
}
(outputToFilebeing the helper method from the APW PDFWriterDemo class)
The result looks like this:
This seems pretty much to fulfill the expectations.
Thus, in whichever way it doesn't work with some special characters(portuguese) for the OP, some vital information is missing for reproducing the issue.
PS: Depending on the setup of the development environment, there might be an issue with non-ASCII characters in the source code. Thus, it might be a good idea to replace
mPDFWriter.addText(170, 50, 40,"Coração");
with
mPDFWriter.addText(170, 50, 40,"Cora\u00e7\u00e3o");
PPS: Adobe Reader after viewing a file generated like this wants to repair it. The reason is that the cross reference table is broken. The code generating entries for it is this:
public void addObjectXRefInfo(int ByteOffset, int Generation, boolean InUse) {
StringBuilder sb = new StringBuilder();
sb.append(String.format("%010d", ByteOffset));
sb.append(" ");
sb.append(String.format("%05d", Generation));
if (InUse) {
sb.append(" n ");
} else {
sb.append(" f ");
}
sb.append("\r\n");
mList.add(sb.toString());
}
(from CrossReferenceTable.java)
Counting the characters in this entry we get 10 + 1 + 5 + 3 + 2 = 21.
According to the specification, though:
Each entry shall be exactly 20 bytes long, including the end-of-line marker
(from section 7.5.4 Cross-Reference Table of ISO 32000-1)
When using (the current version of) the Android PDF Writer, you should fix this code, too.

Displaying multiple lines of text and variables in an AlertDialog using setMessage()

I need to display multiple lines of text in an Alert Dialog. If I use multiple setMessage() methods, only the last setMessage is displayed, as shown below.
final AlertDialog alertDialog = new AlertDialog.Builder(this).create();
alertDialog.setTitle("Statistics:");
alertDialog.setMessage("No. of attempts: " + counter);
alertDialog.setMessage("No. of wins: " + counterpos);
alertDialog.setMessage("No. of losses: " + counterneg);
Is there a way to create a new line for each of these in the dialog? Like using \n in System.print.out(); method.
Thanks!
You can do something like this
String alert1 = "No. of attempts: " + counter;
String alert2 = "No. of wins: " + counterpos;
String alert3 = "No. of losses: " + counterneg;
alertDialog.setMessage(alert1 +"\n"+ alert2 +"\n"+ alert3);
You could just create one string of everything you want to show and add "\n" where you'd like the line breaks to be.
alertDialog.setMessage("No. of attempts: " + counter + "\n" +
"No. of wins: " + counterpos + "\n" +
"No. of losses: " + counterneg);
Or even better to use a StringBuilder:
StringBuilder sb = new StringBuilder();
sb.append("No. of attempts: " + counter);
sb.append("\n");
sb.append("No. of wins: " + counterpos);
sb.append("\n");
sb.append("No. of losses: " + counterneg);
alertDialog.setMessage(sb.toString());
And the best way to do it would be to extract the static texts into a string resource (in the strings.xml file). Use the %d (or %s if you want to insert strings rather than ints) to get the dynamic values in the right places:
<string name="alert_message">No. of attempts: %1$d\nNo. of wins: %2$d\nNo. of losses: %3$d</string>
And then in code:
String message = getString(R.string.alert_message, counter, counterpos, counterneg);
alertDialog.setMessage(message);
You can also insert newlines directly in the strings.xml file:
<string name="my_string_text">This would revert your progress.\n\n Are you sure you want to proceed?</string>
Kotlin simplifies the solution by:
chaining the calls of the set methods
using interpolated strings
as follows:
"AlertDialog.Builder
This Builder object to allow for chaining of calls to set methods
"
(https://developer.android.com/reference/android/app/AlertDialog.Builder)
fun alertDemo() {
var counter: Int = 5
var counterpos: Int = 2
var counterneg: Int = 3
val builder = AlertDialog.Builder(this)
.setTitle("Statistics:")
.setMessage("""
|number of
|
|attempts: $counter
|wins: $counterpos
|losses: $counterneg
""".trimMargin())
.show()
}
I had prepared a screen-shot of the result, but as I am new here, I appear to have learned that uploading screenshots may be restricted to higher level community peers. Or did I miss something? Thank you for enlighting (perhaps not only) myself :)
The screenshot comes in a nice format without showing the bars.
PS:
For the minimalists, due to chaining, we could even eliminate the redundant "val builder ="

Categories

Resources