My app resets data when it is minimized - java

i made an android game once i minimize it,
it resets data and refresh the timer like you started the game from the scratch
how can i make it Don't do this
i think the problem is on the OnStart function
protected void onStart() {
super.onStart();
// Reset score
Configs.score = 0;
scoreTxt.setText(String.valueOf(Configs.score));
// Set progressBar and start the gameTimer
pb = (ProgressBar)findViewById(R.id.gbProgressBar);
progress = 0;
pb.setProgress((int) progress);
startGameTimer();
// Get a random circle for letters
Random r = new Random();
randomCircle = r.nextInt(Configs.circlesArray.length);
// Reset taps count
tapsCount = -1;
// Get a random word from words string-array
getRandomWord();
}

onStart is called every time the app starts. onCreate on the other hand, is only called when the app starts or after the activity process has been killed and restarted. Usually the last scenario means after onStop is called and the activity process is killed, but it isn't destroyed yet.
Move that code to onCreate, otherwise it calls that every time the app is reopened which resets it

Related

android: taking pictures in task or thread at regular interval?

I'm writing an android app which should take pictures in a user-defined interval (20 sec - 1 min). It should take the pictures even while it is running in background or while the device is sleeping. The app will run for a very long time period. If it is necessary to wake up the device, it should put back to sleep as soon as possible to save batterie life. After taking a picture the app will process some additional work (comparison of two pictures).
I read some stuff about sheduling alarms (http://developer.android.com/training/scheduling/alarms.htm), creating Services (also # android training) and Android AsyncTasks, Java threads (http://www.mergeconflict.net/2012/05/java-threads-vs-android-asynctask-which.html)
... but I'm still not sure what is the best way to achieve this.
My questions are:
Should I use thread or a task to take the pictures in background?
(the comparison of the two pictures might take longer than a few
milliseconds but i don't know anything about the cpu load of this
operation)
Should I use an alarm to wake the device up or are there any alternative solutions?
How can both (alarms and thread/task) work together? (Include the Alarm in the Task/Thread?)
Many thanks for your help in advance.
As to our question I know I can help get started with the aspect of repeating the picture taking task at a user defined time interval. For such a task you can user a Timer to achieve this. The code would look something like this:
mTmr = new Timer();
mTsk = new TimerTask() {
#Override
public void run() {
//Take picture or do whatever you want
}
};
mTmr.schedule(mTsk, 0, USER_DEFINED_EXECUTION_INTERVAL);
schedule begins the timer. The first parameter of schedule used here is the task to run which is mTsk. The second parameter is the delay until the first execution (in milliseconds), in this case no delay. The third parameter is what you'll want to manipulate which is the interval of executions. The parameter is the time between executions so if it were 20 seconds you'd pass in 20,000. If it were a minute it would be 60,000. You can get this value from the user using any method you'd like.
To keep the timer running make sure you don't call mTmr.cancel in onPause because for your case you want to keep the timer running while the user isn't on the app. Not calling cancel means the timer will hold it's resources until the app is closed by the user.
OR you can look at this How to schedule a periodic task in Java? If you'd like to use ScheduledExecutorService instead of a Timer.
I have made this app - Lenx. It uses Camera extensively and I am processing image in the background. I have used AsyncTask to process the image and it has never given any problems. The app also has a timer which starts the process after certain interval. The logic that I have used is very simple.
I have not used Camera2 API yet, so the code might be deprecated. I created CameraPreview class which implements Camera.PreivewCallback.
#Override
public void onPreviewFrame(byte[] data, Camera camera) {
if (data == null) {
return;
}
int expectedBytes = previewWidth * previewHeight *
ImageFormat.getBitsPerPixel(ImageFormat.NV21) / 8;
if (expectedBytes != data.length) {
Log.e(TAG, "Mismatched size of buffer! Expected ");
mState = STATE_NO_CALLBACKS;
mCamera.setPreviewCallbackWithBuffer(null);
return;
}
if (mProcessInProgress || mState == STATE_PROCESS_IN_PROGRESS) {
mCamera.addCallbackBuffer(data);
return;
}
if (mState == STATE_PROCESS) {
mProcessInProgress = true;
processDataTask = new ProcessDataTask();
processDataTask.execute(data);
}
}
public void startProcessing() {
mState = STATE_PROCESS;
}
And my AsyncTask is something like this
private class ProcessDataTask
extends
AsyncTask<byte[], Void, Boolean> {
#Override
protected Boolean doInBackground(byte[]... datas) {
mState = STATE_PROCESS_IN_PROGRESS;
Log.i(TAG, "background process started");
byte[] data = datas[0];
long t1 = java.lang.System.currentTimeMillis();
// process your data
long t2 = java.lang.System.currentTimeMillis();
Log.i(TAG, "processing time = " + String.valueOf(t2 - t1));
mCamera.addCallbackBuffer(data);
mProcessInProgress = false;
return true;
}
#Override
protected void onPostExecute(Boolean result) {
mState = STATE_PROCESS_WAIT;
}
}
onPreviewFrame() will always get called as long as the camera preview is running. You need to take the data and process it only when you trigger something. So simply change the state of a variable, in this case, mState, and based on the state, call your AsyncTask.

resetting SystemClock.currentThreadTimeMillis()

I have a button that appears at the end of my app when the game is complete that is meant to reset the app. I have tested it and it works besides the timer. I have does not reset to the "startTime". I have a button that is used to reset the game such as:
if(resetButton.getText().equals("Restart"))
{
reset_flag = true;
Intent i = getBaseContext().getPackageManager()
.getLaunchIntentForPackage(getBaseContext().getPackageName());
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
}
I have a runnable for the timer as:
long gamerestart = SystemClock.currentThreadTimeMillis();
if(reset_flag)
{
gamerestart = 0;
startTime = 60000;
flag = false;
}
timeInMilliseconds = startTime - gamerestart;
The reset_flag did help as I noticed the time at the top of the game reset to the original time but at the next time-tick it updated to whatever the currentThreadTimeMillis is.
I did try doing SystemClock.currentThreadTimeMillis() = 0; but that did not work ( I was not surprised it didn't either..)
I did not see a function within SystemClock that would doing any resetting. I thought this would be a simple task but maybe it is not, could anyone give me some help? Thanks.
That time is how long the thread has been alive, consider using a separate variable for timing. You can always initialize it to SystemClock.currentThreadTimeMillis() and deduct SystemClock.currentThreadTimeMillis() whenever you want to display the value

CountDownTimer continues to tick in background — How do I retrieve that count in onResume?

I have an app with multiple timers; when I start one, I can see it counting down in Logcat in Eclipse.
When I hit the Back button, onStop() is called in the app but the timer continues to countdown in logcat (the onTick() is continuing to tick away).
What I would like is when onResume() is called, I want to get that timer which is still counting down and continue it. Is this possible?
Here are my buttons that start the countdown:
//Button1 Timer
final CountDown button1 = new CountDown(420000,1000,bButton1);
bButton1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
button1.start();
long currentTime = System.currentTimeMillis();
//Set start time for calculating time elapsed if needed
saveTime("START_TIME_BUTTON1", currentTime);
}
});
//Button2 Timer
final CountDown button2 = new CountDown(360000,1000,bButton2);
bButton2.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
button2.start();
long currentTime = System.currentTimeMillis();
//Set start time for calculating time elapsed if needed
saveTime("START_TIME", currentTime);
}
});
My onResume() looks like this:
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
//Reset the timers on appropriate buttons if there was something running
//If nothing was running or timer finished - have button in default state
//See if there was a button1 timer running - if not, it will be 0
SharedPreferences start = PreferenceManager.getDefaultSharedPreferences(this);
long startTime = start.getLong("START_TIME_BUTTON1", 0);
long timeElapsed = (System.currentTimeMillis()-startTime);
long timeRemaining = (420000 - timeElapsed);
if (timeRemaining == 0) {
} else if (timeRemaining > 0) {
final CountDown button1Timer = new CountDown(timeRemaining,1000,bButton1);
button1Timer.start();
long currentTime = System.currentTimeMillis();
saveTime("START_TIME", currentTime);
} else {
}
}
This actually works — the onResume() starts another timer right where the first one would be, and the text displays the appropriate number and continues counting down with the onTick() method. But now logcat shows 2 timers counting down instead of just one!
Ultimately I wouldn't want to start another timer, I just want to pick up the first timer I started where it is currently in the countdown at and have the onTick() display appropriately. Is there a way to do that? Would services be what I'm looking for? Is it already a service since it continues to tick down in the background?
I'm a little confused on what would be best practice to get this done.
onTick() will continue being called until either the time remaining reaches 0 or you call cancel() on the CountDownTimer.
So in your onStop() method you will need to call cancel() on the timer you want to stop receiving onTick() notifications.
Android's implementation of CountDownTimer uses a Handler to perform timing by queuing a Message to be sent to the Handler after each tick. Unfortunately there is no way to pause the CountDownTimer, so I believe you will need to create a new Timer with the appropriate values like you're doing currently.
When you're calculating the timeElapsed, you shouldn't use System.currentTimeMillis() because it can be changed at any time, instead you should use SystemClock.elapsedRealtime(). System.currentTimeMillis() is the timer used for the wall clock (time and date) and so can change unpredictably, see the Android documentation.

