the BACK key ?

edited April 7 in Android Mode

I know this has been discussed elsewhere and I have read and tried code ideas from several threads and also some from Stack Overflow but with no luck. So how can the the BACK key behaviour be controlled in the new version of Processing. In P2 and early versions of P3 (before android mode started putting us in a Fragment - why?) I was able to use the function boolean surfaceKeyDown(int code, KeyEvent event) but that has now for some reason become void surfaceKeyDown(int code, KeyEvent event) and doesn't work any longer.

So back to basics .... the following code makes use of keyPressed() as described in the Android Mode Wiki. The code runs when the BACK key is pressed, but the app quits.... setting keyCode = 0 doesn't prevent quitting. This is presumably dated info in the wiki??

So what to try next .... any ideas please?

Thanks, Mark

void setup() {
  fullScreen(P2D);
  rectMode(CENTER) ;
}

// draw() ... just to have somethng happening ...

void draw() {
  background(0) ;
  rect(mouseX, mouseY, width/8, width/8) ;
}


// keyPressed() ... copied from Processing's Android Mode WIKI ...

void keyPressed() {
  // doing other things here, and then:
  if (key == CODED && keyCode == android.view.KeyEvent.KEYCODE_BACK) {
    keyCode = 0;  // don't quit by default
    println("BACK key pressed") ; // to prove the code ran to here ...
  }
}

