After successfully implementing sounds on my weather app, it plays quite OK when a city is searched. But the problem is that even when I minimize the app, it still keeps playing the sounds on repeat until I close/exit the app. I would like it to pause when I minimize the app, then continue playing from exactly where it stopped the moment I enter back.
So I tried adding this code:
@Override
public void onStop() {
super.onStop();
mMediaPlayer.pause();
}
@Override
public void onDestroy() {
super.onDestroy();
mMediaPlayer.pause();
}
It only entirely stops the sound after minimizing and doesn't resume when entering back. It also slows the app from searching a city.
Also, the app contains 3 fragments(today, hourly and daily tabs) which I navigate through by clicking on the bottom navs. If I'm on the first tab and the sound is playing then I switch to the 2nd/3rd tab then move back to the first tab, the sound automatically restarts whichever sound it is playing. I would like to resolve the issue also.
Here is the Fragment's code:
public class FirstFragment extends Fragment {
private WeatherDataViewModel viewModel;
private MediaPlayer mMediaPlayer; // Single MediaPlayer object
public FirstFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.fragment_first, container, false);
// For displaying weather data
final TextView current_temp = rootView.findViewById(R.id.textView10);
final TextView current_output = rootView.findViewById(R.id.textView11);
final TextView rise_time = rootView.findViewById(R.id.textView25);
final TextView set_time = rootView.findViewById(R.id.textView26);
final TextView temp_out = rootView.findViewById(R.id.textView28);
final TextView Press_out = rootView.findViewById(R.id.textView29);
final TextView Humid_out = rootView.findViewById(R.id.textView30);
final TextView Ws_out = rootView.findViewById(R.id.textView33);
final TextView Visi_out = rootView.findViewById(R.id.textView34);
final TextView Cloud_out = rootView.findViewById(R.id.textView35);
final ImageView current_icon = rootView.findViewById(R.id.imageView6);
final SwipeRefreshLayout realSwipe = rootView.findViewById(R.id.real_swipe);
// Get our ViewModel instance
viewModel = new ViewModelProvider(this).get(WeatherDataViewModel.class);
// And whenever the data changes, refresh the UI
viewModel.getWeatherDataLiveData().observe(getViewLifecycleOwner(), data -> {
realSwipe.setOnRefreshListener(() -> {
// perform you action here for ex. add refresh screen code here
new Handler().postDelayed(() -> {
// this code is for stop refreshing icon, After 1000 ms automatically refresh icon will stop
realSwipe.setRefreshing(false);
}, 1000);
});
int drawableResource = -1; // here define default icon for example R.drawable.default_weather_icon
int soundResource = -1; // Default sound is nothing
if (data != null) {
current_temp.setVisibility(View.VISIBLE);
current_temp.setText(data.getMain().getTemp() " ℃"); // for that you can use strings resource and templates more in https://developer.android.com/guide/topics/resources/string-resource.html#formatting-strings
current_output.setVisibility(View.VISIBLE);
current_output.setText(data.getWeather().get(0).getDescription());
rise_time.setVisibility(View.VISIBLE);
rise_time.setText(data.getSys().getSunrise() " ");
set_time.setVisibility(View.VISIBLE);
set_time.setText(data.getSys().getSunset() " ");
temp_out.setVisibility(View.VISIBLE);
temp_out.setText(data.getMain().getTemp() " ℃");
Press_out.setVisibility(View.VISIBLE);
Press_out.setText(data.getMain().getPressure() " hpa");
Humid_out.setVisibility(View.VISIBLE);
Humid_out.setText(data.getMain().getHumidity() " %");
Ws_out.setVisibility(View.VISIBLE);
Ws_out.setText(data.getWind().getSpeed() " Km/h");
Visi_out.setVisibility(View.VISIBLE);
Visi_out.setText(data.getVisibility() " m");
Cloud_out.setVisibility(View.VISIBLE);
Cloud_out.setText(data.getClouds().getAll() " %");
// get actual weather.
String icon = data.getWeather().get(0).getIcon();
switch (icon) {
case "01d":
case "01n":
drawableResource = R.drawable.sun;
soundResource = R.raw.clear_sky_sound;
break;
case "02d":
case "021n":
drawableResource = R.drawable.few_clouds;
soundResource = R.raw.clouds_sound;
break;
case "03d":
case "03n":
drawableResource = R.drawable.scattered_clouds;
soundResource = R.raw.clouds_sound;
break;
case "04d":
case "04n":
drawableResource = R.drawable.broken_clouds;
soundResource = R.raw.clouds_sound;
break;
case "09d":
case "09n":
drawableResource = R.drawable.shower_rain;
soundResource = R.raw.shower_rain_sound;
break;
case "10d":
case "10n":
drawableResource = R.drawable.small_rain;
soundResource = R.raw.shower_rain_sound;
break;
case "11d":
case "11n":
drawableResource = R.drawable.thunderstorm;
soundResource = R.raw.thunderstorm_sound;
break;
case "13d":
case "13n":
drawableResource = R.drawable.snow;
soundResource = R.raw.snow_sound;
break;
case "50d":
case "50n":
drawableResource = R.drawable.mist;
soundResource = R.raw.mist_sound;
break;
}
if (drawableResource != -1)
current_icon.setImageResource(drawableResource);
if (soundResource != -1) {
if (mMediaPlayer != null) {
// stop the playing
if (mMediaPlayer.isPlaying()) {
mMediaPlayer.stop();
}
// release mMediaPlayer resoruces
mMediaPlayer.release();
mMediaPlayer = null;
}
// Play the new resource
prepareMediaPlayer(soundResource);
}
} else {
Log.e("TAG", "No City found");
current_temp.setVisibility(View.GONE);
current_output.setVisibility(View.GONE);
rise_time.setVisibility(View.GONE);
set_time.setVisibility(View.GONE);
temp_out.setVisibility(View.GONE);
Press_out.setVisibility(View.GONE);
Humid_out.setVisibility(View.GONE);
Ws_out.setVisibility(View.GONE);
Visi_out.setVisibility(View.GONE);
Cloud_out.setVisibility(View.GONE);
Toast.makeText(requireActivity(), "No City found", Toast.LENGTH_SHORT).show();
}
});
return rootView;
}
public void getWeatherData(String name) {
// The ViewModel controls loading the data, so we just
// tell it what the new name is - this kicks off loading
// the data, which will automatically call through to
// our observe() call when the data load completes
viewModel.setCityName(name);
}
private void prepareMediaPlayer(int resource) {
// add track file
mMediaPlayer = MediaPlayer.create(requireActivity(), resource);
// listening to when the media file finishes playing so that we can release the resources
mMediaPlayer.setLooping(true);
mMediaPlayer.start();
}
}
CodePudding user response:
when I minimize the app, it still keeps playing the sounds on repeat until I close/exit the app. I would like it to pause when I minimize the app, then continue playing from exactly where it stopped the moment I enter back.
You can pause the mediPlayer when the fragment is not shown on the screen i.e in onPause() callback, and resume it in onResume().
But be careful as the mediaPlayer doesn't start immediately in onCreate() because it waits until the data is grabbed from the weather API; so you need to do null-ability check:
public void onResume() {
super.onResume();
if (mMediaPlayer != null)
mMediaPlayer.start();
}
@Override
public void onPause() {
super.onPause();
if (mMediaPlayer != null)
mMediaPlayer.pause();
}
Side note: In order to avoid potential memory/battery leaks whenever you do fragment transaction, The mediaPlayer resource should be released if the application is destroyed:
@Override
public void onDestroy() {
super.onDestroy();
// release mMediaPlayer resoruces
mMediaPlayer.release();
mMediaPlayer = null;
}
But I would suggest to add the mMediaPlayer object into the ViewModel, in order to save its state during configuration changes like phone orientation.
CodePudding user response:
you need to use Services : https://developer.android.com/guide/components/services
see this simple exaple too : https://www.tutorialspoint.com/how-to-play-background-music-in-android-app
