Detect when app is put in the background

edited June 9 in Android Mode

When I open another random app while mine is running in the background weird things happen for instance rectMode randomly changes to anything but rectMode(CENTER); (which is what I actually want). At first I thought that perhaps somewhere in the code I call rectMode(CORNER); for instance and then I switch apps at which point the code cuts of and returns to the start of draw with rectMode set to left corner and that's why every rect goes haywire but this can't be the case since In my code I only call rectMode once and that is in the setup like this rectMode(CENTER); so I don't see why this happens

I thought I could just easily detect when my app has been put in the background and close it or something or just reset the "settings" like rectMode when the app was called out of the background. But this turns out to be harder than I thought so I was hoping someone could tell me how to detect when the app has been moved to the background or a way to stop it from glitching when in the background

Answers

  • I also just installed a sound library which works fine but when I switch to another app the music keeps playing even though I exited the app, this is also a reason I need to detect when an app has been put into the background.

  • Answer ✓

    What Android Mode are you using? To get the version of the Android Mode, click in add mode in the Processing IDE and select the Android mode. At the bottom of the Selection dialog box you will see the current mode installed in your machine. If you are using Android 3.0.2, then you can access the Android life cycle's function directly.... if you are using Android mode 4.0 or later... we need to discuss this further...

    Activity's life cycle: https://developer.android.com/guide/components/activities/activity-lifecycle.html

    But of course, a sketch is a fragment... close enough for starters. Previous posts using them, for example:

    https://forum.processing.org/two/search?Search=onresume

    Kf

  • edited June 9

    Thank you! I can't export apk from the processing IDE so I'm using the Android APDE for exporting and I haven't been able to find the version the APDE uses but activity's life cycle works fine so I'm assuming I'm using 3.0.2 although I ran into another problem

    I'm using the cassette library and to detect when the app has been put in the background and then stop the music I use this code

    @ Override
    public void onPause() {
      super.onPause();
      music.stop();
    }
    

    which works great but when I add this piece of code to restart the music when the app is opened the app crashes on start

    @ Override
    public void onResume() {
        super.onResume(); 
        music.loop();
    }
    

    I've modified the cassette library example so other people can run the code and see how / why it crashes

    import cassette.audiofiles.SoundFile;
    SoundFile music;
    
        void setup() {
            size(1000, 1000);
            background(255, 0, 0); 
            music = new SoundFile(this, "Crickets.mp3");
            music.loop();    
        }
    
        @ Override
        public void onPause() {
          super.onPause();
          music.stop();
        }
    
        @ Override
        public void onResume() {
            super.onResume();  
            music.loop();  
        }
    
        void draw() { 
        }
    
  • My first attempt would be to use line 7 in line 20. Or

    if(music==null){
      music = new SoundFile(this, "Crickets.mp3");
    }
    music.loop();
    

    Kf

  • @kfrajer Ah thanks you I thought I would always be loaded since it's done in setup but that's not the case I suppose. Anyway thank you that does indeed solve it but as usual, it also creates another problem no when I close the app it doesn't stop the music?

  • Hmmm let me suggest

    @ Override
    public void onPause() {
      music.stop();
      super.onPause();
    }
    

    Kf

  • edited June 10

    Thank you again it might seem like I just run into a problem and directly ask them but I am really trying to solve them myself although I just couldn't come up with a solution. In retrospect, I do understand the problem and why the solution works. That being said, I ran into a new problem, when you I exit the app the music does indeed stop but when you re-open it now it doesn't start playing. To keep everything from being confusing I added an edited version of the cassette library so show to problem

    import cassette.audiofiles.SoundFile;
    SoundFile music;
    
        void draw() {
        }
    
        void setup() {
          size(1000, 1000);
        }
    
        @ Override
          public void onPause() {
          music.stop();
          super.onPause();
        }
    
        @ Override
          public void onResume() {
          super.onResume();
          if (music==null) {
            music = new SoundFile(this, "Crickets.mp3");
          }
          music.loop();
        }
    

    Also I did move super.onResume(); to the end like this

    @ Override
      public void onResume() {
      if (music==null) {
        music = new SoundFile(this, "Crickets.mp3");
      }
      music.loop();
      super.onResume();
    }
    

    but it still doesn't work

  • I also tried making a boolean which would be turned true when the app opens and then the music would start in draw if the boolean is true but this doesn't start the music I think that public void onPause is the problem when I start music it stops it directly afterward (I think) Although I have no clue on how to fix this.

  • I think that public void onPause is the problem

    I am not able to help much atm related to Android. One suggestion is to write a file to your assets folder to see if onResume is being called. That is what I will do in this situation.

    Just to confirm, APDE v0.4.0 Alpha uses Android Mode v3.0.2 (0253) and Processing 3.0.1 (0247) and requires min. API 15 (Standard for this AM version).

    Quick question, when you move your code to APDE, do you also copy the cassette.jar library?

    Kf

  • You could also open a tix in github: https://github.com/Calsign/APDE/issues describing your issue. I tried running/stopping the cassette soundfile from onResume/onPause but there was no effect. It seems you need to call loop in setup() but then to stop it when the back button is pressed... hmmm One should use those native functions from its life cycle.

    Here is an idea:

    void keyPressed() {
    
      if(key==CODED){
       if(keyCode==MENU || keyCode==BACK){
         music.stop();
       }
      }  
    }
    

    I am not running from the APDE. I am running from Processing v3.3.4 and AM3.0.2 Now, When I send the app to the background, my above trick works. When I bring the app to the foreground, I cannot get it to play.

    A hack to the whole situation (untested) is to have a boolean flag that keeps track of the current status of the music player (is it playing?) When you resume your app, I will assume the flag is false. Then in draw(), you call music.loop() and enabled the flag. Therefore, calling loop should only occur if the flag is flase.

    void draw(){
       if(musicIsPlaying==false){
           music.loop();
           musicIsPlaying=true;   //This is a GLOBAL variable
       }
    }
    

    This is a tremendous hack and it is nice if it works but we shouldn't be doing this. Another alternative is to use the MediaPlayer as documented in the android Developer's website. However, I am not sure how easy is to setup this and run it in APDE. My experience is as limited as few exercises that I have done in the past. Is there any documentation on this App btw?

    Kf

  • edited June 12

    Right now I'm not at my desktop so I will post some documentation on the app soon after this but for now, I ran some more test with this code

    import cassette.audiofiles.SoundFile;
    SoundFile music;
    
    int musicIsPlaying;
    
    void setup() {
      music = new SoundFile(this, "Crickets.mp3");
      size(1000, 1000);
    }  
    
    void draw() {    
      background(0);
      text(musicIsPlaying, width/2, height/2);
    
      if (mousePressed) {
        musicIsPlaying ++;
        if (musicIsPlaying > 1) musicIsPlaying = 0;
      }         
    
      if (musicIsPlaying == 0) {
        music.play();
      } else music.stop();
    }
    

    and just like in the app the music does start in the beginning and after that, you can turn it off by tapping the screen but it doesn't start the music afterward? Perhaps it's a bug in the library instead of the APDE?

    I also tried to run your hack but it still doesn't start the music

  • Yes... this is very confusing. I have worked with the cassette library before but in the early days I didn't focus in life cycle management. I was even running your code directly from the Processing IDE on desktop and it didn't work as it should. Either the onXXXX methods are not being called or the hooks to manage the player (the music object in your case) is not doing what it suppose to do. I can say I have worked with onXXX functions in other apps through Processing Android Mode (version 3.0.2) and they do work which makes me to believe the problem is the cassette library. I can try getting an example running using the MediaPlayer. Can you access Android native libraries using the APDE? Last night I read their GitHub repo and they explained about the DX compilation process. I am not sure if I am going to go all the way to get that part working atm because it will take me a while to get everything setup. What I will do first is to make sure I get an example running In Processing Android Mode before doing testing in APDE.... or maybe you can do that part. I will get back to you about this probly tomorrow.

    Kf

  • edited June 12

    @kfrajer Thanks for your help.

    I tried to use the minim library but the Processing APDE does not support Minim because it depends upon the JavaSound API which is not available on Android. Other desktop libraries are not supported for similar reasons. Although I did try to install the default processing library ( I don't know If it depends upon the JavaSound API ) I tried anyway I downloaded the zip file from https://github.com/processing/processing-sound and the APDE doesn't recognize it after installing it but I think It might not be the distribution version of the library but I couldn't find one.

    In other news, I tried to install the Sound library example on my phone trough the processing IDE on my computer but It gives an error in Java mode and Android mode. Although this isn't a problem that needs to be solved now since I will have to export the apk trough the Processing APDE anyway.

    So, in conclusion, I don't yet know if processing default sound library works through APDE I have contact with the developer and I asked If he knew about any other sound libraries that are supported by the APDE. So I'll be waiting for a response and post any useful information that I get here.

    Also, I assumed you meant the minims or processing default library since you mentioned native librarys but please correct me if I'm wrong.

  • Oh my bad, I ran the code from this comment ( https://forum.processing.org/two/discussion/comment/80718/#Comment_80718 ) in the processing APDE and it works fine when you press the button it plays the music and if you press it again it does nothing (music continues ) although when I put the app in the background the music stops like it should but when I open it up again the music doesn't return and if you press the button then the app crashes. Altough that might just be a problem with the code?

  • @schotsl I will check it today as time permit. I ran out of time yesterday. Good to know it works with APDE. I will check how well it behaves with Processing, Android Mode 3.0.2 + onXXXXX() functions

    Kf

  • @schotsl

    Here below is a version tested in P3.3.3 and AM 3.0.2

    Instructions: Tap on the screen to toggle music playing state.
    Back button will ensure music stops playing, so does HOME and MENU buttons. When you return to your application....

    • If you returned after pressing the BACK button, you can play/pause the player

    • But if you pressed HOME/MENU, then when you come back you cannot access the player. The application quits without warning, probly because of the current error handling, aka. those try-catch blocks.

    Tagging @codeanticode:

    In this scenario, when the application is returning from the background, is setup() called at all? Also, is it guaranteed that setup() is called after onResume() (I am assuming they run strictly in that order - this claim hasn't been tested)

    Kf

        //REFEREENCE: https://forum.processing.org/two/discussion/comment/100364/#Comment_100364
        //REFEREENCE: https://developer.android.com/reference/android/media/MediaPlayer.html#start()
        //REFEREENCE: https://forum.processing.org/two/discussion/comment/80718/#Comment_80718
        
        
        import android.media.MediaPlayer;
        import  android.content.res.Resources;
        import android.content.res.AssetFileDescriptor;
        import android.content.res.AssetManager;
        import android.content.Context;
        import android.app.Activity;
        
        
        
        //===========================================================================
        // IMPORTS:
        
        import android.app.Activity;
        import android.content.Context;
        import android.widget.FrameLayout;
        //import android.app.Fragment;
        
        import android.os.Environment;
        import android.graphics.Color;
        import android.widget.Toast;
        import android.os.Looper;
        import android.view.WindowManager;
        import android.os.Bundle;
        import android.view.ViewParent;
        import android.view.ViewGroup;
        import android.view.View;
        import android.widget.RelativeLayout;
        import android.view.LayoutInflater;
        import android.R.string;
        
        
        //===========================================================================
        // FINAL FIELDS:
        
        
        //===========================================================================
        // GLOBAL VARIABLES:
        
        Activity act;
        Context mC;
        
        MediaPlayer snd = new MediaPlayer();
        //AssetManager assets = this.getAssets();
        AssetFileDescriptor fd;
        Context context;
        Button bPlay;
        
        
        void setup()
        {
          colorMode(HSB);
          size(800, 800);
          act = this.getActivity();
          context = act.getApplicationContext();
          try {
        
            fd = context.getAssets().openFd("Crickets.mp3");
            snd.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
          }
          catch (IllegalArgumentException e) {
            e.printStackTrace();
          }
          catch (IllegalStateException e) {
            e.printStackTrace();
          } 
          catch (IOException e) {
            e.printStackTrace();
          }
        
          bPlay = new Button(width/2, height/2, 500, color(0, 125, 255));
        }
        
        void draw()
        {
          background(210);
          bPlay.draw();
          textSize(30);
          textAlign(CENTER);
          fill(0, 21, 75);
          text("Press for replacement", width/2, height/2);
        }
        
        void mousePressed()
        {
          if (bPlay.isHovering  ()) {
        
            if (snd.isPlaying()==true) {
              try {
                snd.stop();
              } 
              catch (IllegalStateException e) {
                e.printStackTrace();
              } 
              bPlay.c = color(0, 125, 255);
            } else {
        
              bPlay.c = color(0, 125, 220);
              try {
                snd.prepare();
                snd.start();
                //fd = context.getAssets().openFd("Ni-"+(int)random(1, 22)+".mp3");
                //snd.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
              }
              catch (IllegalArgumentException e) {
                e.printStackTrace();
              }
              catch (IllegalStateException e) {
                e.printStackTrace();
              } 
              catch (IOException e) {
                e.printStackTrace();
              }
              //fd = context.getAssets().openFd("Ni-"+(int)random(1, 22)+".mp3");
            }
          }
        }
        
        void mouseReleased()
        {
          bPlay.c = color(0, 125, 255);
        }
        
        
        
        ////////////
        
        class Button
        {
          int x, y, w, h, r;
          color c;
        
          Button(int x, int y, int w, int h, color c) //rectangular buttons
          {
            this.x = x;
            this.y = y;
            this.w = w;
            this.h = h;
            this.c = c;
          }
          Button(int x, int y, int r, color c) //circular buttons
          {
            this.x = x;
            this.y = y;
            this.r = r;
            this.c = c;
          }
        
          void draw()
          {
            ellipseMode(CENTER);
            noStroke();
            fill(c);
            rect(x, y, w, h);
            ellipse(x, y, r, r);
          }
        
          boolean isHovering()
          {
            boolean result = false;
            float disX = x - mouseX;
            float disY = y - mouseY;
            if (sqrt(sq(disX) + sq(disY)) < r/2) result = true;
            return result;
          }
        }
        
        
        //===========================================================================
        // ANDROID ACTIVITY LIFECYCLE'S FUNCTIONS:
        
        
        //  @@@@@@@@@@@@
        @Override 
          public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
        }
        
        //  @@@@@@@@@@@@
        @Override 
          public void onStart() {
          super.onStart();
        }
        
        //  @@@@@@@@@@@@
        @Override 
          public void onResume() {
          super.onResume();
        
          //act = this.getActivity();
          //mC= act.getApplicationContext();
        
          //try {
          //  fd = context.getAssets().openFd("Crickets.mp3");
          //  snd.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
          //}
          //catch (IllegalArgumentException e) {
          //  e.printStackTrace();
          //}
          //catch (IllegalStateException e) {
          //  e.printStackTrace();
          //} 
          //catch (IOException e) {
          //  e.printStackTrace();
          //}
        
        
          //if (snd.isPlaying()==false) {
          //  try {
          //    snd.prepare();
          //    snd.start();
          //    //fd = context.getAssets().openFd("Ni-"+(int)random(1, 22)+".mp3");
          //    //snd.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
          //  }
          //  catch (IllegalArgumentException e) {
          //    e.printStackTrace();
          //  }
          //  catch (IllegalStateException e) {
          //    e.printStackTrace();
          //  } 
          //  catch (IOException e) {
          //    e.printStackTrace();
          //  }
          //}
          
          
        }
        
        
        //  @@@@@@@@@@@@
        @Override 
          void onPause() {
          super.onPause();
          if (snd.isPlaying()==true) {
            try {
              snd.pause();
            } 
            catch (IllegalStateException e) {
              e.printStackTrace();
            }
          }
        }
        
        //  @@@@@@@@@@@@
        @Override 
        void onStop() {
          super.onStop();
          endPlaying();
        }
        
        //  @@@@@@@@@@@@
        @Override 
        void onDestroy() {
          super.onDestroy();
          endPlaying();
        }
        
        //============================================================
        void endPlaying() {
          if (snd!=null) {
        
            if (snd.isPlaying()==true) {
              try {
                snd.stop();
              } 
              catch (IllegalStateException e) {
                e.printStackTrace();
              }
            }
        
            snd.release();
            snd= null;
          }
        }
    
  • @kfrajer It does indeed do everything like you say It crashes without warning when you use HOME/MENU or if you wake your phone up after standby but when using the back button it works perfectly

  • Thanks @schotsl for providing this info.

    I was checking the template for Android, and fragments created in Processing seem to have the proper handling of the back button as the template calls onBacPressed(). However, I am not sure what is the proper and right way to handle MENU and the START button. It seems those actions need to be managed. For the home button is done via android.R.id.home and the MENU button is done through the ActionBar or ToolBar in newer Android API versions. I would like to ask @akenaton if he could provide some comments on this topi.

    @schotsl, one question for you. When the application comes back to the foreground, if the music was playing before, should it play back again? Aka. should it save the app state?

    Kf

  • Ok, so I was checking the error thrown by the application. After few changes I was getting two errors and both were of the type IllegalStateException. I check the documentation https://developer.android.com/reference/android/media/MediaPlayer.html and these error were happening, in some occasions when setting the data source (setDataSource) or when preparing (right before start)

    So I added these changes:

    A boolean field to trigger instantiation and init of the MediaPlayer. This field forces to defined the MediaPlayer and resources. This field is set onResume() and executed on draw(). This method should run only once.

    Previous field is toggle back to false after resources are set (via startMPNow() ) is executed

    Notice that in onPause(), I am resetting the MP so when I come back from either event (MENU,HOME,BACK), the MP is in the right state for setDataSource() and prepare() to operate.

    Notice there seems to be an error when the song finishes playing. I will need to look this later. For now, let's focus in returning from background.

    FINAL note: It seems accessing the HOME key via keyPressed():
    if (key==CODED && keyCode==android.view.KeyEvent.KEYCODE_HOME) {...} doesn't work at all.

    Kf

    //REFEREENCE: forum.processing.org/two/discussion/comment/100364/#Comment_100364
    //REFEREENCE: developer.android.com/reference/android/media/MediaPlayer.html#start
    //REFEREENCE: forum.processing.org/two/discussion/comment/80718/#Comment_80718
    
    
    import android.media.MediaPlayer;
    import  android.content.res.Resources;
    import android.content.res.AssetFileDescriptor;
    import android.content.res.AssetManager;
    import android.content.Context;
    import android.app.Activity;
    
    
    
    //===========================================================================
    // IMPORTS:
    
    import android.app.Activity;
    import android.content.Context;
    import android.widget.FrameLayout;
    //import android.app.Fragment;
    
    import android.os.Environment;
    import android.graphics.Color;
    import android.widget.Toast;
    import android.os.Looper;
    import android.view.WindowManager;
    import android.os.Bundle;
    import android.view.ViewParent;
    import android.view.ViewGroup;
    import android.view.View;
    import android.widget.RelativeLayout;
    import android.view.LayoutInflater;
    import android.R.string;
    
    
    //===========================================================================
    // FINAL FIELDS:
    
    
    //===========================================================================
    // GLOBAL VARIABLES:
    
    Activity act;
    Context mC;
    
    MediaPlayer snd;
    //AssetManager assets = this.getAssets();
    AssetFileDescriptor fd;
    Context context;
    Button bPlay;
    
    boolean startMP=true;
    
    void setup()
    {
      colorMode(HSB);
      size(800, 800);
      act = this.getActivity();
      context = act.getApplicationContext();
    
      //startMPNow();   <-------- FAILS, when returning from HOME/MENU button events, it seems setup is not being called at all... maybe bc the frameCount is not 1? (Guessing)
    
      bPlay = new Button(width/2, height/2, 500, color(0, 125, 255));
    }
    
    void draw()
    {
      //Next field is activated onResume() and toggle back in startMPNow() function.
      if (startMP) {   
        startMPNow();
      }
    
      background(210);
      bPlay.draw();
      textSize(30);
      textAlign(CENTER);
      fill(0, 21, 75);
      text(startMP+"\nPress for replacement\n"+snd.toString(), width/2, height/2);
    }
    
    //void keyPressed() {
    
    //  if (key==CODED && keyCode==android.view.KeyEvent.KEYCODE_HOME) {
    //    snd.reset();
    //    //endPlaying();
    //  }
    //}
    
    
    
    void mousePressed()
    {
      if (bPlay.isHovering  ()) {
    
        if (snd.isPlaying()==true) {
          try {
            snd.stop();
          } 
          catch (IllegalStateException e) {
            e.printStackTrace();
          } 
          bPlay.c = color(0, 125, 255);
        } else {
    
          bPlay.c = color(0, 125, 220);
          try {
            snd.prepare();
            snd.start();
            //fd = context.getAssets().openFd("Ni-"+(int)random(1, 22)+".mp3");
            //snd.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
          }
          catch (IllegalArgumentException e) {
            e.printStackTrace();
          }
          catch (IllegalStateException e) {
            e.printStackTrace();
          } 
          catch (IOException e) {
            e.printStackTrace();
          }
          //fd = context.getAssets().openFd("Ni-"+(int)random(1, 22)+".mp3");
        }
      }
    }
    
    void mouseReleased()
    {
      bPlay.c = color(0, 125, 255);
    }
    
    
    //  ooooooooooooooooooOOOOOOO   @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    
    void startMPNow() {
    
      if (snd==null)
        snd= new MediaPlayer();
    
      try {
    
        fd = context.getAssets().openFd("Crickets.mp3");
        snd.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
      }
      catch (IllegalArgumentException e) {
        e.printStackTrace();
      }
      catch (IllegalStateException e) {
        e.printStackTrace();
      } 
      catch (IOException e) {
        e.printStackTrace();
      }
    
      startMP=false;
    }
    
    
    
    ////////////
    
    class Button
    {
      int x, y, w, h, r;
      color c;
    
      Button(int x, int y, int w, int h, color c) //rectangular buttons
      {
        this.x = x;
        this.y = y;
        this.w = w;
        this.h = h;
        this.c = c;
      }
      Button(int x, int y, int r, color c) //circular buttons
      {
        this.x = x;
        this.y = y;
        this.r = r;
        this.c = c;
      }
    
      void draw()
      {
        ellipseMode(CENTER);
        noStroke();
        fill(c);
        rect(x, y, w, h);
        ellipse(x, y, r, r);
      }
    
      boolean isHovering()
      {
        boolean result = false;
        float disX = x - mouseX;
        float disY = y - mouseY;
        if (sqrt(sq(disX) + sq(disY)) < r/2) result = true;
        return result;
      }
    }
    
    
    //===========================================================================
    // ANDROID ACTIVITY LIFECYCLE'S FUNCTIONS:
    
    
    //  @@@@@@@@@@@@
    @ Override 
      public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
    }
    
    //  @@@@@@@@@@@@
    @ Override 
      public void onStart() {
      super.onStart();
    }
    
    //  @@@@@@@@@@@@
    @ Override 
      public void onResume() {
      super.onResume();
      startMP=true;
      //startMPNow();   <-------- FAILS, maybe mC is not available at this step
    
    }
    
    
    //  @@@@@@@@@@@@
    @ Override 
      void onPause() {
      super.onPause();
      //if (snd.isPlaying()==true) {
      //  try {
      //    snd.pause();
      //  } 
      //  catch (IllegalStateException e) {
      //    e.printStackTrace();
      //  }
      //}
      snd.reset();
    }
    
    //  @@@@@@@@@@@@
    @ Override 
      void onStop() {
      super.onStop();
      //endPlaying();
    }
    
    //  @@@@@@@@@@@@
    @ Override 
      void onDestroy() {
      super.onDestroy();
      //endPlaying();
      snd.release();
      snd= null;
    }
    
    //============================================================
    void endPlaying() {
      if (snd!=null) {
    
        if (snd.isPlaying()==true) {
          try {
            snd.stop();
          } 
          catch (IllegalStateException e) {
            e.printStackTrace();
          }
        }
    
        //snd.release();
        //snd= null;
      }
    }
    
  • edited June 15

    @kfrajer It works perfectly with the processing APDE when you press the HOME/BACK/MENU or go into standby and return you can always play the music, thank you so much! I didn't think it would be this hard to add music.

    To answer your question about whether or not the music should continue playing, yes its for my app and the idea is that when you open the app music starts looping so it never ends and when you leave the app it pauses and if you return it starts again (It doesn't have to start at time that it left it can just play from the start again)

  • @kfrajer I got it working now, altough I have to enter the length of the mp3 manual to loop it. I thought I could find the length of the video with int(fd.getLength()) and just restart after that time has passed but it returns a value which isn't the actual length in milliseconds nor seconds of the mp3. Which makes me wonder what does it actually return? I couldn't find documentation

  • edited August 3

    EDIT: I think I fixed it by removing startMP=true; remove the resume void altough I'm not 100% sure since Its hard to reproduce the problem

    @kfrajer I have used your code (modifiyd) quite a few times in my app now and most of the time it works fine, but sometimes it doesn't detect for instance, when I set my phone in standby the music stops, but when I open it again it starts playing even though I haven't unlocked my phone after I unlock it it plays the music twice.

    Or sometimes when I switch between apps the music doesn't stop playing, so when I reopen the app the music starts playing twice again. I can't reproduce the problem often I feel like it happens 1 out of 30 times so maybe you noticed something I did wrong in my code. This is the code I'm using

    import android.media.MediaPlayer;
    import android.content.res.AssetFileDescriptor;
    import android.content.Context;
    import android.app.Activity;
    import android.os.Bundle;
    
    Activity act;
    Context mC;
    Context context;
    MediaPlayer snd;
    boolean startMP=true;
    AssetFileDescriptor fd;
    
    void setup()
    {
      size(800, 800);
      act = this.getActivity();
      context = act.getApplicationContext();
    }
    
    void draw()
    {
      if (startMP) {   
        startMPNow();
      }
          if(snd.isPlaying()==false) {
          try {
    
            startMPNow();
            snd.prepare();
            snd.start();
          }
          catch (IllegalArgumentException e) {
            e.printStackTrace();
          }
          catch (IllegalStateException e) {
            e.printStackTrace();
          } 
          catch (IOException e) {
            e.printStackTrace();
          }
        }
      } 
    
    void startMPNow() {
        snd= new MediaPlayer(); 
      try {
        fd = context.getAssets().openFd("music.mp3");
        snd.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
      }
      catch (IllegalArgumentException e) {
        e.printStackTrace();
      }
      catch (IllegalStateException e) {
        e.printStackTrace();
      } 
      catch (IOException e) {
        e.printStackTrace();
      }
      startMP=false;
    }
    
    @ Override 
      public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
    }
    
    @ Override 
      public void onStart() {
      super.onStart();
    }
    
    @ Override 
      public void onResume() {
      super.onResume();
      startMP=true;
    }
    
    
    @ Override 
      void onPause() {
      super.onPause();
      snd.reset();
    }
    
    @ Override 
      void onStop() {
      super.onStop();
    }
    
    @ Override 
      void onDestroy() {
      super.onDestroy();
      snd.release();
      snd= null;
    }
    
    void endPlaying() {
      if (snd!=null) {
        if (snd.isPlaying()==true) {
          try {
            snd.stop();
          } 
          catch (IllegalStateException e) {
            e.printStackTrace();
          }
        }
      }
    }
    
Sign In or Register to comment.