Is there a way to make this Pulse number infinite?

I've created a button to trigger a pulse LED action on my app, but I cant make it pulse forever. It always Pulses by value ( on the example above you will see it pulses 10 times and then stops )
//Button Pulse
Button bpulse = (Button) findViewById(R.id.bpulse);
bpulse.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
Intent led = new Intent(IlluminationIntent.ACTION_START_LED_PULSE);
led.putExtra(IlluminationIntent.EXTRA_PACKAGE_NAME, "com.devsgonemad.xslc");
led.putExtra(IlluminationIntent.EXTRA_LED_ID,
IlluminationIntent.VALUE_BUTTON_2);
led.putExtra(IlluminationIntent.EXTRA_LED_NO_OF_PULSES, 10);
led.putExtra(IlluminationIntent.EXTRA_LED_PULSE_ON_TIME, 1000);
led.putExtra(IlluminationIntent.EXTRA_LED_PULSE_OFF_TIME, 1000);
led.putExtra(IlluminationIntent.EXTRA_LED_COLOR, m_ledColor);
startService(led);
m_isEnabled = true;
}
How can I make this pulse forever when the button is pressed until the user goes back to the app and stops it from pulsing?
Best regards
How about using a while loop? You could put the number of pulses as 1, and let this run continuously in a while loop, until some condition (in your case some button is pressed) is satisfied.
while(buttonNotPressed){
led.putExtra(IlluminationIntent.EXTRA_LED_NO_OF_PULSES, 1);
startService(led);
}
Ofcourse this has an obvious pitfall that you may start many parallel services all trying to flash the LED once. But I guess you can control your while loop to wait for the service to end before you start the next iteration.
EDIT: For the while loop to wait for your service, you will need to add some sort of flag inside your service on which the while loop can wait. Once the service finishes, the flag can be set and the while loop can move onto the next iteration, thus giving you infinite rounds of flashes until the button is pressed.

