I am developing an app that plays a stream by using the built-in Android Mediaplayer. Everything works fine apart the fact that when I press the "home" button and then open the activity again, the app just starts a new instance of the mediaplayer and I can hear the stream twice without the possibility to stop the first one.
Scenario.
My app is only made of one activity.
I open my app first time and the stream starts.
Push the home button and the activity is "minimized" but the music still plays
I open my app again and it just starts a new instance of the mediaplayer playing the same music twice.
I check onResume if the mediaplayer is null or playing but somehow it appears to be always null thus a new instance is created.
My pseudo code...
public class MainActivity {
private MediaPlayer _mp;
private PlayTask _playTask;
private PauseTask _pauseTask;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
protected void onResume(){
super.onResume();
if(_mp != null && _mp.isPlaying()){
// I should find a playing mediaplayer here but it's always null!!!
Toast.makeText(MainActivity.this, "Playing mediaplayer found!", Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(MainActivity.this, "No mediaplayer found :(", Toast.LENGTH_SHORT).show();
}
}
/* ...:::============= *** ASYNCTASK Definition START *** =============:::... */
private class PlayTask extends AsyncTask<Void, Void, Integer> {
#Override
protected void onPreExecute() {
if(_mp == null)
_mp = new MediaPlayer();
else if(_mp.isPlaying()){
_mp.stop();
_mp.release();
_mp = null;
_mp = new MediaPlayer();
}
}
#Override
protected Integer doInBackground(Void...voids) {
try{
_mp.setDataSource(URL_DATASOURCE);
_mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
_mp.prepare();
_mp.start();
}
catch(Exception ex){
}
return 0;
}
#Override
protected void onPostExecute(Integer i) {
}
}
private class PauseTask extends AsyncTask<Void, Void, Integer> {
#Override
protected void onPreExecute() {
// Do Nothing here...for now
}
#Override
protected Integer doInBackground(Void...voids) {
_mp.stop();
_mp.release();
_mp = null;
return 0;
}
#Override
protected void onPostExecute(Integer i) {
}
}
public void playPause(View view){
if(_play){
_playTask = new PlayTask();
_playTask.execute();
}
else{
_pauseTask = new PauseTask();
_pauseTask.execute();
}
}
}
Any idea? Thanks
Related
hi i'm trying to create a simple Online Radio i want to keep radio playing in bakcground and i know i should use Service but i don't how to use it please help me to make my app radio keep playing in background
this my code :
Button b_play ;
MediaPlayer mediaPlayer ;
boolean prepared = false;
boolean started = false;
String stream = "http://stream.radio.co/s98f81d47e/listen";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
b_play = (Button)findViewById(R.id.b_play);
b_play.setEnabled(false);
b_play.setText("Loading");
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
new PlayerTask().execute(stream);
b_play.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(started){
started = false;
mediaPlayer.pause();
b_play.setText("Play");
}else{
started = true;
mediaPlayer.start();
b_play.setText("Pause");
}
}
});
}
class PlayerTask extends AsyncTask<String, Void ,Boolean>{
#Override
protected Boolean doInBackground(String... strings) {
try {
mediaPlayer.setDataSource(strings[0]);
mediaPlayer.prepare();
prepared = true;
} catch (IOException e) {
e.printStackTrace();
}
return prepared;
}
#Override
protected void onPostExecute(Boolean aBoolean) {
super.onPostExecute(aBoolean);
b_play.setEnabled(true);
b_play.setText("Play");
}
}
#Override
protected void onPause() {
super.onPause();
if(started){
mediaPlayer.pause();
}
}
#Override
protected void onResume() {
super.onResume();
if(started){
mediaPlayer.start();
}
}
#Override
protected void onDestroy() {
super.onDestroy();
if(prepared){
mediaPlayer.release();
}
}
}
Play the music from the foreground service.
Official Android documentation says:
that is a service that the user is actively aware of and is not a
candidate for the system to kill when low on memory. A foreground
service must provide a notification for the status bar, which is
placed under the Ongoing heading. This means that the notification
cannot be dismissed unless the service is either stopped or removed
from the foreground.
In your case a radio that plays music from a service should be set to run in the foreground, because the user is explicitly aware of its operation. The notification in the status bar might indicate the current song and allow the user to launch an activity to interact with the music player.
Here is an example
I am loading video from async task. When video took too long to load then back press to cancel.
My code here
public class LiveStreaming extends AppCompatActivity {
VideoView videoView;
private myAsync sync;
ProgressDialog progressDialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_live_streaming);
String videourl = getIntent().getStringExtra("Link");
videoView = (VideoView) findViewById(R.id.videoStreaming);
progressDialog = ProgressDialog.show(this, "",
"Loading TV...", true);
progressDialog.setCancelable(false);
// progressDialog.dismiss();
MediaController mediaController = new MediaController(this);
mediaController.setAnchorView(videoView);
Uri video = Uri.parse(videourl);// insert video url
videoView.setMediaController(mediaController);
videoView.setVideoURI(video);
videoView.requestFocus();
sync = new myAsync();
sync.execute();
// PlayVideo();
}
private class myAsync extends AsyncTask<Void, Integer, Void> {
int duration = 0;
int current = 0;
private volatile boolean running = true;
#Override
protected void onCancelled() {
running = true;
}
#Override
protected void onPreExecute() {
}
#Override
protected Void doInBackground(Void... params) {
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
public void onPrepared(MediaPlayer mp) {
progressDialog.dismiss();
videoView.start();
duration = videoView.getDuration();
}
});
do {
current = videoView.getCurrentPosition();
System.out.println("duration - " + duration + " current- "
+ current);
if (sync.isCancelled())
break;
}
while (current != duration || current == 0);
return null;
}
}
#Override
public void onBackPressed() {
super.onBackPressed();
if (sync!=null){
this.finish();
}
}
}
I debugged my app.
When back pressed then method wasn't called. I don't know what is the problem
Thank you
remove super.onBackPressed(); for onBackPressed() to work.And to cancel the async you can call sync.cancel()
Declare your async task in your activity.
private YourAsyncTask mTask;
Instantiate your async task where you want to use
mTask = new YourAsyncTask().execute();
And then cancel where you want to stop the task
mTask.cancel(true);
Hope this helps
I'm facing a problem: I created two Activities.
One is the main Activity, which has a Button.
When I click this Button, the second Activity starts.
The second Activity uses an Asynctask in which a number is incremented from 1 to 10 and displays this number in a Textview
What I'm facing is that when I click the back Button while the Asynctask has not completed and then again go to the second Activity the Asynctask is not run from start immediately.
I know because in background when it completed the old task then it again starts a new task. Is there a way to fix this when destroying the Activity it also destroy the Asynctask?
Here is video sample for my problem.
Code for Main Activity:
public class MainActivity extends AppCompatActivity {
Button bt;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bt = (Button) findViewById(R.id.bt);
bt.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(MainActivity.this,SecondAcitivity.class);
startActivity(i);
}
});
}
}
Code of Second Activity:
public class SecondAcitivity extends AppCompatActivity {
TextView t1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second_acitivity);
t1 = (TextView) findViewById(R.id.t1);
OurWork obj = new OurWork();
obj.execute();
}
class OurWork extends AsyncTask<Void, Integer, String> {
#Override
protected String doInBackground(Void... params) {
int i = 0;
while (i < 11) {
try {
Thread.sleep(700);
publishProgress(i);
i++;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return "Successfully Completed";
}
#Override
protected void onProgressUpdate(Integer... values) {
t1.setText(values[0] + "%");
}
#Override
protected void onPostExecute(String result) {
t1.setText(result);
}
}
}
you need to cancel the task on back pressed, and you need to monitor if the task is canceled while executing the doInbackground().
1- override onbackpressed:
#Override
public void onBackPressed() {
obj.cancel(true); // where obj is the asyncTask refernce object name
super.onBackPressed();
}
2- monitor isCanceled()
#Override
protected String doInBackground(Void... params) {
int i = 0;
while (i < 11 && !isCancelled()) { // added !isCancelled()
try {
Thread.sleep(700);
publishProgress(i);
i++;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return "Successfully Completed";
}
on next iteration of the while loop, after cancel(true); is called,the loop will quit, and doInBackground() will return.
When you press back button , onBackPressed callback is called. so you can basically try this :
#Override
public void onBackPressed() {
if (asyncFetch.getStatus() == AsyncTask.Status.RUNNING) {
asyncFetch.cancel(true);
}
finish();
}
Try to use :
private OurWork task;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second_acitivity);
t1 = (TextView) findViewById(R.id.t1);
task = new OurWork();
task.execute();
}
#Override
public void onBackPressed() {
task.cancel(true);
super.onBackPressed();
}
AsyncTask runs in background of the activity where it was hosted. If OnPause or OnDestroy is called, AsyncTask is destroyed, so to solve this issue, Override OnResume and execute AsyncTask again.
To cancel the asyncTask even when it is running when back is pressed, add this to onBackPressed:
public class SecondAcitivity extends AppCompatActivity {
TextView t1;
static OurWork obj;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second_acitivity);
t1 = (TextView) findViewById(R.id.t1);
obj = new OurWork();
obj.execute();
}
class OurWork extends AsyncTask<Void, Integer, String> {
#Override
protected String doInBackground(Void... params) {
int i = 0;
while (i < 11) {
try {
Thread.sleep(700);
publishProgress(i);
i++;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return "Successfully Completed";
}
#Override
protected void onProgressUpdate(Integer... values) {
t1.setText(values[0] + "%");
}
#Override
protected void onPostExecute(String result) {
t1.setText(result);
}
}
//override onBackPressed and do this
#Override
public void onBackPressed() {
if (obj!=null && (obj.getStatus()== AsyncTask.Status.RUNNING ||
obj.getStatus()== AsyncTask.Status.PENDING ))
obj.cancel(true);
super.onBackPressed();
}
}
Im working on music player for Android and I need to get static time to start playing music. Acutally command context.player.start() take random time from range <2;20> [ms] but I need to get static time of accomplishing method. My code is below. I mean that time difference between "before call method time" and "just after method accomplished time" need to be static (method should take static time)
public class SpeakerActivity extends AppCompatActivity {
MusicPlayer player;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_speaker);
player = new MusicPlayer(SpeakerActivity.this);
run();
}
private void run() {
AsyncTask.execute(new Runnable() {
#Override
public void run() {
ClientTask ct = new ClientTask(SpeakerActivity.this);
try {
ct.run();
} catch (IOException e1) {
e1.printStackTrace();
}
}
});
}
}
public class ClientTask extends Listener {
ClientTask(Context context) { this.context = context);}
...
//I'm only going to implement this method from Listener.class because I only need to use this one.
public void received(Connection c, Object p){
//Is the received packet the same class as PacketMessage.class?
if(p instanceof PacketMessage){
//Cast it, so we can access the message within.
PacketMessage packet = (PacketMessage) p;
if(packet.message.charAt(0) == 'p') {
String latencyString = packet.message.replace('p','0');
int latency = Integer.parseInt(latencyString);
try {
Thread.sleep(latency);
context.player.start(); <---- THIS LINE TAKE RANDOM AMOUNT OF TIME
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public class MusicPlayer {
private MediaPlayer player;
private Context context;
public MusicPlayer(Context context) {
this.context = context;
player = MediaPlayer.create(context, R.raw.zero);
}
public void start() {
player.start();
}
public void stop() {
player.stop();
}
}
Does anybody know whats wrong?
I am using a music in background of my activity. But when i am trying to cancel it its not working. The music is just continuously running until it finishes itself. Below is the code:
public class xx extends Activity
{ BackgroundSound mBackgroundSound = new BackgroundSound();
#Override
protected void onCreate(Bundle savedInstanceState)
{ ....
}
#Override
protected void onResume()
{
super.onResume();
mBackgroundSound.execute();
}
#Override
protected void onPause()
{
super.onPause();
mBackgroundSound.cancel(true);
}
and for options menu selection:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
mBackgroundSound.cancel(true);
NavUtils.navigateUpFromSameTask(this);
return true;
case R.id.menu_Add:
{ mBackgroundSound.cancel(true);
Intent intent = new Intent(xx.this,yy.class);
intent.putExtra("flag", "add");
intent.putExtra("AddObj", "mm");
startActivity(intent);
break;
}
case R.id.menu_list_quote:
{
mBackgroundSound.cancel(true);
Intent intent = new Intent(xx.this,zz.class);
intent.putExtra("Obj", "nn");
startActivity(intent);
break;
}
}
//return true;
return super.onOptionsItemSelected(item);
}
and the asynTask:
public class BackgroundSound extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
try
{
while( !isCancelled())
{
// FileDescriptor afd = openFd("cock_alarm.mp3");
MediaPlayer player = new MediaPlayer();
player.setDataSource(_musicFilePath);
player.prepare();
//player.setLooping(true); // Set looping
player.setVolume(100,100);
player.start();
// if(isCancelled())
// player.stop();
}
}
catch(Exception exp)
{
exp.printStackTrace();
}
return null;
}
}
Also, tried using for loop:
for(int i=0;i<100 && !isCancelled();i++)
and tried this inside try block of asyncTask:
if(isCancelled())
player.stop();
How am i going to solve it?
Instead of creating an AsyncTask, why not just create the MediaPlayer, and start it from your activity?
The MediaPlayer has its own threading logic built into it. You don't need to create a thread to manage the media player. You can read more here: http://developer.android.com/guide/topics/media/mediaplayer.html
In your activity, you could do the following:
private MediaPlayer mMediaPlayer;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Initalize the media player
mMediaPlayer = ... however you are initializing it ...;
// Set the listener so the media player can tell you when it is finished preparing
mMediaPlayer.setOnPreparedListener(this);
// Prepare the MediaPlayer asynchronously so that the UI thread does not lock up
mMediaPlayer.prepareAsync();
}
// You need to listen for when the Media Player is finished preparing and is ready
public void onPrepared(MediaPlayer player) {
// Start the player
player.start();
}
Then whenever you need to stop the player, simply call
mMediaPlayer.stop();
As, vogella explains it on his website:
"The AsyncTask does not handle configuration changes automatically, i.e. if the activity is recreated, the programmer has to handle that in his coding.
A common solution to this is to declare the AsyncTask in a retained headless fragment."
Look for full text to:
http://www.vogella.com/tutorials/AndroidBackgroundProcessing/article.html#androidbackground