using threads and timer correctly - android

i have three functions- animation, sound, vibration. all these work perfectly fine individually. i need to start all these 3 functions together and continue playing for 3 seconds and then stop. i want this to repeat after every 15 seconds. what will be the correct approach to implement this?
my vibration code is as follows
public void vibration(){
int dash = 1000;
int medium_gap = 500;
long[] pattern = { 0, // Start immediately
dash, medium_gap,dash , medium_gap
};
// Only perform this pattern one time (-1 means "do not repeat")
v.vibrate(pattern, -1);
}
animation code:
linear = (LinearLayout) findViewById(R.id.lay);// this line is after setContentView in onCreate
public void anim(){
drawable.addFrame(new ColorDrawable(Color.RED), 1000);
drawable.addFrame(new ColorDrawable(Color.WHITE), 500);
drawable.setOneShot(false);
linear.setBackgroundDrawable(drawable);
drawable.start();
}
sound using soundpool:
sp = new SoundPool(5, AudioManager.STREAM_NOTIFICATION, 0);
buzzer = sp.load(this, R.raw.buzzer, 0);
public void sound(){
sp.play(buzzer, 1,1, 0, 0, 1); //start alert tone
}

you need to implement thread to run all together for specified time.
Thread myTime = new Thread()
{
void run(){
sleep(3000) //sleep untill 3 sec than stop
//your code
}
}

Related

Android view doesn't update when trying to set values over time

I got a fragment which got a control called RingProgress which is simply a ring that fills itself according to a percentage value given. For example, if I do:
ringProgress.setProgress(20);
It means that 20% of the ring will now be filled.
What I'm trying to do is to animate the ring being filled over a few seconds. So what I've tried to do is this:
#Override
public void onResume()
{
super.onResume();
HandlerThread handlerThread = new HandlerThread("countdown");
handlerThread.start();
Handler handler = new Handler(handlerThread.getLooper());
handler.post(new Runnable()
{
#Override
public void run()
{
final Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask()
{
int totalSeconds = secondsToStart + minutesToStart * 60;
int secondsPassed = 0;
#Override
public void run()
{
if(secondsPassed == totalSeconds)
{
timer.cancel();
}
final int currentProgress = (secondsPassed / totalSeconds) * 100;
secondsPassed++;
getActivity().runOnUiThread(new Runnable()
{
#Override
public void run()
{
mRingProgressBar.setProgress(currentProgress);
}
});
}
}, 0, 1000);
}
});
}
The problem is that the update of the ring is not shown until the time is up. For example, if I set it for 5 seconds then when the fragment loads the ring is set to 0, then nothing happens for 5 seconds and then the ring is full with 100% all at once..
How can I start this animation properly?
I guess the problem is with
final int currentProgress = (secondsPassed / totalSeconds) * 100;
secondsPassed / totalSeconds return int value so it will be 0 or 1 only. And you multiply it to 100.
You have to use float or double instead
something like
final int currentProgress = Math.round(((float) secondsPassed)/((float) totalSeconds)*100f);
On this line:
Handler handler = new Handler(handlerThread.getLooper());
You are trying to get the looper from a handlerThread. But how sure you are the looper has already been initialized?
From the documentation of getLooper()
This method returns the Looper associated with this thread. If this thread not been started or for any reason is isAlive() returns false, this method will return null. If this thread has been started, this method will block until the looper has been initialized.
onLooperPrepared() is the callback, where you can be sure, that the Looper has been initialized, and therefore you can construct logics on that.
Thus, what you have to do, is to subclass HandlerThread and create appropriate logics from onLooperPrepared() callback.
Here's a nice post which will help you out. See implementation of MyWorkerThread class there.
Instead of using a handler, you could use a property animator as follows:
ObjectAnimator.ofInt(mRingProgressBar, "progress", 0, 100)
.setDuration(totalSeconds * 1000) //time is in miliseconds
.start();
This will find a method setProgress() in your mRingProgressBarand set the value according to the limits given. In the example above, 0 to 100.
You can read more about it here
Since you want to run on a different thread, you can use this handler in the top of the class:
private int progress = 0;
Handler timerHandler = new Handler();
Runnable timerRunnable = new Runnable() {
#Override
public void run() {
ringProgress.setProgress(progress);
progress += 20;
if (progress == 100) { //clear??
}
timerHandler.postDelayed(this, 1000);
}
};
In inCreate set the max:
ringProgress.setMax(100);
This will complete the animation within 5 seconds, then you can clear the animation. If you want smaller increments, change the line below (update every tenth of a second), and change the steps
timerHandler.postDelayed(this, 100);