Counting headset button clicks in BroadcastReceiver

Inside of the onReceive(Content context, Intent intent) method of my public class MediaButtonIntentReceiver extends BroadcastReceiver I need to count the number of headset button clicks (single, double, triple), which is denoted by KeyEvent.ACTION_DOWN of the ACTION_MEDIA_BUTTON.
What I have almost works, but my current algorithm sucks and is unreliable after a few times. Basically every successive ACTION_DOWN (hit within a certain number of milliseconds to the previous ACTION_DOWN) I do numClicks++. But also I need to see when the user is done pressing, so after each event I start a CountDownTimer, and if by the time it runs out there are no new clicks, then I'm done and now know the number of clicks.
The problems I'm running into are as follows: for one, the button itself seems noisy - if I press it too fast I usually miss a click. Two, after a few trials when the app it loaded, it starts getting random and I'm assuming that there are multiple CountDownTimer threads (is that the right word?) still running which screws my stuff up.
Anyways here's the main code snippet:
//note: thisClickTime uses System.currentTimeMillis()
if (action == KeyEvent.ACTION_UP) {
if (isDown == true) {
if (numClicks == 0 && lastClickTime == 0) {
//we have a new click
numClicks++;
lastClickTime = thisClickTime; //update the click time
isDown = false;
elapsedTime = thisClickTime - lastClickTime;
} else if (thisClickTime - lastClickTime < clickDelay) { //&& thisClickTime - lastClickTime > 10
numClicks++;
lastClickTime = thisClickTime;
isDown = false;
}
final int oldNumClicks = numClicks;
final CountDownTimer checkIfDone = new CountDownTimer(clickDelay, 10) {
public void onTick(long millisUntilFinished) {
if (oldNumClicks != numClicks) {
cancel();
}
}
public void onFinish() { //code that executes when counter is done
if (oldNumClicks == numClicks) {
//if user doesn't click anymore in time clickDelay + X milliseconds, then it's done
Toast.makeText(context, "Number of clicks: " + Integer.toString(numClicks), Toast.LENGTH_SHORT).show();
//reset state variables
numClicks = 0;
lastClickTime = 0;
}
}
}.start();
} else {
//?
}
}
For reference, I've been looking around at stuff like:
http://musicqueueproject.googlecode.com/svn-history/r83/trunk/src/com/yannickstucki/android/musicqueue/old/PlayerService.java
To see if there's a good way to register number of clicks. I don't really understand their code too well though, and from what I can see they only deal with single/double clicks (I may need triple and quadruple).
EDIT - uploaded the current code I'm working with. It works pretty decently most of the time. Here's what I've noticed though: if I do my button testing too close together in time, the results start screwing up and under counting the clicks. I think this is because other CountDownTimers from previous attempts are still open, and when they finish, they reset certain state variables (numClicks = 0, for one). So am I misusing the timer? I can't think of another solution though as I need some concept of elapsed time after the last click to determine when the clicking is done.
Thanks for any help.
If your BroadcastReceiver is registered in the manifest, the BroadcastReceiver will only exist for a single call to onReceive() -- subsequent broadcasts may result in another BroadcastReceiver instance. And a manifest-registered BroadcastReceiver cannot fork threads, as the whole process may get shut down once onReceive() is over.
I am skeptical that there a clean way to get your code to be reliable, as the media button simply was not designed for your intended use pattern.

Categories

Resources