Accelerometer sampling rate jitter with 'onSensorChanged' - android

I am using a samsung galaxy ace3 to sample accelerations. getMinDelay() gives me 10 000 µs. When I log my accelerations with that period to a csv file, I get delays around the correct period with a random jitter which is sometimes huge (above 0.5 second).
Does someone know how to improve this?
Here are the delays between samples that I got.
public class MainActivity extends Activity implements SensorEventListener {
private SensorManager mSensorManager;
private Sensor mSensor;
private int cpt = 0;
private boolean start;
private List<String> records = new ArrayList<String>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
}
public final File dir = new File("/mnt/extSdCard/test/");
public FileOutputStream afos = null;
public OutputStream stream = null;
public void startButton(View view) {
start = true;
cpt = 0;
mSensorManager.registerListener((SensorEventListener) this, mSensor, 10000); // 10000 µs -> 10 ms
openCsvFiles(dir, "data.csv");
stream = new BufferedOutputStream(afos);
}
public void stopButton(View view) {
for (String record: records) {
try {
stream.write(record.getBytes());
} catch (IOException e) {
}
}
try {
stream.flush();
stream.close();
afos.close();
start = false;
} catch (IOException e) {
Toast.makeText(MainActivity.this, "exception: " + e.getMessage(), Toast.LENGTH_SHORT).show();
}
Toast.makeText(MainActivity.this, "Done", Toast.LENGTH_SHORT).show();
}
#Override
public final void onSensorChanged(SensorEvent event) {
float ax, ay, az;
String axs, ays, azs, ts, line;
if (start) {
cpt++;
ax = event.values[0];
ay = event.values[1];
az = event.values[2];
ts = String.valueOf(event.timestamp);
long ns = android.os.SystemClock.elapsedRealtimeNanos();
line = ns+", "+ cpt+", "+ ts + "," + ax + "," + ay + "," + az + "\n";
records.add(line);
}
}
}

mSensorManager.registerListener((SensorEventListener) this, mSensor, 10000);
Instead of hard coded value 10000 use SensorManager.SENSOR_DELAY_FASTEST
mSensorManager.registerListener((SensorEventListener) this, mSensor, SensorManager.SENSOR_DELAY_FASTEST);

The documentation for onSensorChanged says that you should not do much processing within the method because it blocks further samples coming in. It says that on this page:
http://developer.android.com/guide/topics/sensors/sensors_overview.html
Here, you are creating a string from the data and adding it to an ArrayList. It takes a certain amount of time to create the string, and usually that will be added quickly into the ArrayList, but there are occasions when the ArrayList will need to grow to accommodate the next object and on such occasions it takes a long time because it needs to allocate a new (larger) array internally and copy the references from the old array to the new one.
Consider adding the SensorEvent to a FIFO such as an ArrayDeque within the method and then processing these in another thread. It should improve the jitter.
I don't think the Android system provides any guarantees that the jitter will never be large, but this should help.

Related

android control to pan-tilt using accelerometer and gyroscope data