Android Studio Mediaplayer how to fade in and out

I am working with the mediaplayer class in android studio. I simply want to fade out one sound and fade in the other sound instead of using setVolume(0,0) and setVolume(1,1).
I have created two mediaplayers for this and it seemed like I found a solution in this thread: Android: How to create fade-in/fade-out sound effects for any music file that my app plays? but I don't know how to use deltaTime.
There are also some other solutions to this, which I can barely understand. Isn't there an easy way to cross fade two mediaplayers, I can not imagine no one has needed this yet or everyone uses obsessive code to achieve it. And how should I use deltaTime?
Looking at the linked example, you would have to call fadeIn()/fadeOut() in a loop, to increase/decrease the volume over a period of time. deltaTime would be the time between each iteration of the loop.
You'd have to do this in a separate thread from your main UI thread, so you don't block it and cause your app to crash. You can do this by either putting this loop inside a new Thread/Runnable/Timer.
Here is my example for fading in (you can do a similar thing for fading out):
float volume = 0;
private void startFadeIn(){
final int FADE_DURATION = 3000; //The duration of the fade
//The amount of time between volume changes. The smaller this is, the smoother the fade
final int FADE_INTERVAL = 250;
final int MAX_VOLUME = 1; //The volume will increase from 0 to 1
int numberOfSteps = FADE_DURATION/FADE_INTERVAL; //Calculate the number of fade steps
//Calculate by how much the volume changes each step
final float deltaVolume = MAX_VOLUME / (float)numberOfSteps;
//Create a new Timer and Timer task to run the fading outside the main UI thread
final Timer timer = new Timer(true);
TimerTask timerTask = new TimerTask() {
#Override
public void run() {
fadeInStep(deltaVolume); //Do a fade step
//Cancel and Purge the Timer if the desired volume has been reached
if(volume>=1f){
timer.cancel();
timer.purge();
}
}
};
timer.schedule(timerTask,FADE_INTERVAL,FADE_INTERVAL);
}
private void fadeInStep(float deltaVolume){
mediaPlayer.setVolume(volume, volume);
volume += deltaVolume;
}
Instead of using two separate MediaPlayer objects, I would in your case use just one and swap the track between the fades.
Example:
**Audio track #1 is playing but coming to the end**
startFadeOut();
mediaPlayer.stop();
mediaPlayer.reset();
mediaPlayer.setDataSource(context,audiofileUri);
mediaPlayer.prepare();
mediaPlayer.start();
startFadeIn();
**Audio track #2 has faded in and is now playing**
Hope this solves your problem.
Here's the fade-out code in case it saves someone some time.
This also includes a stopPlayer() function to release the MediaPlayer from memory. It's a good practice to do so.
// Set to the volume of the MediaPlayer
float volume = 1;
private void startFadeOut(){
// The duration of the fade
final int FADE_DURATION = 3000;
// The amount of time between volume changes. The smaller this is, the smoother the fade
final int FADE_INTERVAL = 250;
// Calculate the number of fade steps
int numberOfSteps = FADE_DURATION / FADE_INTERVAL;
// Calculate by how much the volume changes each step
final float deltaVolume = volume / numberOfSteps;
// Create a new Timer and Timer task to run the fading outside the main UI thread
final Timer timer = new Timer(true);
TimerTask timerTask = new TimerTask() {
#Override
public void run() {
//Do a fade step
fadeOutStep(deltaVolume);
//Cancel and Purge the Timer if the desired volume has been reached
if(volume <= 0){
timer.cancel();
timer.purge();
stopPlayer();
}
}
};
timer.schedule(timerTask,FADE_INTERVAL,FADE_INTERVAL);
}
private void fadeOutStep(float deltaVolume){
player.setVolume(volume, volume);
volume -= deltaVolume;
}
// Release the player from memory
private void stopPlayer() {
if (player != null) {
player.release();
player = null;
}
}
There's a VolumeShaper class added in API Level 26 (https://developer.android.com/guide/topics/media/volumeshaper).
Here's an example of volume out and in, you can shape the fade in or out speed (ramp) adding more points to times and volumes arrays.
Time points must start at 0 and end at 1 and they are relative times of volume ramping.
fun fadeOutConfig(duration: Long): VolumeShaper.Configuration {
val times = floatArrayOf(0f, 1f) // can add more points, volume points must correspond to time points
val volumes = floatArrayOf(1f, 0f)
return VolumeShaper.Configuration.Builder()
.setDuration(duration)
.setCurve(times, volumes)
.setInterpolatorType(VolumeShaper.Configuration.INTERPOLATOR_TYPE_CUBIC)
.build()
}
fun fadeInConfig(duration: Long): VolumeShaper.Configuration {
val times = floatArrayOf(0f, 1f) // can add more points, volume points must correspond to time points
val volumes = floatArrayOf(0f, 1f)
return VolumeShaper.Configuration.Builder()
.setDuration(duration)
.setCurve(times, volumes)
.setInterpolatorType(VolumeShaper.Configuration.INTERPOLATOR_TYPE_CUBIC)
.build()
}
fun fadeInOrOutAudio(mediaPlayer: MediaPlayer, duration: Long, out: Boolean) {
val config = if (out) fadeOutConfig(duration) else fadeInConfig(duration)
val volumeShaper = mediaPlayer.createVolumeShaper(config)
volumeShaper.apply(VolumeShaper.Operation.PLAY)
}
private void fadeOut() {
final long steps = 30;
final double stepWidth = (double) 1 / steps;
mFadeOutCriteria = 1;
handler.postDelayed(new Runnable() {
#Override
public void run() {
mFadeOutCriteria -= stepWidth;
mediaPlayer.setVolume(mFadeOutCriteria, mFadeOutCriteria);
if (mFadeOutCriteria <= 0) {
mediaPlayer.stop();
nextrunq();
mFadeOutCriteria = 0;
handler.removeCallbacks(this);
} else
handler.postDelayed(this, 100);
}
}, 100);
}