Answers

  • Try this -

    void keyPressed() {
      // doing other things here, and then:
      if (key == CODED && keyCode == android.view.KeyEvent.KEYCODE_BACK) {
        keyCode = 0;  // don't quit by default
        println("BACK key pressed") ; // to prove the code ran to here ...
        return;//to prevent exit?
      }
    }
    
  • Just to clarify, in previous Processing versions, you were able to override the behavior of the BACK key? Is that really necessary? I mean, the concept is to allow the user to switch between different apps (if any on the stack) or just back to the main screen.

    @akenaton

    Would you be able to onPause, force the application to run onResume so the application is constantly running? Do you know if that is allowed? Not that it should be done... but more of a theoretical question.

    Kf

  • @kfrajer Yes I was able to override it. I understand it has a particular function to swap between apps etc but I use in case it is accidentally pressed ... as can easily happen with soft back key as opposed to an actual hardware key. By intercepting I just then show an alert asking confirmation that quitting is what the user really wants ..

  • So did my method work?

  • @Lord_of_the_Galaxy Will be trying later as just out and about without my laptop. Thanks for your idea though ... fingers crossed!

  • The problem is, I don't know if Processing does the job of BACK or if it is done behind the scenes by Android (I believe that my method won't work). If it is done by Android, then we'll have to search for a universal (non - Processing specific) solution.

  • edited April 7 Answer ✓

    @kfrajer, @Lord_of_the_Galaxy===

    • backPressed is an event that android manages according to the cases:

    first case: you have only one activity in your app: in this case back pressed is like leaving the app; you cannot forbid that, you can only register some data(that you can use with "on resume()" before leaving (or make an alert dialog)

    second case: you have a lot of activities so when you hit the back button you go to the previous activity (in your app-stack); in this case you can do a lot of things overriding the back pressed - yet you cannot forbid the user to press it! supposing that you have a service running (audio eg) you can (and sometimes have) to stop it...In this case you can also send some data to the previous activity, if useful.example code==

        @  Override
        public void onUserLeaveHint() {
    
            super.onUserLeaveHint();
    
            if ( !lanceA){
               System.out.println("appname Home Key Pressed"); 
               Home = true;
               stoppeSoudon();
            doUnbindService();
    
            }else{
             doUnbindService();
                Log.i("appname","We are leaving, but will probably be back shortly!");  
        }
        }
    

    So= YES you can override backPressed NO you cannot make that the user stays in your app or in your activity...

    As for the HOME button you can only Know that it was pressed and, using onUserLeaveHint(), do something before quitting.

  • @Lord_of_the_Galaxy Thanks for your ideas earlier ... but as you guessed it didn't work. I suppose I am confused because in previous Processing versions I was able to do so with the boolean version of surtface KeyDown ... Oh well !

    @akenaton Thankyou for this code ... I am going to play with it now.

    Re exiting the app, I can see why it should be that hitting BACK leaves the app .. onPause() and onStop() get called regardless of anything I try to put in keyPressed() so maybe I will add some code there to do an auto save, so that a user can at least restart from where they left off.

    Thanks all ... Mark

  • @akenaton

    I just found the old code you posted in 2014 using boolean surfaceKeyDown(int code, KeyEvent event) ... that used to do the trick but is no longer possible

    https://forum.processing.org/two/discussion/8220/can-i-override-android-methods-like-onpause-onresume-in-processing#latest

  • I am now fiddling with the lifecycle callbacks just to see what happens, they do seem to be called as expected in the right order (phew!)

    void setup() {
      fullScreen(P2D);
      rectMode(CENTER) ;
    }
    
    // draw() ... just to have somethng happening ...
    
    void draw() {
      background(0) ;
      rect(mouseX, mouseY, width/8, width/8) ;
    }
    
    
    // keyPressed() ... copied from Processing's Android Mode WIKI ...
    void keyPressed() {
      //doing other things here, and then:
      if (key == CODED && keyCode == BACK) { //android.view.KeyEvent.KEYCODE_BACK) {
        keyCode = 0;  // don't quit by default
        println("BACK key pressed") ; // to prove the code ran to here .. :)
        return ;
      }
    }
    
    // the various lifecycle callbacks for testing ... (and learning!)
    
    void onPause() {
      println("onPause()") ;
      super.onPause() ;
    }
    
    void onStop() {
      println("onStop()") ;
      super.onStop() ;
    }
    
    void onDestroy() {
      println("onDestroy()") ;
      super.onDestroy() ;
    }
    
    void onResume() {
      println("onResume()") ;
      super.onResume() ;
    }
    

    Has anybody already been through this process who can offer any guidance as to how to deal with the fact that setup() seems to get run again when the app resumes, resetting everything to default conditions? Ideally I had hoped to just go back into draw() and carry on from there?

  • Could you set your values used in setup right in onResume()?

    You will need to adapt to your app concept running setup every time the app is restored. If one is running the app for the first time, then the default values of setup should be used. If the app has run before, then use bundle to recover the previous values.

    Another question is if setup and onStart/onResume run in the same order? Is it consistent between different platforms?

    I believe @akenaton was experimenting with this long time ago and they are interesting questions.

    Kf

  • @kfrajer Thanks for the ideas ... never used bundle so will read up to see how it works.

  • edited April 8

    @kfrajer && hudson_m400===

    @kfrajer is right: these are interesting questions (and not as i can see here from people who have not any idea about android and think that the P5 android mode is a way to "avoid" learning android, i mean the fundamentals!)

    i never tried to use "bundle" with P5; what i know by android standard is that it is useful (not only!) when you want that some special values are saved when the app is stopping. I say "special values" because android save by itself (without coding) values for views: if you have a textView with some text and the app goes in the background, when the user comes back the text is still here. Special values (thinks to a game score) can be integers, charSequence, floats, array and can be saved adding explicitely the onSaveInstanceState(Bundle savedInstanceState...put int, put charSequence, put float...+ an identifier) method though not all values can be saved in this way. Then, when the user comes back onCreate() calls this bundle (of course it can be null if it is the first time that your app is running!) and you can get the saved values with getInt, getFloat and so on.

    As for the other question, YES, the lifecycle is always the same and the way used by hudson_m400 is good to verify when are called onPause() or others. What matters is onPause(), onResume() && on stop(), depending of your app and needs: but it happens often that you have to release services or unregister receivers each time that the user leaves your app or your activity: if you dont think to that the system can decide that it needs memory or... and chooses to kill the app (destroy)!

    last precision: onResume() is NOT ONLY called when the user leaves the activity (or the app) then comes back: it is fired when the app (or the activity) comes in the foreground: you can verify that using the "println" from @hudson_m400. As for onDestroy() it is called (in a fragment) when the user hits the backButton (supposing that there is only 1 fragment).

  • edited April 8

    See! Nothing in Android is simple, it's extremely complicated. And that's why I prefer to stick to PC programs, and haven't yet tried Android. (P.S. Don't get discouraged by me though)

  • edited April 8

    @Lord_of_the_Galaxy===

    No && Yes!!!

    Android is as complicated as java (which is not so simple...)

    (it is not a simple "little subclass of Java", it as its own rules:: because we are on a PHONE, not on a laptop and all rules (security, permissions...) result from that).

    Example: the phone is ringing, what happens??? - You can override pause, stop and what you want, the fact is = phone is ringing && the user (normal user!) has to answer to the call...

    Then, suppose that you have an app, at the same time which use media player && makes music...It s easyto understand that the user, when he or she gets the call does not want to hear your GENIAL music: that is all!) - So, when i see (i am android developper by job) asking for "on backPressed" or on "homePressed()" "stay in "my app" i think: they never think and read what are the main and fundamentals rules from android.

    Thats is why, when i read "processing has made android incredibly easy" i am very surprised.

    Mainly, P5 is a graphics library for Android and it works well.

    As for all other stuffs P5 is a headache...

    example: if i use AS or Eclipse i CAN (i have done....) save a lot of things (activity or fragment, values.... in a bundle. If i use P5 it says me that this function (bundle, save) does not exist) --- that is our case, and i shall try to find some work around, yes, but there is a GREAT problem: do not tell to people that it is easy when you make the job MORE COMPLICATED

  • edited April 8

    @kfrajer, @Lord_of_the_Galaxy, @ akenaton, @kfrajer

    Much to think about! As for me, Processing IS a very easy way to get into producing something that runs on Android ... type some code using the Processing library, hit run and it's there on my phone in less than a minute ... !!! ... but as I have progressed (since past 3 years) I am now finding a need to go beyond Processing's scope and capabilities ... in fact that first happened quite early on for some audio work I needed to do that Minim didn't support, so I had to learn how to import and use the AudioTrack class, and then for dealing with file saving etc. BUT ... I would have had to do this with any IDE ... Processing gave me the best start with this and I'm still hooked and love using it!

    In short ... without Processing I don't think I would have ever produced anything, but because my early tinkering worked so easily, I have an app I'm proud of and am still developing/improving now.

    @ akenaton those of us who are not 'real' programmers have gained so much from having Processing and really appreciate help from users such as yourself! I don't always comment, but I do always read and try your suggestions to whoever you are writing to. I may one day migrate to Android Studio, but I already tried it once and it was such an effort to just install it, yet alone use it, I just stick with Processing! In the old days of Processing (version 1.5 when I began) the whole process of downloading, installing and running a very simple app took me less than 15 minutes! I even exported binaries for PC and Mac and my code ran first time on both platforms with no crashes .. I nearly fell over from the shock! That is why I say it is incredibly easy'!!! Now, as I progress, I know I need more knowledge and experience. The lifecycle callbacks I am now experimenting with, my next stage, are part of that', but if I was using AS or Eclipse ... that would be just the same learning experience?

  • @akenaton

    What is the meaning of Eclipse not supporting ADT? All Android migration should be done in AS then? The option of doing android in Eclipse is dead?

    Also now that you mention you have experience in both(you have mention this before), what are your thoughts of their performance of both AS and Eclipse as IDE for Android?

    I do believe android mode in Processing is very convenient and it offers a really good set of tools to implement advanced concepts. Ketai library is an example. I wish there was more support and to have access to more examples.

    @hudson_m4000 What solution will you implement at the end for your case?

    Kf

  • @kfrajer I will let you know once I have something working! I think though that simply saving a file (saveBytes) to SD Card in onStop(), that the user can then just reload to carry on from where they left off ... interrupted by a phone call or by accidentally touching the BACK key!

  • @akenaton @kfrajer @hudson_m4000 and everyone else
    I suppose all that really matters is what you learn first. Many people claim that it is easier to learn new programming languages after learning the first one. Yet, from my personal experiences and from those of others I know, the first you learn is always the one you will know best, even if you spend months learning a new one. It is somewhat like languages, one always speaks best in their mother tongue.

  • @kfrajer, @Lord_of_the_Galaxy, @ akenaton, @kfrajer

    OK, my solution...

    Trying to do a file save in onStop() didn't work ... I think that the app is stopped too quickly for anything useful to be done. But it did work when saving in keyPressed() ... and this can deal with all buttons, BACK, HOME etc

    I can can get rid of all my onPause(), onResume(), onStop() etc and just have the keyPressed() callback. Processing and the android system do whatever they do with these so I don't have to! Back to being nice and easy ... just as it should be!! I may revisit them one day, and I at least have some understanding now that they are being called and are a necessary part of the android app lifecycle, but for now I can just do the other things that are needed ... developing the functionality of my app.

    Many thanks for all your help and comments ... an interesting discussion.

    Basic code ....

        void setup() {
          //set things up
        }
    
        void draw() {
         // the app does its work here ....
        }
    
        void keyPressed() {
        // do an autoSave
            saveAppData() ; 
        }
    
     // my function to do the file saving ...
    
       void saveAppData() {
       //create a byte[] with all data to be saved and use saveBytes() 
       //to put it on the Primary SD Card
       }
    
  • edited April 9

    @kfrajer=== eclipse && as are very similar now that eclipse has integrated gradle for building; yet it is probable (though i dont like that!!!) that AS win - with google help!

    @ hudson_m4000 yes, of course you can save data when the key is pressed, but the question was to use Bundle... As for me, till now i can save successfully bundle using onStop() - now i have to restore it i dont know when...

  • @akenaton I will look at Bundle too as it does look useful, but I have a feeling that restoring from it would happen before setup() is re-run, which would reduce its usefulnees... need to investigate though to confirm that.

  • edited April 9

    @hudson_m4000===

    yes, you are right, restoring must happens before setup(); and i am able to do that with eclipse using onCreate() in a fragment; but when i want to apply my code to processing i see that onCreate is not called (seems to...); only onStart() has a callback.

    other problem is that super.onSavedInstanceState() is not recognized by P5, which is also very weird...

  • Fragments..... I haven't seen any fragment code in the forum. Is it easy or possible to use in Processing?

    @akenaton If eclipse implemented gradel, then the Android environment is operated through a new plugin is it still called ADT? My understanding is that you use both but AS performs better? I did check some info before saying that AS is really optimized for Android and eclipse gives you a big headache, for example when there are updates... In overall, I would like to know if you have to use both IDEs or if you could have sticked to one from the beginning.

    @hudson_m4000 Thanks for sharing your answer. Related to the info you were saving, were they few fields or were you saving data tables?

    Kf

  • edited April 9

    @kfrajer===

    as for now there is a release from eclipse "special android" called "neon" which works fine and is (for me!!!) better than AS...But as i told you i am afraid that Google changes that next years...With this version you can work only with your SDK. Try to download it.

    as for fragments, what do you mean??? - Each app in android processing is extending the Fragment class...And till you want to add some new fragment with a fragment transaction (that is possible and useful in some cases, i have done that with P5 - a workaround!) you dont need to know many things about fragments (except that they have a lifecycle somewhat different from activities)

    @m_Hudson4000=== always with Eclipse i have now another way to save my data in fragment and it is very simple. Yet again, when i put the code in P5 it fails because some callbacks are not recognized:

    /////

                    int score;
                            final static String STATE_SCORE;
                            ////
                            public void onCreate(Bundle savedInstanceState){
                                        super.onCreate(savedInstanceState);
    
                    ///at this line i get "super.onCreate(savedInstanceState) does not exist
                    /// that is exactly the same problem that i have seen with Keitai lib (cursors blue //tooth example, at the same "on create()"
    
                    //error code:: super.onSaveInstanceState(savedInstanceState);
                            ///  ^^^^^^^^^^^^^^^^^^^
                    //The method onSaveInstanceState(Bundle) is undefined for the type PApplet
    
    
                        if (savedInstanceState != null) {
    
                       score = savedInstanceState.getInt(STATE_SCORE, 0);
                            System.out.println(score);
                        }else{
                          System.out.println(savedInstanceState);
                        }
    
    
    
                    };
    
  • @kfrajer It's a lot of data for a music app. Lots of note data, with all sorts of controls for volume, panning, synth settings etc. I use a byte[] because when I started the Table didn't exist ... it is on my list of things to do to make use of it though.

    @akenaton Thanks once more for your code. I think I will leave this for now though...I have a solution now that works and it sounds as if using the callbacks in Processing is incomplete or buggy!

Sign In or Register to comment.