android writing files from onSensorChanged event - android

I confess I'm a bit stumped on this one. I've just started with Android programming and am loving the experience so far, but I've got a mysterious problem where I write to files but they remain indefinitely empty (no, I'm pretty sure I'm not overwriting them accidentally).
The scenario is that I'd like to record a few seconds of sensor data to a log file on the SD card upon hitting a button. I also display the same content to the screen. However, though the content that appears on the screen is correct, the log file gets created but is empty.
I can only assume that it has something to do with the fact that I'm calling write from the onSensorChanged(Event) method, since the same code executes just fine when used elsewhere.
public MyClass(....){
....
sensorManager.registerListener(this, accelerometer, sensorManager.SENSOR_DELAY_NORMAL);
Thread.sleep(time * 1000);
sensorManager.unregisterListener(this);
try {
logWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public void onSensorChanged(SensorEvent event){
String msg = msgFor(event);
try {
logWriter.write("SOME_TEXT" + msg + "\n"); // FileWriter logWriter is a field, but the file is empty in the end
} catch (IOException e){
e.printStackTrace();
}
resultBox.append("\n" + msg); // TextView resultBox is a field, and writes to screen correctly
Log.d("SENSOR-CHANGE", msg);
}
private String msgFor(SensorEvent event){
return event.timestamp+", "+event.sensor.getName()+", "+Arrays.toString(event.values);
}
Any advice would be greatly appreciated! I am aware that there are some similar threads out there, but I didn't find exactly what I needed.

Related

Android SensorDirectChannel returns no sensor measurements

I'm trying to use the SensorDirectChannel added in Andriod 8. With the memory file as shared medium it is all zero. Using the hardware buffer the returned array is of size zero.
I initiate the SensorDirectChannel like this:
if (mSensor.isDirectChannelTypeSupported(SensorDirectChannel.TYPE_HARDWARE_BUFFER)) {
try {
hawBuff = HardwareBuffer.create(1040, 1, HardwareBuffer.BLOB, 1, HardwareBuffer.USAGE_SENSOR_DIRECT_DATA);
mSensorDirectChannelBuff = mSensorManager.createDirectChannel(hawBuff);
mSensorDirectChannelBuff.configure(mSensor, SensorDirectChannel.RATE_FAST);
} catch (Exception e) {
e.printStackTrace();
}
}
Then I try to read from the hardware buffer like this:
if (mSensorDirectChannelBuff.isOpen()) {
Parcel measurement = Parcel.obtain();
hawBuff.writeToParcel(measurement, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
int[] measurementArray = measurement.createIntArray();
try {
Log.d("SensorDirectChannel", "HardwareBuffer: " + measurementArray[0]);
} catch (Exception e) {
Log.e("HardwareBuffer", "array is empty");
e.printStackTrace();
}
}
The array is always of size zero.
I don't know if I missed something in the docs or what I'm doing wrong.
Does someone have an idea what's wrong?
Now, after some software updates, the smartphone does no longer support sensor direct channels. The line mSensor.isDirectChannelTypeSupported(SensorDirectChannel.TYPE_HARDWARE_BUFFER) now returns false. The same is the case for the memory file option.
So I guess it never worked from the start, causing my problems trying to use it.

Optimising Android file writing

I am currently writing an android app that logs the accelerometer. (its a test app at the moment so i can prototype an algorithm.
To write out a list of SensorEventStore's (which is just a way of storing the data from a SensorEvent) to the SD card from a 30 minute recording, locks up the GUI for about 20 - 30 seconds while writing the file.
I am using the following code to write out the file to the SD card.
#Override
public void onMessage(Messages message, Object param[]) {
if(message == IDigest.Messages.SaveData) {
File folder = (File) param[0];
File accFileAll = new File(folder, startTime + "_all.acc");
FileWriter accFileWriterAll;
try {
accFileWriterAll = new FileWriter(accFileAll);
} catch (IOException e) {
accFileWriterAll = null;
}
for(Iterator<SensorEventStore> i=eventList.iterator(); i.hasNext();) {
SensorEventStore e = i.next();
if(accFileWriterAll != null) {
try {
accFileWriterAll.write(
String.format(
"%d,%d,%f,%f,%f\r\n",
e.timestamp,
e.accuracy,
e.values[0],
e.values[1],
e.values[2]
)
);
accFileWriterAll.flush();
} catch (IOException ex) {
}
}
}
new SingleMediaScanner(RunBuddyApplication.Context, accFileAll);
}
}
Can anyone give me any pointers to make this not lock up the UI, or not have to take the amount of time it currently takes to write out the file.
Firstly you should try to do this in the background. The AsyncTask is fairly well suited for the task.
Other than that, you should remove the flush() statement, and probperly close() your file writer. The flush causes the data to be written to disk in rather small portions, which is really slow. If you leave the filewriter to its own flushing, it will determine a buffer size on its own. When you properly close the FileWriter, the remaining data should be written to disk as well.
Also, you could take a look at "Try with resources" for your filewriter, but that is optional.

File data storing

i did an application to collects light sensor data, such that these data are stored in text file in the external sdcard, the data is stored correctly and file are created successfully but the problem is when then application running on the my device for x period (e.g 1 min)the data is stored but when is close the application and re running it on from the device for the same period also the new collected data are append stored to the previous stored data from previous running and i noted that when the sizes of the text files is increases with each running.
i need for each running ,the collected data is stored totally (for the whole period of the running i.e 1 min ) in the text file and when i re- running the application again the new collected data of the new running to be overwriting on previous stored data.
i attempted to do that using arraylist, i .e when then app starts running i put all gathered reading in array list and when the running is stopped the arraylist will out all gathered data to the text file but when i re-running app the array list also gathered data and append out it into the text file next to the previous running stored data, where this is the problem which need to solve,i need to overwrite new running gathered data on the previous running stored data.
the code of collecting light sensor data looks like:
#Override
public void onSensorChanged(SensorEvent event) {
if(event.sensor.getType()==Sensor.TYPE_LIGHT){
max = msensorManager.getDefaultSensor(Sensor.TYPE_LIGHT).getMaximumRange();
//getMaximumRange() is the maximum range of the sensor in the sensor's unit.
//tv1.setText("Max Reading: " + String.valueOf(max));
tv1.setText(msg +"Max Reading: " + String.valueOf(max) );
tv1.invalidate();
lightMeter.setMax((int)max);
//setMax is the max of the upper range of this progress bar
currentReading = event.values[0];
//timestamp = event.timestamp;
lightMeter.setProgress((int)currentReading);
Toast.makeText(MainActivity.this,"Event Happend '", Toast.LENGTH_SHORT).show();
tv2.setText("Current Reading: " + String.valueOf(currentReading));
current_reading_list.add((double) currentReading);
}
the code of writing from array list into file looks like :
public void writing_in_file_1(){
try{
fw = new FileWriter(file_1, true);
bw = new BufferedWriter(fw);
out = new PrintWriter(bw);
//out.append( String.valueOf(currentReading + " \t"));
//out.append(String.valueOf(current_reading_list));
out.print(String.valueOf(current_reading_list));
out.flush();
Toast.makeText(this,"Done writing SD 'specific text file'", Toast.LENGTH_SHORT).show();
}
catch (IOException e)
{
e.printStackTrace();
}
finally{
try {
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
the writing is done when the stop button is pressed:
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.bt1:
counter_function();
//onResume();
break;
case R.id.bt2:
onPause();
writing_in_file_1();
tv1.setText("");
tv2.setText("");
break;
default:
break;
}
}
can any one help me?
thank you in advance.
You are using the constructor FileWriter(File file, boolean append) with append = true
Replace
fw = new FileWriter(file_1, true);
with
fw = new FileWriter(file_1, false);

Need some explaining

So this is the weirdest thing ever to happen to me during programing. Yes I'm no pro at programing, but I'm learning as I go. I've got an app talking to a server, a socket in the main thread, reading is done in a separate class and thread and writing in a separate class with asynctask.
The problem is LocationManager. I could talk to server and write/read commands just fine, I implemented the LocationManager and its listener.
I then proceeded to implement a method to update my textview with the new coordinates on locatinChanged. So far so good. Thing is when I use the Emulator control in eclipse and send coordinates the app crashed with a stringOutOfBoundsException (I've programed for 3 years now never seen this). I looked at the code stepped through it and so on. Read the stacktrace, logcat, console and everywhere I could think of but it got me nowhere. Until I finally went to the readerthread which looks like this:
public class ReaderThread extends Thread {
public void run() {
new Thread(new Runnable(){
public void run(){
try {
//Establish a bufferedreader to read from the socket/server.
in = new BufferedReader(new InputStreamReader(socket.getInputStream()), 8 * 1024);
}
catch(Exception e) { e.printStackTrace(); }
//As long as connect is true.
while (connected) {
String line;
try {
//Try to read a line from the reader.
line = in.readLine();
System.out.println(in.readLine());
if (in == null) {
//No one has sent a message yet.
System.out.println("No data recieved");
}
else {
int i = 0;
//As long as someone is sending messages.
while((line = in.readLine()) != null ){
//Make a new Message.
Message msg;
msg = new Message();
//Set the object to the input line.
msg.obj = line;
//Set an id so it can be identified in the main class and used in a switch.
msg.what = i;
System.out.println("i is: "+i);
//Send the message to the handler.
Main.this.h.sendMessage(msg);
}
}
}
catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
}).start();
}
The variable i is in an if statement depending on what the server sent but I cut that out as it has nothing to do with this problem.
The problem is the freaking catch. When the catch is IOException, the app crashes. Out of dumb luck I changed this to Exception and printed e.message to catch the error and see what caused it. Thing is this change fixed it. How can switching IOException to just plain Exception fix a problem like this?
Its like with IOException the program says: "hey your not gonna catch the error but there is no error" but with Exception it says "Well now you could catch it so I'll proceed".
My app is working but I just can't grasp this, why and how does this happen?
You're essentially telling the application to catch the base Exception class. This means that any type of error will be caught, since all exception classes descend from that base type. Since StringOutOfBoundsException does not descend from IOException it was not being caught before and the error was not being caught. Instead of catching all exceptions, you might try the following:
try {
// Your code here...
} catch (IOException e) {
Log.e(TAG, "Caught an IOException!", e);
} catch (StringOutOfBoundsException e) {
Log.e(TAG, "Caught a string out of bounds Exception!", e);
}
I'm unable to determine what is actually throwing the StringOutOfBoundsException to begin with. It may be in the if statement that you cut out of your example.
while (connected) {
String line;
try {
//Try to read a line from the reader.
line = in.readLine();
System.out.println(in.readLine());
if (in == null) {
//No one has sent a message yet.
System.out.println("No data recieved");
}
The test for in == null is in a funny location. You should receive a NullPointerException if that test were to ever return true by nature of calling methods on it a few lines earlier. Obviously something is a little funny with this code.
You fail to save the return value from in.readLine() the second time you call it. I hope it did not contain anything useful. (Though, since you print the line, you obviously wanted to know what data it contained.)
Whatever that line was (from the first call to in.readLine()), it gets thrown away; there's nothing else in the loop that uses it before it is over-written on this line:
while((line = in.readLine()) != null ){
At this point, the two lines that you read are gone forever.
I'm not entirely sure what should be done to fix this; if it were me, I'd be sorely tempted to start over with a sheet of paper and sketch out what the method should be doing without looking at the existing code, then compare the sketch against the code to see which cases each one has overlooked.

Android asynctask reading from socket

Im having some trouble reading/writing to a tcp server for which im building an app. In a recent thread I was suggested to use a service instead but this is a project for school which suggested asyncTask so I might aswell go for that.
So the classes ive got are my activity class and async, nothing interesting is going on in activity but sending a string which is working so ill get on with the async one.
class ServerTask extends AsyncTask<Void, Void, Void>{
public static String ip = "10.0.2.2";
public static int port = 2002;
Socket socket;
public DataInputStream dis;
public DataOutputStream dos;
public String message;
#Override
protected Void doInBackground(Void... params) {
try {
socket = new Socket(ip, port);
dis = new DataInputStream(socket.getInputStream());
dos = new DataOutputStream(socket.getOutputStream());
} catch (Exception e) {
Log.i("AsyncTank", "Cannot create Socket");
}
while(socket.isConnected()){
read();
}
}
}
return null;
}
public void write(String message) {
try {
if (socket.isConnected()){
dos.writeUTF(message);
dos.flush();
} else {
Log.i("AsynkTask", "Socket appears to be closed");
}
} catch (Exception e) {
Log.i("AsynkTask", "Writing failed");
}
}
public String read() {
try {
if (socket.isConnected()) {
message = dis.readLine();
} else {
Log.i("AsyncTask", "Cannot read");
}
} catch (Exception e) {
Log.i("AsyncTask", "Cannot read from stream");
}
return message;
}
}
Things I do know, the server DOES get the messages but it doesnt update until I restart the server which leads me to believe that im not pushing a new line or something which makes it all appear as one line after its closed. This however might aswell be the server for which im not reponsible so ill have to read up in that.
The read part however does not want to work, im not sure on how to call the method to have it constantly listen and react to the servers sockt? I tried make a thread just before the return in doInBackGround but then the application starts works for a couple of seconds the force closes due to lack of memory? Do I need a thread to keep constantly listen?
The whole point of this as you might guess is to make a chat so the read method is eventually supposed to update a textView in my activity class. The send method is "working" but not as it should though this might be as I said earlier the server doing some funky buisness.
Another one, is it even possible to have the read as a method like I have or does something have to react when the server sends data and then call the method?
Edit
I have now moved the read part, or atleast some of it to doInBackGround so its now
dis = new BufferedReader(new InputStreamReader(socket.getInputStream()));
message = dis.readLine();
Log.i("AsynkTask", "Read : "+message+" this is doInBackGround!");
This along with a change to simply hardcode a printline in the server made me read that line in the client so im guessing its working realtively good for now.
How is it looking? Is it utter crap this code and should be done some other way? Got my functionality but never bad to learn to do it better so to speak :).
You should do both your writing and reading to the Socket in an AsyncTask's doInBackground() method, as both take time and could block the main (UI) thread. I don't know how you are calling your write() method above but you might also want to take a look at this question that might be related.

Categories

Resources