Call a method in variable period on everytime? [duplicate]

This question already exists:
Timer time does not change as variable?
Closed 9 years ago.
I have to call some webservice method in variable times, every time method runs it returns me next period time as long. I tried it with timer but after first calling, it can not understand new variable time.
This is the link asked yesterday something about it: Timer time does not change as variable?
Here is the sample code:
private int V_Time = 1;
.
.
.
try {
final Timer V_Timer;
final Handler V_Handler;
V_Timer = new Timer();
V_Handler = new Handler(Looper.getMainLooper());
V_Timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
V_Handler.post(new Runnable() {
public void run() {
webservice_method();
V_Time = 2; // it returns from method, not manually right as shown
//and it can be change every time method calls..
}
});
}
}, 0, V_Time * 1000 * 60);
} catch (Exception hata) {
}
It works first time after 1 minute, but others does not change (eg 2 min), it works every 1 minute.
I want just it works properly, with timer or without timer with anything else...
I think I may cancel timer but I guess I cannot resume or restart it again.
It must be something to do what I want, but I do not to know how?
I want to change period time, every timer task run what return from method.
What you are trying to achieve is impossible. You have to cancel the current task and reschedule a new one with the new interval.
private TimerTask mTask = new TimerTask() {
#Override
public void run() {
V_Handler.post(new Runnable() {
public void run() {
webservice_method();
V_Time = 2; // it returns from method, not manually right as shown
//and it can be change every time method calls..
V_Timer.cancel();
V_Timer.scheduleAtFixedRate(mTask, 0, V_Time * 1000 * 60);
}
});
}
}
try {
final Timer V_Timer;
final Handler V_Handler;
V_Timer = new Timer();
V_Handler = new Handler(Looper.getMainLooper());
V_Timer.scheduleAtFixedRate(mTask, 0, V_Time * 1000 * 60);
} catch (Exception hata) {
}

