I writing an android timer app that uses System.nanotime. The issue is that it's giving me underpredicted results as well negative numbers. redVal, blueVal, and greenVal are updated on each frame of the camera.
results
504455566
-95947265
9063721
61035
-99487305
-98937988
12664795
-75317382
code
for (testAmount = 0; testAmount < 80; testAmount++) {
runOnUiThread(new Runnable() {
public void run() {
lagSquare.setBackgroundColor(Color.rgb(255, 255, 255));
lagStartTime = System.nanoTime(); //start lagTimer start
}
});
while (redVal <= 100.0 && blueVal <= 100.0 && greenVal <= 100.0) {
x=0;
}
runOnUiThread(new Runnable() {
public void run() {
lagEndTime = System.nanoTime(); //start lagTimer end
lagSquare.setBackgroundColor(Color.rgb(000, 000, 000));//set lagSquare black
}
});
lagTimeResult = (lagEndTime - lagStartTime);
timeArray[testAmount] = lagTimeResult;
Log.i("LTR", String.valueOf(lagTimeResult));
try {
Thread.sleep(60);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
You are trying to output a time difference which is relying upon values being set in different threads, without any synchronization. This will almost always end up with the wrong value:
for (testAmount = 0; testAmount < 80; testAmount++) {
// this will schedule the Runnable to run *sometime* in
// the future - but not necessarily right now
runOnUiThread(new Runnable() {
public void run() {
lagStartTime = System.nanoTime(); //start lagTimer start
}
});
// this will also schedule this Runnable to run *sometime* in
// the future - but not necessarily after the first one
runOnUiThread(new Runnable() {
public void run() {
lagEndTime = System.nanoTime(); //start lagTimer end
}
});
// this will probably execute first (before either of
// the other Runnables have completed)
lagTimeResult = (lagEndTime - lagStartTime);
}
You simply can't rely on the order of threads executing in the order you've coded them - and definitely not in a loop.
I can't understand from your question what you are trying to time, but the take-home rule is that whenever you have multiple threads, you can never rely on the order of execution without using some form of synchronization.
Related
I write a simple AsyncTask which:
#Override
protected Void doInBackground(Void... params) {
for (int i = 0; i <= 99; i++) {
long time = System.currentTimeMillis();
try {
//Wait for 6ms
Thread.sleep(6);
} catch (InterruptedException e) {
e.printStackTrace();
}
long diff = System.currentTimeMillis() - time;
Log.d(TAG, "Row "i + " is DONE with timeDiff=" + diff + "ms vs. waitTime=" + waitTime + "ms");
publishProgress(i);
}
}
It works well in some of test devices until I try on LG devices (Nexus 4, G3): time to sleep seems longer than I think. After checking log, I see in normal case, timeDiff is 6ms or 7ms; while with LG devices, timeDiff is mostly > 40ms.
Also try to use SystemClock.sleep() but no luck.
Could anyone please suggest me how to fix it? Any help would be appreciated!
Alternate solution is use Handler for wait.
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
//call after delay
}
}, 2000);
I have setup two commands in Oncreate and both send data to a bluetooth device. I need the 2nd command to wait for a data string to be received from the 1st command before advancing to the 2nd command. Each command just send a byte to BT. I tried a while looping true but does not seam to work and hangs on the while true statement. I assume the while true is not letting the handler fire when in the loop. Both commands work fine individually as long as I don't send both.
This is the code in Oncreate with both commands and while true statement
looping=true;
intByteCount =9;
GetData(intCommand); // (Command 1)Send byte to get data on reveiver
while( looping) { // Wait add data to be received before next command
Log.d("TAG", "On Hold ? ");
}
intByteCount=160; // (command 2)
GetTitle(intCommand);
This is the code in a handler for bluetooth that sets the looping to false once all the bytes have been received.
Handler h = new Handler() {
#Override
// public void handleMessage(android.os.Message msg) {
public void handleMessage(android.os.Message msg) {
byte[]readBuf = (byte[]) msg.obj;
if (intByteCount==9){
// Data is channel status and Master value
byte[] encodedBytes = new byte[5];
System.arraycopy(readBuf, 0, encodedBytes, 0, encodedBytes.length);
looping=false;
};
The GetTitle and GetData are basically the same
Here is the GetTitle()
private void GetData(int FixtureNumber) {
Log.d("TAG", "Value " + intArrayToInt(intArray1));
intByteCount=9; // set to receive 9 bytes
byte buffer[] = new byte[6];
buffer[0] = ((byte) 1); // Command (get data)
buffer[1] = ((byte) Master_value);
buffer[2] = ((byte) intArrayToInt(intArray1));
buffer[3] = ((byte) intArrayToInt(intArray2));
buffer[4] = ((byte) 3);
buffer[5] = ((byte) 4);
if (isBTConnected) {
try {
mmOutputStream.write(buffer);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Here is the final code to get both control data
new Thread(new Runnable() {
#Override
public void run() {
intByteCount =9;
GetData(intCommand); // Send byte to get data on reveiver
//you can use a for here and check if the command was executed or just wait and execute the 2nd command
try {
Thread.sleep(1000); //wait 2 seconds
} catch (InterruptedException e) {
e.printStackTrace();
}
intByteCount=160; // Sed incoming data byte count
GetTitle(intCommand);
}
}).start();
You can use a Thread and wait x amount of time, :
new Thread(new Runnable() {
#Override
public void run() {
//your 1st command
//you can use a for here and check if the command was executed or just wait and execute the 2nd command
try {
Thread.sleep(2000); //wait 2 seconds
} catch (InterruptedException e) {
e.printStackTrace();
}
//your 2nd command
}
}).start();
Thank you Agustin that worked fine. The received data was quick so just a delay will work without the control boolean. Here is the new code.
new Thread(new Runnable() {
#Override
public void run() {
intByteCount =9;
GetData(intCommand); // Send byte to get data on reveiver
//you can use a for here and check if the command was executed or just wait and execute the 2nd command
try {
Thread.sleep(1000); //wait 2 seconds
} catch (InterruptedException e) {
e.printStackTrace();
}
intByteCount=160; // Sed incoming data byte count
GetTitle(intCommand);
}
}).start();
You are currently holding up the main thread there, something it is not advised to do. The best option for this is to modify the code so that the second Bluetooth command is done in a function that is called where the looping == false code is used.
This question is related to Android multi-threading, OpenCV and JNI. The JNI call made inside onCameraFrame is kind of an expensive image-processing operation, hence the camera-preview frame rate gets very slow (a lot of frame lag). When, the native method - 'FindSquare' is called in background from a new thread, the performance improves a little but not very much.
Please suggest the most efficient way to do what I intend to do below, so as to improve the frame-rate.
boolean isCallFinished = false;
public Mat onCameraFrame(Mat inputFrame) {
Size originalSize = inputFrame.size();
Imgproc.cvtColor(inputFrame, mDstImg, Imgproc.COLOR_RGBA2BGR);
Imgproc.resize(inputFrame, mDstImg, new Size(mScreenWidth,
mScreenHeight)); // 2048, 1536
new Thread(new Runnable() {
public void run() {
Message msg = new Message();
if(!isCallFinished) {
msg.arg1 = FindSquares(mDstImg.getNativeObjAddr()); // JNI call
isCallFinished = true;
messageHandler.sendMessage(msg);
}
}
}).start();
if (mDraw == 1) {
Imgproc.resize(mDstImg, inputFrame, originalSize);
}
return inputFrame;
}
A rapid optimization on a first glance would be to avoid creating a new thread for each frame.
Creating a new thread is very expensive.
Try the following approach :
Create a worker thread (keep reference to it)
Create a synchronized queue to communicate with the worker thread
Add objects to the worker thread queue and process them as a bunch
I'll try to write down the concept bellow , and adapt it to your needs (please note that the code wasn't tested in a proper environment).
public class MyWorkerThread extends Thread
{
ArrayList<FrameEvent> frameList;
boolean runWorkerThread;
public WorkerThread
{
super("FrameEventsWorkerThread");
runWorkerThread=true;
frameList= new ArrayList<FrameEvent>();
}
public synchronized AddFrameEvent(FrameEvent aEvent)
{
frameList.add(aEvent);
}
public void kill ()
{
runWorkerThread=true;
}
public void run()
{
while (true && runWorkerThread)
{
synchronized(this)
{
if (frameList.size()>0)
{
for (int i=0;i<frameList.size();i++)
{
Message msg = new Message();
if (!isCallFinished) { // don't quite understand what you want with this
FrameEvent evt = frameList.get(i);
msg.arg1 = FindSquares(evt.dstImg.getNativeObjAddr());
isCallFinished=true;
messageHandler.sendMessage(msg);
}
}
frameList.clear();
}
}
try {
Thread.sleep(10);
} catch (Exception e)
{
}
}
}
}
Your new function should look something like this :
boolean isCallFinished = false;
MyWorkerThread theThread;
public Mat onCameraFrame(Mat inputFrame) {
Size originalSize = inputFrame.size();
Imgproc.cvtColor(inputFrame, mDstImg, Imgproc.COLOR_RGBA2BGR);
Imgproc.resize(inputFrame, mDstImg, new Size(mScreenWidth,
mScreenHeight)); // 2048, 1536
FrameEvent newEvt = new FrameEvent();
newEvt.dstImg = mDstImg;
theThread.AddFrameEvent(newEvt); // avoid creating new threads
if (mDraw == 1) {
Imgproc.resize(mDstImg, inputFrame, originalSize);
}
return inputFrame;
}
I need some help with starting/stopping my monsters.
We generate like this:
for (int i = 0; i < 20; i++) {
boolean notFree = true;
int x = 0, y = 0;
// while not free change
// not determinstisch setting!
while (notFree) {
x = (int) (Math.random() * Config.XSIZE);
y = (int) (Math.random() * Config.YSIZE);
if (map.getMapPosition(x, y) == Config.EMPTYPOSITION) {
notFree = false;
}
}
switch ((int) Math.floor(Math.random() * 2)) {
case 0:
monsterVerktor.add(new Monster(context, x, y, this.map, 1,
this.charac));
break;
case 1:
monsterVerktor.add(new DeathReaper(context, x, y, this.map, 1,
this.charac));
break;
default:
break;
}
}
And I stop them like this: (Start is same just with Startmoving...)
public void stopAllMonsters() {
for (Monster monster : monsterVerktor) {
monster.getControl().stopMovingThread();
}
}
The thread.stopMovingThread works like this:
public void stopMovingThread() {
this.monster.setAlife(false);
running = false;
moveDone = true;
boolean retry = true;
while (retry) {
try {
thread.join();
retry = false;
} catch (InterruptedException e) {
// try again shutting down the thread
}
}
}
To the run():
public void startMovementThread() {
running = true;
thread = new Thread() {
#Override
public void run() {
while (running) {
Log.d(TAG, "run Thread");
// get a little randomness in the movement ;)
try {
// up to 0.5s sleeping till next moving
sleep(new Random().nextInt(Config.RANDOMSLEEP));
} catch (InterruptedException e1) {}
while (monster.isAlife()) {// check if alife
moveDone = false; // resett movement Done
noMove = false;
// Charakter in near if one is in near he
// will move to it.
if (!checkCharInAggroRange()) {
noMove = rndMove(); // if we have no move
}
while (!moveDone) {
timeBegin = System.currentTimeMillis();
// if hes not done with the move
if (monster.moveToX == monster.positionX
&& monster.moveToY == monster.positionY) {
if (noMove) {
try {// sleep because no movement with a bit
// randomness
sleep(Config.MONSTERMOVINGTIME
+ (new Random()
.nextInt(Config.RANDOMSLEEP)));
} catch (InterruptedException e) {
Log.d(TAG,
"An error occured during sleep because"
+ " of no Animatino");
}
}
// false after sleep
moveDone = false;
break; // already at the right position!
// movetoX is left of position
} else if (monster.moveToX > monster.positionX) {
monster.positionX++;
// movetoX is left of it
} else if (monster.moveToX < monster.positionX) {
monster.positionX--;
// movetoY is left of position
} else if (monster.moveToY > monster.positionY) {
monster.positionY++;
// movetoY is left of position
} else if (monster.moveToY < monster.positionY) {
monster.positionY--;
}
// sleep if hes moving to fast!
timeDiff = System.currentTimeMillis() - timeBegin;
sleepTimer = (int) (Config.MONSTERTIMING - timeDiff);
if (sleepTimer > 0) { // if >0 we are fast enough
// and can sleep a bit ;)
try {
sleep(sleepTimer);
} catch (InterruptedException e) {
Log.d(TAG, "Gameloop thread cant sleep");
}
}
}
}
try {
sleep(Config.RESPAWNTIMER);
} catch (InterruptedException e) {
Log.d(TAG, "Monsterthread cant sleep");
}
// respawn it after a sleep :)
respawn();
}
}
};
thread.start();
}
Android stops working if we want to stop them and start them like this, and I dont get it why. We also stop/start our render like this. (Well it's a runable and this isn't)
Monster isAlife and etc:
public class Monster extends Drawable {
private static final String TAG = Monster.class.getSimpleName();
private int fullLife; // full life
private int curLife; // current life
public Context context;
private Character charac;
// ..
// Basic monsterstuff
private boolean alife, moveDone;
private int level;
public Status status;
private MonsterControl control;
// ..
public Monster(Context context, int mapPosX, int mapPosY, Map map,
int level, Character cha) {
this.context = context;
this.map = map;
this.setCharac(cha);
this.mapPosition[0] = mapPosX;
this.mapPosition[1] = mapPosY;
this.status = Status.IDLE;
// example for full life calculation
this.fullLife = level * 100 + ((int) (Math.random() * 10 * level)); // Examples
this.curLife = this.fullLife;
this.map.setMapPosition(mapPosX, mapPosY, Config.MONSTERSTATE);
// set monster position
// ..
// load the sprite bitmap
// ...
// Change this later!
alife = true;
Log.d(TAG, "Monster created");
// Starting the Controler
control = new MonsterControl(this, this.charac);
control.startMovementThread();
Log.d(TAG, "Monster start moving");
// exemplarisch cut of the sprite
this.monsterPicAnimation();
}
}
here the getter/setter for aLife
public boolean isAlife() {
return alife;
}
public void setAlife(boolean alife) {
this.alife = alife;
}
First off, your comment of "Android stops working", Are you implying a crash? Got a LogCat trace?
Other than that is this analysis correct?
1.Create a monster.
running = true;
isAlife = true; //or whatever monster.isAlife() checks
2.Thread starts.
while (running) {
...
while (monster.isAlife()) {
...
}
}
3.You try to stop the thread by (1) setting running to false, and (2) joining on the thread?
Assuming that is all true. The monster thread still runs until something kicks it from the nested while(monster.isAlife()) loop. Once that ends, the while(running) will evaluate false and the thread should terminate, moving on to the next monster in your collection. Without this ever terminating you'll be waiting on each monster to die while locking your main thread with join().
Apart from the logic of your code which I haven't looked at in details, there is a lack of synchronization around shared variables. In particular, as it is, your code provides no guarantee that your thread (in startMovementThread) will ever be able to observe the changes made to your flags from the main thread.
A good first step would be to make those variables volatile:
private volatile boolean alife, moveDone;
Note however that there might be other issues (depending on your requirements). For example, when those statements are executed in startMovementThread:
if (monster.moveToX == monster.positionX ...)
monster.positionX++;
any changes made in that thread might not be visible from the main thread and vice versa. If that can be an issue, you need to synchronize access to those variables too (and making them volatile will not be enough because, for example, monster.positionX++ is not atomic).
I solved it myself with and "good" idea.
The problem was, that i let them sleep at some points. If they sleep it cant stop/join the thread and even dont watch if its "running". So i solved it with a small methode that looks like this:
private void breakableSleep(int i, int intervall){
int x = 0;
while(running && x <= i){
try {
this.thread.sleep(intervall);
} catch (InterruptedException e) {
Log.d(TAG, "Monsterthread cant sleep");
}
x++;
}
}
it can be stoped at every intervall. Sure it will cost some Battery but did not finde any other way to stop the Monsters in a "fast" way because some sleep for around 3seconds if they died (respawning)
I also rewrote the whole startMovementThread because it did not look well in my opinion.
Best Regards
I am trying to run the audio recording http://developer.android.com/guide/topics/media/index.html, Its working fine, what I need is to show max amplitude while recording voice continuously. What is the best approach for that.
Max amplitude gives max amplitude of the given sample, so I taken sample for every 250 milli seconds and calculated max amplitude
public void run() {
int i = 0;
while(i == 0) {
Message msg = mHandler.obtainMessage();
Bundle b = new Bundle();
try {
sleep(250);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (mRecorder != null) {
amplitude = mRecorder.getMaxAmplitude();
b.putLong("currentTime", amplitude);
Log.i("AMPLITUDE", new Integer(amplitude).toString());
} else {
b.putLong("currentTime", 0);
}
msg.setData(b);
mHandler.sendMessage(msg);
}
}
I used message handlers to modify front end using background process thread
Create a thread which runs all the time.
In the thread do this:
int amp = mrec.getMaxAmplitude();
if (amp > 0)
yourcode;
Do you need more information on the thread?