I set a sound when I check the button
public void Button(View v) {
final MediaPlayer mpStart = MediaPlayer.create(this, R.raw.startsound);
mpStart.start();
}
I want to wait some time before the sound starts.
How can i do?
One solution is to use Handler.postDelayed() method.
#Override
public void onClick(View v) {
// This solution will leak memory! Actually don't use!!!
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
final MediaPlayer mpStart = MediaPlayer.create(this, R.raw.startsound);
mpStart.start();
}
}, 2000); //Here change the time to wait in milliseconds
}
For more Info look here: Pause a process
Related
I have a daily alarm and a settings page that allow users to change the timing that the daily alarm fires. I have a OnSharedPreferenceChangeListener in my SettingsFragment that extends PreferenceFragmentCompat and it is working here. However, when I do the same thing in my MainActivity, it does not seem to be working.
This is my code in Main Activity:
'''
public class MainActivity extends AppCompatActivity {
//some other variables
private SharedPreferences.OnSharedPreferenceChangeListener preferenceChangeListener;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//some other code
preferenceChangeListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (key.equals("daily alarm time")){
int alarmTime = sharedPreferences.getInt("daily alarm time", 36000000);
setdailyalarm(alarmTime, true, false);
System.out.println("onsharedpreferencechange activited");
}
if (key.equals("daily alarm toggle")){
Boolean dailyAlarmToggle = sharedPreferences.getBoolean(key, true);
System.out.println("111111111111111111111111");
if (dailyAlarmToggle){
int alarmTime = sharedPreferences.getInt(key, 36000000);
setdailyalarm(alarmTime, true, false);
}
else{
int alarmTime = sharedPreferences.getInt(key, 36000000);
setdailyalarm(alarmTime, true, true);
}
}
}
};
}
'''
This is my onpause and onresume:
'''
#Override
protected void onPause() {
super.onPause();
PreferenceManager.getDefaultSharedPreferences(this).unregisterOnSharedPreferenceChangeListener(preferenceChangeListener);
}
#Override
protected void onResume() {
super.onResume();
PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(preferenceChangeListener);
}
'''
When I start my app and check my System.out, '''System.out.println("onsharedpreferencechange activited");''' does not seem to be firing which means my OnSharedPreferenceChangeListener is not working. I have seem the other discussions SharedPreferences.onSharedPreferenceChangeListener not being called consistently but it does not seem to be the solution to my problem.
When I start my app and check my System.out, '''System.out.println("onsharedpreferencechange activited");''' does not seem to be firing which means my OnSharedPreferenceChangeListener is not working.
It's because you're always unregistering the listener in your onPause(). So, whenever you leave the activity, the listener is removed and you can't listen for the SharedPreferences changes.
You could register the listener inside your onCreate() method.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// setup the listener
preferenceChangeListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
...
// then register it
PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(preferenceChangeListener);
}
Then unregister the listener when you close the activity by overriding the onDestroy() method:
#Override
public void onDestroy() {
PreferenceManager.getDefaultSharedPreferences(this).unregisterOnSharedPreferenceChangeListener(preferenceChangeListener);
super.onDestroy();
}
Or unregister the listener whenever you call finish() method. Either call the unregister part before finish() or overriding the finish() method.
I'm building an app in Android Studio for countdown timer from 40 min, I want to get notification after the time is complete, the problem is where should I put the codes for notification for it to appear after the countdown is complete.
this is what I have trying and it clashes after the countdown
public void startTimer() {
CountDownTimer cdt= new CountDownTimer(60000, 1000) {
#Override
public void onTick(long millisUntilFinished) {
timeLeft = millisUntilFinished;
updateTimer();
}
#Override
public void onFinish() {
NewMessageNotification sms = new NewMessageNotification();
sms.notify();
}
};
cdt.start();
startBtn.setText("PAUSE");
timeRunning = true;
}
The CountDownTimer class has two callbacks: onTick(long millisUntilFinished) and onFinish(). The first is fired on regular intervals while the second is fired when the time is up.
So if you want the notification to be shown when time is up, your code should be added inside the onFinish() exactly where you override it.
Example:
CountDownTimer cdt = new CountDownTimer(30000, 1000) {
#override
public void onTick(long millisUntilFinished) {
//code for regular intervals or nothing
}
#override
public void onFinish() {
//your code for notification
}
};
cdt.start();
And it's done
In my JavaFX Application I want to disable a couple of Buttons during a refresh of the data from a database.
I am using the disableProperty of the Buttons I want to disable.
Here is the basic JavaFX Application, modefied to illustrate my point:
public class BindLengthy extends Application {
BooleanProperty disable = new SimpleBooleanProperty(false);
#Override
public void start(Stage primaryStage) {
Button btn = new Button();
btn.setText("Say 'Hello World'");
btn.disableProperty().bind(disable);
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
disable.set(true);
try {
Thread.sleep(5000);
} catch (InterruptedException ex) {
Logger.getLogger(BindLengthy.class.getName()).log(Level.SEVERE, null, ex);
}
btn.setText("Done");
}
});
//Do all the other stuff that needs to be done to launch the application
//Like adding btn to the scene and so on...
primaryStage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
When executed, on the click the Button stays in the "fired" mode, waits for 5 Seconds and then changes text and disables. While I want the text to change later, I want to disableProperty Change to take effect immediately!
I tried putting the lengthy operation, represented by Thread.sleep(5000) into a task and start it on a new Thread(task), but then obviously the text is changes before the Thread awakens.
I can't put the btn.setText("Done")into the Threadas it wouldn't be executed on the JavaFX-Thread(which it needs to). So I tried joining the Thread, yet that gives the same result as not putting it into an extra Thread as well.
How can I force the diableProperty to register the new value before executing my long operation?
Use a Task and use its onSucceeded handler to update the UI:
public class BindLengthy extends Application {
BooleanProperty disable = new SimpleBooleanProperty(false);
#Override
public void start(Stage primaryStage) {
Button btn = new Button();
btn.setText("Say 'Hello World'");
btn.disableProperty().bind(disable);
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
disable.set(true);
Task<String> task = new Task<String>() {
#Override
public String call() throws Exception {
Thread.sleep(5000);
return "Done" ;
}
});
task.setOnFailed(e ->
Logger.getLogger(BindLengthy.class.getName())
.log(Level.SEVERE, null, task.getException()));
task.setOnSucceeded(e -> {
btn.setText(task.getValue());
disable.set(false);
});
Thread t = new Thread(task);
t.setDaemon(true);
t.start();
}
});
//Do all the other stuff that needs to be done to launch the application
//Like adding btn to the scene and so on...
primaryStage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
I want to develop a Java program playing an mp3-file in a specific manner. I marked a number of fragments in this file with startTime and endTime. The program should play the first fragment and then sleep for 5 seconds. Then play the second fragment and sleep again. And so on. I use JavaFX class MediaPlayer. The program prototype is as follows:
import javafx.application.Application;
import javafx.stage.Stage;
import java.io.FileNotFoundException;
import java.io.IOException;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.util.Duration;
import java.util.concurrent.TimeUnit;
public class JavaFXMediaPlayer02 extends Application {
#Override
public void start(Stage stage) throws FileNotFoundException,IOException,InterruptedException {
Media media = new Media("file:///D:/1016_00.mp3");
MediaPlayer mediaPlayer = new MediaPlayer(media);
//Set and play the first fragment of mp3-file
mediaPlayer.setStartTime(Duration.millis(1219.0));
mediaPlayer.setStopTime(Duration.millis(2728.0));
mediaPlayer.play();
System.out.println("1st fragment played!");
TimeUnit.SECONDS.sleep(5);
//Set and play the second fragment
mediaPlayer.setStartTime(Duration.millis(3947.0));
mediaPlayer.setStopTime(Duration.millis(6629.0));
mediaPlayer.play();
System.out.println("2nd fragment played!");
TimeUnit.SECONDS.sleep(5);
//Set and play the second fragment
mediaPlayer.setStartTime(Duration.millis(7453.0));
mediaPlayer.setStopTime(Duration.millis(10704.0));
mediaPlayer.play();
System.out.println("3rd fragment played!");
}
public static void main(String[] args) {
launch(args);
}
}
But I only hear the 3rd fragment. What's the matter? Why don't I hear the first and the second fragments? How to correct my program? Isn't JavaFX an appropriate tool for my task?
The problem here lies in the TimeUnit.SECONDS.sleep(5); invokation. This method sets the current thread into sleep. And in your case this thread is the JavaFX Application Thread. That causes the whole application to "freeze" (which would be more obviously if you added some GUI-Elements) and therefore the mediaPlayer.play(); commands are executed, but are instantly "freezed" because of the sleep function. After the `TimeUnit.SECONDS.sleep(5); calls, you set new start and end times for your MediaPlayer and execute play() again, so that the track starts at the new start time. Thats why only your last fragment is played.
Now to the solution:
You should never invoke Thread.sleep() or similar methods on the JavaFX App Thread. But in your case you have to wait a certain amount of time between playing the fragments. The first approach would be invoke Thread.sleep() or TimeUnit.SECONDS.sleep(5); on a new thread and call the Mediaplayer methods on the JFX App Thread. But that doesn't work properly because you haven't set up an "order" in which the threads are called. There are various ways to do this (via Semaphores, Locks and Conditions, JavaFX Concurrency and so on...)
I tried to solve your problem by doing some quick-and-dirty programming, but i came across a problem with mediaPlayer.setStopTime(Duration.millis());. It does not seem to work on my computers, so that the files are always played to the end. I added a stop button to simulate the automatic stopping.
The following class sets the new start and endpoints and plays the fragment. If the mediaplayer is stops, it calls the next fragment on the LittleMediaScheduler class.
public class LittleMediaHelper implements Runnable {
public double startTime;
public double endTime;
public MediaPlayer player;
public int id;
public LittleMediaScheduler scheduler;
public LittleMediaHelper(double startTime, double endTime,
MediaPlayer player, int id) {
this.startTime = startTime;
this.endTime = endTime;
this.player = player;
this.id = id;
}
public LittleMediaScheduler getScheduler() {
return scheduler;
}
public void setScheduler(LittleMediaScheduler scheduler) {
this.scheduler = scheduler;
}
#Override
public void run() {
Platform.runLater(new Runnable() {
#Override
public void run() {
player.setStartTime(Duration.millis(startTime));
player.setStopTime(Duration.millis(endTime));
System.out.println(player.getStartTime());
System.out.println(player.getStopTime());
player.play();
player.setOnStopped(new Runnable() {
#Override
public void run() {
int idtmp = id + 1;
System.out.println("NEXT " + idtmp);
scheduler.call(idtmp);
}
});
}
});
}
}
This class is responsibly for sleeping a certain amount on a new thread and after successfully sleeping invoking the next LittleMediaHelper class play functionality.
public class LittleMediaScheduler {
private ArrayList<LittleMediaHelper> hArrL;
private int SLEEPTIME = 2000;
public LittleMediaScheduler(LittleMediaHelper... helpers) {
this.hArrL = new ArrayList<>();
for (LittleMediaHelper h : helpers) {
h.setScheduler(this);
System.out.println(h.startTime);
this.hArrL.add(h);
}
System.out.println(hArrL.size());
}
public void init() {
Thread t = new Thread(this.hArrL.get(0));
t.start();
}
public void call(final int id) {
Thread t = new Thread(new Task<String>() {
#Override
protected String call() throws Exception {
Thread.sleep(SLEEPTIME);
return null;
}
#Override
protected void succeeded() {
super.succeeded();
System.out.println("Next playing...");
if (id > LittleMediaScheduler.this.hArrL.size() - 1) {
return;
}
LittleMediaHelper next = LittleMediaScheduler.this.hArrL
.get(id);
Thread nextT = new Thread(next);
nextT.start();
}
});
t.start();
}
}
The main class with a stop button. Without mediaPlayer.pause() the player somehow repeats one step twice although new start end endpoints are set. Don't know if this is a bug or not.
public class JavaFXMediaPlayer02 extends Application {
#Override
public void start(Stage stage) throws FileNotFoundException, IOException,
InterruptedException {
Media media = new Media("file:///C:/test.mp3");
final MediaPlayer mediaPlayer = new MediaPlayer(media);
LittleMediaHelper phase1 = new LittleMediaHelper(0, 1000, mediaPlayer,
0);
LittleMediaHelper phase2 = new LittleMediaHelper(50000, 55000,
mediaPlayer, 1);
LittleMediaHelper phase3 = new LittleMediaHelper(200000, 200500,
mediaPlayer, 2);
LittleMediaScheduler scheduler = new LittleMediaScheduler(phase1,
phase2, phase3);
scheduler.init();
Group g = new Group();
Button b = new Button("STOP");
b.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent arg0) {
mediaPlayer.pause();
mediaPlayer.stop();
}
});
g.getChildren().add(b);
Scene sc = new Scene(g);
stage.setScene(sc);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
I want to disable a button for a specific time in JavaFX application. Is there any option to do this? If not, is there any work around for this?
Below is my code in application. I tried Thread.sleep, but i know this is not the good way to stop the user from clicking on next button.
nextButton.setDisable(true);
final Timeline animation = new Timeline(
new KeyFrame(Duration.seconds(delayTime),
new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent actionEvent) {
nextButton.setDisable(false);
}
}));
animation.setCycleCount(1);
animation.play();
You could use the simple approach of a thread that provides the relevant GUI calls (through runLater() of course):
new Thread() {
public void run() {
Platform.runLater(new Runnable() {
public void run() {
myButton.setDisable(true);
}
}
try {
Thread.sleep(5000); //5 seconds, obviously replace with your chosen time
}
catch(InterruptedException ex) {
}
Platform.runLater(new Runnable() {
public void run() {
myButton.setDisable(false);
}
}
}
}.start();
It's perhaps not the neatest way of achieving it, but works safely.
You could also be using the Timeline:
final Button myButton = new Button("Wait for " + delayTime + " seconds.");
myButton.setDisable(true);
final Timeline animation = new Timeline(
new KeyFrame(Duration.seconds(delayTime),
new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent actionEvent) {
myButton.setDisable(false);
}
}));
animation.setCycleCount(1);
animation.play();
The method to disable a JavaFX control is:
myButton.setDisable(true);
You can implement the time logic programmatically in any way you wish, either by polling a timer or by having this method invoked in response to some event.
If you have created this button instance through FXML in SceneBuilder, then you should assign the button an fx:id so that its reference is automatically injected into your controller object during the loading of the scene graph. This will make it easier for you to work with in your controller code.
If you have created this button programmatically, then you'll already have its reference available in your code.
Or you could use a Service and bind the running property to the disableProperty of the button do you want to disable.
public void start(Stage stage) throws Exception {
VBox vbox = new VBox(10.0);
vbox.setAlignment(Pos.CENTER);
final Button button = new Button("Your Button Name");
button.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
Service<Void> service = new Service<Void>() {
#Override
protected Task<Void> createTask() {
return new Task<Void>() {
#Override
protected Void call() throws Exception {
Thread.sleep(5000);//Waiting time
return null;
}
};
}
};
button.disableProperty().bind(service.runningProperty());
service.start();
}
});
vbox.getChildren().addAll(button);
Scene scene = new Scene(vbox, 300, 300);
stage.setScene(scene);
stage.show();
}
But the Timeline solution given by Uluk Biy, looks more elegant.