Android - Run a thread repeatingly within a timer

First of all, I could not even chose the method to use, i'm reading for hours now and someone says use 'Handlers', someone says use 'Timer'. Here's what I try to achieve:
At preferences, theres a setting(checkbox) which to enable / disable the repeating job. As that checkbox is checked, the timer should start to work and the thread should be executed every x seconds. As checkbox is unchecked, timer should stop.
Here's my code:
Checking whether if checkbox is checked or not, if checked 'refreshAllServers' void will be executed which does the job with timer.
boolean CheckboxPreference = prefs.getBoolean("checkboxPref", true);
if(CheckboxPreference == true) {
Main main = new Main();
main.refreshAllServers("start");
} else {
Main main = new Main();
main.refreshAllServers("stop");
}
The refreshAllServers void that does the timer job:
public void refreshAllServers(String start) {
if(start == "start") {
// Start the timer which will repeatingly execute the thread
} else {
// stop the timer
}
And here's how I execute my thread: (Works well without timer)
Thread myThread = new MyThread(-5);
myThread.start();
What I tried?
I tried any example I could see from Google (handlers, timer) none of them worked, I managed to start the timer once but stoping it did not work.
The simpliest & understandable code I saw in my research was this:
new java.util.Timer().schedule(
new java.util.TimerTask() {
#Override
public void run() {
// your code here
}
},
5000
);
Just simply use below snippet
private final Handler handler = new Handler();
private Runnable runnable = new Runnable() {
public void run() {
//
// Do the stuff
//
handler.postDelayed(this, 1000);
}
};
runnable.run();
To stop it use
handler.removeCallbacks(runnable);
Should do the trick.
Use a CountDownTimer. The way it works is it will call a method on each tick of the timer, and another method when the timer ends. At which point you can restart if needed. Also I think you should probably be kicking off AsyncTask rather than threads. Please don't try to manage your own threads in Android. Try as below. Its runs like a clock.
CountDownTimer myCountdownTimer = new CountDownTimer(30000, 1000) {
public void onTick(long millisUntilFinished) {
mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
// Kick off your AsyncTask here.
}
public void onFinish() {
mTextField.setText("done!");
// the 30 seconds is up now so do make any checks you need here.
}
}.start();
I would think to use AlarmManager http://developer.android.com/reference/android/app/AlarmManager.html
If checkbox is on call method where
AlarmManager alarmManager = (AlarmManager)SecureDocApplication.getContext()
.getSystemService(Context.ALARM_SERVICE);
PendingIntent myService = PendingIntent.getService(context, 0,
new Intent(context, MyService.class), 0);
long triggerAtTime = 1000;
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, triggerAtTime, 5000 /* 5 sec*/,
myService);
If checkbox is off cancel alarm manager
alarmManager.cancel(myService);
"[ScheduledThreadPoolExecutor] class is preferable to Timer when multiple worker threads are needed, or when the additional flexibility or capabilities of ThreadPoolExecutor (which this class extends) are required."
per...
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ScheduledThreadPoolExecutor.html
It's not much more than the handler, but has the option of running exactly every so often (vice a delay after each computation completion).
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
...
final int THREAD_POOL_SIZE = 10;
final int START_DELAY = 0;
final int TIME_PERIOD = 5;
final TimeUnit TIME_UNIT = TimeUnit.SECONDS;
ScheduledThreadPoolExecutor pool;
Runnable myPeriodicThread = new Runnable() {
#Override
public void run() {
refreshAllServers();
}
};
public void startTimer(){
pool.scheduleAtFixedRate(myPeriodicThread,
START_DELAY,
TIME_PERIOD,
TIME_UNIT);
}
public void stopTimer(){
pool.shutdownNow();
}
Thanks to everyone, I fixed this issue with using Timer.
timer = new Timer();
timer.scheduleAtFixedRate(
new java.util.TimerTask() {
#Override
public void run() {
for (int i = 0; i < server_amount; i++) {
servers[i] = "Updating...";
handler.sendEmptyMessage(0);
new MyThread(i).start();
}
}
},
2000, 5000);

