Android Sensor Data Logging

I have an Android app that registers several Android sensors at approximately 100 Hz. Therefore, if I register 10 sensors, I write about 3,000 data per second to a file (each sensor usually has 3 entries). Now the problem is that I want to minimize the effect of this entry in the rest of the application. In particular, I don’t want logging to slow down the delivery of events ... I want to make sure that I receive events as soon as they happen, and not with a delay (I know there will always be some kind of delay because Android does not in real time and because of the "traction" nature of the Sensor event environment).

Next, I will describe my approach, which does not seem to work well. I would like suggestions for improvement.

My current procedure is ...

For each sensor, I create a separate stream with BlockingQueue of events for registration. Inside the stream, I have a while loop that gets pulled out of the queue and writes the file using a buffered writer. When the sensor manager delivers a new SensorEvent, the event is placed in the appropriate queue (thereby starting the IO file on another stream) so as not to delay the main stream to which SensorEvents are transmitted.

I want to receive events as soon as they appear, so it is important that I do not introduce any delays in the Sensor infrastructure. If, for example, I made an IO file directly in the onEvent callback, then I worry that events may begin to accumulate in the pipeline and that they will be outdated by the time they are finally delivered. The above approach mitigates these concerns.

But there is one more problem ...

, IO , . , (, 5 1 ). , IO , . :

  • -. , , , , . , IO, , , .

  • , . . , , , ... , . , , IO . ?

  • , , , - .

?


:

, . SensorEvent.

package io.pcess.utils;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * This type of File Writer internally creates a low-priority {@link Thread}
 * which queues data to be written to a specified file. Note that the
 * constructor starts the {@link Thread}. Furthermore, you can then append a
 * {@link String} to the end of the specified file by calling
 *
 * <pre>
 * fileWritingThread.append(stringToAppend);
 * </pre>
 *
 * Finally, you should tidy up by calling
 *
 * <pre>
 * fileWritingThread.close();
 * </pre>
 *
 * which will force the writer to finish what it is doing and close. Note that
 * some {@link String}s might be left in the queue when closing, and hence will
 * never be written.
 */
public class NonblockingFileWriter {

    /**
     * ---------------------------------------------
     *
     * Private Fields
     *
     * ---------------------------------------------
     */
    /** The {@link Thread} on which the file writing will occur. */
    private Thread                      thread     = null;

    /** The writer which does the actual file writing. **/
    private BufferedWriter              writer     = null;

    /** A Lock for the {@link #writer} to ensure thread-safeness */
    private final Object                writerLock = new Object();

    /** {@link BlockingQueue} of data to write **/
    private final BlockingQueue<String> data       = new LinkedBlockingQueue<String>();

    /** Flag indicating whether the {@link Runnable} is running. **/
    private volatile boolean            running    = false;

    /**
     * The {@link Runnable} which will do the actual file writing. This method
     * will keep writing until there is no more data in the list to write. Then
     * it will wait until more data is supplied, and continue.
     */
    private class FileWritingRunnable implements Runnable {

        @Override
        public void run() {
            try {
                while (running) {
                    String string = data.take();
                    synchronized (writerLock) {
                        if (writer != null) {
                            writer.write(string);
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                close();
            }
        }
    };

    /**
     * ---------------------------------------------
     *
     * Constructors
     *
     * ---------------------------------------------
     */
    public NonblockingFileWriter(String filename) {
        this(new File(filename));
    }

    public NonblockingFileWriter(File file) {
        writer = createWriter(file);
        if (writer != null) {
            running = true;
        }
        thread = new Thread(new FileWritingRunnable());
        thread.setPriority(Thread.MIN_PRIORITY);
        thread.start();
    }

    /**
     * ---------------------------------------------
     *
     * Public Methods
     *
     * ---------------------------------------------
     */
    /** Append the specified string to the file. */
    public void append(String string) {
        try {
            data.put(string);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }

    /**
     * Close the {@link BufferedWriter} and force the {@link Thread} to stop.
     */
    public void close() {
        running = false;
        try {
            synchronized (writerLock) {
                if (writer != null) {
                    writer.close();
                    writer = null;
                }
            }
            /**
             * This string will not be written, but ensures that this Runnable
             * will run to the end
             */
            data.put("Exit");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Create a {@link BufferedWriter} for the specified file.
     *
     * @param file
     * @return
     */
    private BufferedWriter createWriter(File file) {
        BufferedWriter writer = null;
        if (!file.exists()) {
            try {
                file.getParentFile().mkdirs();
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
                return writer;
            }
        }
        if (file.canWrite()) {
            boolean append = true;
            try {
                synchronized (writerLock) {
                    writer = new BufferedWriter(new FileWriter(file, append));
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return writer;
    }

}
+4
3

, , . , 1 3 . 2 ; , , , , , / C API, .

GC, Looper (api) Handler (api). , BlockingQueue , GC. , .

, -/ Clean Code, , ( , ), .

IO-: , , , . Stream Writer, , , flush().

+2

, , , :

  • , Looper, Barend, , , , , , , .

  • , Android , , , .

  • GC'ing , () , , . , .

, .

0

https://docs.oracle.com/javase/7/docs/api/java/math/BigInteger.html#toByteArray()

IO, . , . . 3000 . 20 480 .

, , , instagram , "".

GC GC ? . , , . . .

. asycronous . . , . , . , , . , .

. , encyption SDCard, , .

0

Source: https://habr.com/ru/post/1675736/


All Articles