Sorry for doing this, I really don't know where to post beacuse this is both android studio code and arduino code so I post i both site.
I want to create a project of using controlling pan-tilt(2 servos combine) using the accelerometer and gyroscope data in smartphone. Creating android app and sending the accelerometer and gryroscope data to arduino so that the pan-tilt can determine its location.
My problem is when i connect the android app to arduino, no data shown in serial monitor of arduino and the pan-tilt is not locating the smartphone.
Please help me to solve this problem.....
this MainActivity is class to identify the data of accelerometer and gyrscope.
MainActivity:
public class MainActivity extends AppCompatActivity implements SensorEventListener{
private final String TAG = "MainActivity";//log our activity
SensorManager sm;//define sensor manager
Sensor accelerometer, gyrometer;//define accelerometer
TextView xValue, yValue, zValue, xGyroValue, yGyroValue, zGyroValue;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
xValue = (TextView)findViewById(R.id.xValue);
yValue = (TextView)findViewById(R.id.yValue);
zValue = (TextView)findViewById(R.id.zValue);
xGyroValue = (TextView)findViewById(R.id.xGyroValue);
yGyroValue = (TextView)findViewById(R.id.yGyroValue);
zGyroValue = (TextView)findViewById(R.id.zGyroValue);
Log.d(TAG, "onCreate: Initializing Sensor Services");
sm =(SensorManager) getSystemService(Context.SENSOR_SERVICE);//permission to use the sensor
accelerometer = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
if (accelerometer != null) {
sm.registerListener(MainActivity.this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL);
Log.d(TAG, "onCreate: Registered accelerometer listerner");
}else {
xValue.setText("accelerometer is not supported");
yValue.setText("accelerometer is not supported");
zValue.setText("accelerometer is not supported");
}
gyrometer = sm.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
if (gyrometer != null) {
sm.registerListener(MainActivity.this, gyrometer, SensorManager.SENSOR_DELAY_NORMAL);
Log.d(TAG, "onCreate: Registered gyrometer listerner");
}else {
xGyroValue.setText("gyrometer is not supported");
yGyroValue.setText("gyrometer is not supported");
zGyroValue.setText("gyrometer is not supported");
}
}
public void connect(View v){
DataSender dataSender = new DataSender();
dataSender.execute((String) xValue.getText(), toString());
dataSender.execute((String) yValue.getText(), toString());
dataSender.execute((String) zValue.getText(), toString());
dataSender.execute((String) xGyroValue.getText(), toString());
dataSender.execute((String) yGyroValue.getText(), toString());
dataSender.execute((String) zGyroValue.getText(), toString());
}
#Override
public void onSensorChanged(SensorEvent sensorEvent) {
Sensor sensor = sensorEvent.sensor;
if(sensor.getType() == Sensor.TYPE_ACCELEROMETER){
Log.d(TAG, "onSensorChanged: X: " + sensorEvent.values[0] + "Y: " + sensorEvent.values[1] + "Z:" + sensorEvent.values[2]);
xValue.setText("xValue: " + sensorEvent.values[0]);
yValue.setText("yValue: " + sensorEvent.values[1]);
zValue.setText("zValue: " + sensorEvent.values[2]);
}else if (sensor.getType() == Sensor.TYPE_GYROSCOPE){
xGyroValue.setText("xGyroValue: " + sensorEvent.values[0]);
yGyroValue.setText("yGyroValue: " + sensorEvent.values[1]);
zGyroValue.setText("zGyroValue: " + sensorEvent.values[2]);
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}
this DataSender is class for sending the data to arduino.
DataSender:
public class DataSender extends AsyncTask<String, Void, Void> {
Socket s;
DataOutputStream dos;
PrintWriter pw;
#Override
protected Void doInBackground(String... voids) {
String data = voids[0];
try {
s = new Socket("192.168.1.100",80);
pw = new PrintWriter(s.getOutputStream());
pw.write(data);
pw.flush();
pw.close();
s.close();
} catch (IOException e){
e.printStackTrace();
}
return null;
}
}
this is code that are uploaded in wifi module(esp8266-01) that are connected in arduino.
Arduino code:
#include <SoftwareSerial.h>
#include <Servo.h>
#define DEBUG true
char tiltChannel=0, panChannel=1;
//These are the objects for each servo.
Servo servoTilt, servoPan;
//This is a character that will hold data from the Serial port.
char serialChar=0;
// Center servos
int tiltVal = 90;
int panVal =90;
//smaartphone value
String inText;
float value0, value1, value2;
SoftwareSerial esp8266(10, 11); // RX, TX
void setup() { // Open serial communications and wait for port to open:
servoTilt.attach(2); //The Tilt servo is attached to pin 2.
servoPan.attach(3); //The Pan servo is attached to pin 3.
servoTilt.write(90); //Initially put the servos both
servoPan.write(90); //at 90 degress.
Serial.begin(9600); //for monitoring purposes
esp8266.begin(9600);
//sendCommand("AT+CIFS+RST\r\n", 2000, DEBUG); // reset module
sendCommand("AT+IPR=9600\r\n", 1000, DEBUG);
sendCommand("AT+CWMODE=1\r\n", 1000, DEBUG); // configure as access point
sendCommand("AT+CWJAP=\"EceConnect\",\"1234\"\r\n", 3000, DEBUG); //connec to
a network with name EceConnect with password 1234
delay(1000);
sendCommand("AT+CIFSR\r\n", 1000, DEBUG); // get ip address
sendCommand("AT+CIPSTA=\"192.168.1.100\"\r\n", 1000, DEBUG);
sendCommand("AT+CIPMUX=1\r\n", 1000, DEBUG); // configure for multiple
connections
sendCommand("AT+CIPSERVER=1,80\r\n", 1000, DEBUG); // turn on server on port
80
Serial.println("Server Ready");
Serial.println("Android Sensor Type No: ");
Serial.println("1- ACCELEROMETER (m/s^2 - X,Y,Z)");
Serial.println("2- GYROSCOPE (rad/s - X,Y,Z)");
Serial.flush();
}
void loop() { // run over and over
Serial.flush();
int inCommand = 0;
int sensorType = 0;
unsigned long logCount = 0L;
if (Serial.available() < 1) return; // if serial empty, return to loop().
char getChar = ' ';
if (esp8266.available()) {
if (esp8266.find("+IPD,0,")) {
delay(10);
esp8266.find(":");
delay(10);
char letter = esp8266.read();
Serial.print(letter); //for monitoring purposes
//Gets the value/char from android app
}
}
// parse incoming command start flag
if (getChar != serialChar) return; // if no command start flag, return to
loop().
// parse incoming pin# and value
sensorType = Serial.parseInt(); // read sensor typr
logCount = Serial.parseInt(); // read total logged sensor readings
value0 = Serial.parseFloat(); // 1st sensor value
value1 = Serial.parseFloat(); // 2rd sensor value if exists
value2 = Serial.parseFloat(); // 3rd sensor value if exists
// send smartphone readings to serial monitor/terminal
if (DEBUG) {
Serial.print("Sensor type: ");
Serial.println(sensorType);
Serial.print("Sensor log#: ");
Serial.println(logCount);
Serial.print("Val[0]: ");
Serial.println(value0);
Serial.print("Val[1]: ");
Serial.println(value1);
Serial.print("Val[2]: ");
Serial.println(value2);
Serial.println("-----------------------");
delay(10);
}
// Check sensor type. If not for Accelerometer (#1) then ignore readings
// sensorType 1 is the Accelerometer sensor
if (sensorType !=1) return;
panVal = value0; // value0 = X sensor reading
tiltVal = value1; // value1 = Y sensor reading
tiltVal = map(tiltVal, 10, -10, 0, 179); // Map Accelerometer Y value to
tilt servo angle.
servoTilt.write(tiltVal);
delay(10);
panVal = map(panVal, -10, 10, 0, 179); // Map Accelerometer X value to pan
servo angle.
servoPan.write(panVal);
delay(10);
}
String sendCommand(String command, const int timeout, boolean debug) {
String response = "";
esp8266.print(command); // send the read character to the esp8266
long int time = millis();
while ((time + timeout) > millis()) {
while (esp8266.available()) {
// The esp has data so display its output to the serial window
char c = esp8266.read(); // read the next character.
response += c;
}
}
if (debug) {
Serial.print(response);
}
return response;
}

Max rate to stream sensor data from Android Wearable

I am developing an app that requires real time sensor data streaming from a wearable. I am using an LG G watch and the accelerometer and gyroscope sensors.
The sensor data and system current time are packaged as an array of 4 bytes for each axis of each sensor X 32 samples (hence 4 X 3 X COUNT.
This data is then sent through the message api.
Main question:
I have registered the sensors with fastest update rate (SENSOR_DELAY_FASTEST) and when I analyze the data samples I have captured with the mobile device, the time step is roughly 200ms per sample (roughly 5 HZ).
I am expecting much faster.
Am I limited by:
1) bluetooth 4.0 bandwith
2) LG G watch sensor (it's an Invensense and the bandwidth should be much higher)... or
3) the message API
Would DataApi allow me to stream data to the mobile device much faster?
Here is a section of my code:
static final int COUNT = 32;
static ByteBuffer AcceleratorBuffer = ByteBuffer.allocate((4 * 3 * COUNT) + (8 * 1 * COUNT));
static ByteBuffer GyroBuffer = ByteBuffer.allocate((4 * 3 * COUNT) + (8 * 1 * COUNT));
static int accelerator_cycle = 0;
static int gyro_cycle = 0;
static AcceleratorWearSensorListener mAcceleratorSensorEventListener = null;
static GyroWearSensorListener mGyroSensorEventListener = null;
static class GyroWearSensorListener implements SensorEventListener {
GoogleApiClient mGoogleApiClient;
public GyroWearSensorListener(GoogleApiClient mGoogleApiClient) {
this.mGoogleApiClient = mGoogleApiClient;
}
#Override
public void onSensorChanged(SensorEvent event) {
if (On) {
Float x = event.values[0];
Float y = event.values[1];
Float z = event.values[2];
Log.i(TAG, "Gyro x: " + x + " y: " + y + " z: " + z);
GyroBuffer.putFloat(x).putFloat(y).putFloat(z).putLong(System.currentTimeMillis()).array();
++gyro_cycle;
if (gyro_cycle % COUNT == 0) {
Wearable.NodeApi.getConnectedNodes(mGoogleApiClient)
.setResultCallback(new ResultCallback<NodeApi.GetConnectedNodesResult>() {
#Override
public void onResult(NodeApi.GetConnectedNodesResult nodes) {
Log.i(TAG, "Nodes size : " + nodes.getNodes().size());
for (Node node : nodes.getNodes()) {
if (node != null && mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
Wearable.MessageApi.sendMessage(
mGoogleApiClient, node.getId(), GYROSCOPE_DATA_PACKET, GyroBuffer.array())
.setResultCallback(
new ResultCallback<MessageApi.SendMessageResult>() {
#Override
public void onResult(MessageApi.SendMessageResult sendMessageResult) {
if (!sendMessageResult.getStatus().isSuccess()) {
Log.e(TAG, "Failed to send message with status code: "
+ sendMessageResult.getStatus().getStatusCode());
} else {
Log.e(TAG, "send gyro data successfully ");
}
}
}
);
} else {
Log.e(TAG, "node null or client null or not connected. ");
}
}
}
});
GyroBuffer.clear();
gyro_cycle = 0;
}
}
}

Android app to display and log sensor data

I'm new to Android programming and i'm trying to understand the control flow in android programs. I've been working on a program to log and display sensor data.
public class MainActivity extends ActionBarActivity implements SensorEventListener
This is the main class with onCreate(), btnStart.setOnClickListener(new OnClickListener(), btnStop.setOnClickListener(new OnClickListener(), onSensorChanged(SensorEvent event) which do most of the important tasks.
onCreate() has all this code:
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
title = (TextView)findViewById(R.id.titleView);
acc_x = (TextView)findViewById(R.id.acc_x_values);
acc_y = (TextView)findViewById(R.id.acc_y_values);
acc_z = (TextView)findViewById(R.id.acc_z_values);
x = (TextView)findViewById(R.id.acc_x);
y = (TextView)findViewById(R.id.acc_y);
z = (TextView)findViewById(R.id.acc_z);
btnStart = (Button)findViewById(R.id.button_start);
btnStop = (Button)findViewById(R.id.button_stop);
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
mAccel = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
sensorManager.registerListener(this,sensorManager.getDefaultSensor(sensorType), 20000);
And the start and stop button funtionalities are defined here.
btnStart.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
startFlag = true;
String storepath = Environment.getExternalStorageDirectory().getPath();
System.out.println("Stored at" +storepath); // /storage/sdcard
Toast.makeText(getBaseContext(), "Started Recording Data and Storing at"+storepath, Toast.LENGTH_SHORT).show();
try {
myFile = new File(storepath + "/GaitApp/" + name.getText() + "_acc.csv");
myFile.createNewFile();
fOut = new FileOutputStream(myFile);
myOutWriter = new OutputStreamWriter(fOut);
myBufferedWriter = new BufferedWriter(myOutWriter);
myPrintWriter = new PrintWriter(myBufferedWriter);
} catch (Exception e) {
Toast.makeText(getBaseContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
}
} //onclick
}); //startbutton
btnStop.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Toast.makeText(getBaseContext(), "Stopped Recording",Toast.LENGTH_SHORT).show();
startFlag = false;
try {
fOut.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}// onClick
}); // btnstopButton
onSensorChanged() is:
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
if(startFlag){
float[] values = event.values;
// Movement
float x_float = values[0];
float y_float = values[1];
float z_float = values[2];
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
String currentDateandTime = sdf.format(new Date());
long curTime = System.currentTimeMillis();
if ((curTime - lastUpdate) > 20) {
long diffTime = (curTime - lastUpdate);
lastUpdate = curTime;
x_float = event.values[0];
y_float = event.values[1];
z_float = event.values[2];
acc_x.setText(Float.toString(x_float));
acc_y.setText(Float.toString(y_float));
acc_z.setText(Float.toString(z_float));
String res=String.valueOf(currentDateandTime+", "+x_float)+", "+String.valueOf(y_float)+", "+String.valueOf(z_float+"\n");
Log.d("test", res);
for (int i = 0; i % 1 == 0; i++) {
if (startFlag) {
try{
fOut = new FileOutputStream(myFile);
myOutWriter = new OutputStreamWriter(fOut);
myBufferedWriter = new BufferedWriter(myOutWriter);
myPrintWriter = new PrintWriter(myBufferedWriter);
myPrintWriter.append(curTime - lastUpdate + ", " + x_float + ", " + y_float + ", " + z_float+ "\n");
}
catch (IOException e){
System.out.println("Exception: "+e);
}
//myPrintWriter.write(curTime - lastUpdate + ", " + x_float + ", " + y_float + ", " + z_float+ "\n");
} //startFlag is true
else {
try {
myOutWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
fOut.close();
} catch (IOException e) {
e.printStackTrace();
} // catch
} // else
} //for
} // if -- time
} // startFlag
} //accelerometer -- sensor
} // onSensorChanged
I'm trying to understand how the onSensorChanged() transfers control and in the process the acceleration data to onCreate() to be displayed and stored.
The onCreate method is only used to initially setup the view. Updates to the display must occur by deliberately invoking them. Furthermore updates to the UI must occur on the UI thread. Since the onSensorChanged call can occur asynchronously, if you wish sensor updates to trigger a display update you must send yourself a UI thread event. One option is to use a handler such as in the following untested code.
private Handler mHandler;
public void onCreate() {
mHandler = new Handler();
}
#Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
saveData(event);
final long currentTime = System.currentTimeMillis();
if (isResumed() && currentTime > (lasttime + SOME_DELAY)) {
lasttime = currentTime;
handler.post(new Runnable() {
#Override
public void run() {
updateDisplay(event);
}
});
}
}
}
private void updateDisplay(SensorEvent event) {
acc_x.setText(...);
acc_y.setText(...);
acc_z.setText(...);
x.setText(...);
y.setText(...);
z.setText(...);
}
Depending on your application you may wish to log your data in a service.
onSensorChanged() is the handler in this case. This call back function takes care of updating the UI and writing to the file.