How to change a TextView every second in Android

I've made a simple Android music player. I want to have a TextView that shows the current time in the song in minutes:seconds format. So the first thing I tried was to make the activity Runnable and put this in run():
int position = 0;
while (MPService.getMP() != null && position<MPService.duration) {
try {
Thread.sleep(1000);
position = MPService.getSongPosition();
} catch (InterruptedException e) {
return;
}
// ... convert position to formatted minutes:seconds string ...
currentTime.setText(time); // currentTime = (TextView) findViewById(R.id.current_time);
But that fails because I can only touch a TextView in the thread where it was created. So then I tried using runOnUiThread(), but that doesn't work because then Thread.sleep(1000) is called repeatedly on the main thread, so the activity just hangs at a blank screen. So any ideas how I can solve this?
new code:
private int startTime = 0;
private Handler timeHandler = new Handler();
private Runnable updateTime = new Runnable() {
public void run() {
final int start = startTime;
int millis = appService.getSongPosition() - start;
int seconds = (int) ((millis / 1000) % 60);
int minutes = (int) ((millis / 1000) / 60);
Log.d("seconds",Integer.toString(seconds)); // no problem here
if (seconds < 10) {
// this is hit, yet the text never changes from the original value of 0:00
currentTime.setText(String.format("%d:0%d",minutes,seconds));
} else {
currentTime.setText(String.format("%d:%d",minutes,seconds));
}
timeHandler.postAtTime(this,(((minutes*60)+seconds+1)*1000));
}
};
private ServiceConnection onService = new ServiceConnection() {
public void onServiceConnected(ComponentName className,
IBinder rawBinder) {
appService = ((MPService.LocalBinder)rawBinder).getService();
// start playing the song, etc.
if (startTime == 0) {
startTime = appService.getSongPosition();
timeHandler.removeCallbacks(updateTime);
timeHandler.postDelayed(updateTime,1000);
}
}
what about this:
int delay = 5000; // delay for 5 sec.
int period = 1000; // repeat every sec.
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask()
{
public void run()
{
//your code
}
}, delay, period);
Use a Timer for this (instead of a while loop with a Thread.Sleep in it). See this article for an example of how to use a timer to update a UI element periodically:
Updating the UI from a timer
Edit: updated way-back link, thanks to Arialdo: http://web.archive.org/web/20100126090836/http://developer.android.com/intl/zh-TW/resources/articles/timed-ui-updates.html
Edit 2: non way-back link, thanks to gatoatigrado: http://android-developers.blogspot.com/2007/11/stitch-in-time.html
You have to use a handler to handle the interaction with the GUI. Specifically a thread cannot touch ANYTHING on the main thread. You do something in a thread and if you NEED something to be changed in your main thread, then you call a handler and do it there.
Specifically it would look something like this:
Thread t = new Thread(new Runnable(){
... do stuff here
Handler.postMessage();
}
Then somewhere else in your code, you do
Handler h = new Handler(){
something something...
modify ui element here
}
Idea its like this, thread does something, notifies the handler, the handler then takes this message and does something like update a textview on the UI thread.
This is one more Timer example and I'm using this code in my project.
https://stackoverflow.com/a/18028882/1265456
I think the below blog article clearly gives a very nice solution. Especially, if you are a background service and want to regularly update your UI from this service using a timer-like functionality.
It really helped me, much more than the 2007 blog link posted by MusiGenesis above.
https://www.websmithing.com/2011/02/01/how-to-update-the-ui-in-an-android-activity-using-data-from-a-background-service/

Categories

Resources