Android-Buffering values to minimize the number of disk writes?

In my Android application I am reading brain data values from an EEG headset. These values are then being written to a Text File.
The problem with this is that the values are being produced 500 times a seconds. As a result they are also being written to the text file 500 times a second, which I don't want.
I only want the values to be displayed in the text file once a second. I was reading about buffering to do so.
How could I use buffering in my case to solve the problem?
Below is my current android code, and also rough pseudo code for what i'm trying to achieve.
Current Android code:
Method used to save the data to file:
public void writeToFileRawData(String data) {
// creating the file where the contents will be written to
File file = new File(dir, fileNameRaw + ".txt");
FileOutputStream os;
try {
boolean append = true;
os = new FileOutputStream(file, append);
String writeMe = data + "\n";
os.write(writeMe.getBytes());
os.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
Calling the above method within the handler for the Headset Values:
Note: in code below "order" is irrelevant, it is just a method used for formatting the txt.
final Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
// msg.what determines the type of each message
switch (msg.what) {
case TGDevice.MSG_RAW_DATA:
// creating the string to be written to file
String line2 = order(seconds2 + "") + order("" + msg.arg1)
+ "\n";
// write the string to file
writeToFileRawData(line2);
break;
Rough Pseudo code for what I am trying to achieve:
brainWaveRaw
time voltage
xxx yyyy
xxx yyyy
[and there should be 500 of these per second]
(buffer these to minimize number of disk writes)
// initialize
timeOfLastRawWrite = timeNow
rawWriteStringBuffer = ''
rawEvent(raw (list of last one or few raw samples))
eventTime = timeNow
for every entry r in raw
rawWriteStringBuffer.append(printf("%d %d\n", eventTime, r))
if timeNow-timeOfLastRawWrite > one second
write rawWriteStringBuffer to file
rawWriteStringBuffer = ''
timeOfLastRawWrite = timeNow
// e.g. if last set of raw values was [123, 456, 678], arrived at time
9876
9876 123
9876 456
9876 678
Don't open the file every time.
Use BufferedOutputStream.
You might want to flush the stream every several times.
Handler mHandler; // member of your Activity class
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final String dir = ...;
final String fileNameRaw = ...;
mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
// msg.what determines the type of each message
switch (msg.what) {
case TGDevice.MSG_RAW_DATA:
// creating the string to be written to file
String line2 = order(seconds2 + "") + order("" + msg.arg1)
+ "\n";
// write the string to file
writeToFileRawData(line2);
break;
}
}
// members of your custom Handler class
private File mFile = new File(dir, fileNameRaw + ".txt");
private BufferedOutputStream mOs = new BufferedOutputStream(new FileOutputStream(mFile, true));
private int mWriteCnt = 0;
// moved this function from Activity to your custom Handler class as well
private void writeToFileRawData(String data) {
try {
mOs.write(data.getBytes());
mOs.write("\n".getBytes());
if (++mWriteCnt == 500) {
mOs.flush();
mWriteCnt = 0;
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

Android parsing ints efficiency

I am trying to parse some unsigned integers from a file stored on the memory card.
Since java does not provide unsigned types I use longs to store the obtained values.
The performance seems to be influenced by the Debugger:
Without the debugger connected I can parse 20000 values in ~820ms.
With the debugger ~5800ms (on HTC Desire).
Can you reproduce this on your devices? Any clue why the debugger has such an overhead?
Here is the code:
public class IntParsingTest extends Activity {
public static final String TEST_FILE = "yourfile";
public static final int LOOPS = 20000;
private Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Toast.makeText(IntParsingTest.this, (CharSequence) msg.obj, Toast.LENGTH_LONG).show();
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
try {
Runnable r = new Runnable() {
#Override
public void run() {
Message m = new Message();
File path = Environment.getExternalStorageDirectory();
File f = new File(path, TEST_FILE);
long startTime = SystemClock.currentThreadTimeMillis();
try {
InputStream is = new FileInputStream(f);
for (int i = 0; i < LOOPS; i++) {
readUnsignedInt(is);
}
long total = SystemClock.currentThreadTimeMillis() - startTime;
m.obj = "Time to parse\r\n"
+ LOOPS
+ " unsigned integers:\r\n"
+ total + " ms";
handler.sendMessage(m);
} catch (Exception e) {
m.obj = e.getMessage();
handler.sendMessage(m);
}
}
};
new Thread(r).start();
} catch (Exception e) {
}
}
public static long readUnsignedInt(InputStream input) throws IOException {
long b1 = input.read();
long b2 = input.read();
long b3 = input.read();
long b4 = input.read();
return (b1 << 24) + (b2 << 16) + (b3 << 8) + b4;
}
}
Edit: It is also interesting that only the shift opperations are slow. If I return one of the bytes or a sum of them it works much faster. It may be the way shift is implemented !?
I'm guessing here - with debugger connected JVM cannot do just-in-time compilation; to be able to detect breakpoints it has to do bytecode interpretation all the time. Debugger also connects to device log stream, which may cause some overhead.

Categories

Resources