keepRunning PhoneGap/Cordova

后端 未结 2 1928
伪装坚强ぢ
伪装坚强ぢ 2020-12-06 18:59

Anyone can explain me how keepRunning works in the config.xml for Android.

I mean, I don\'t want to know how to write the instruction but how does it work, how does

相关标签:
2条回答
  • 2020-12-06 19:22

    I'm not a JS/Cordova developer, I'm an Android developer. Once I worked on a Cordova plugin, faced some issues and did some investigations on the subject.

    General purpose of keepRunning flag is to indicate if JS timers should be stopped when the app is paused (goes to background). Answering your question: no, it doesn't create any new Service. Existing design is quite plain in this regard.

    The keepRunning flag is defined in CordovaActivity.java as follows:

    // Keep app running when pause is received. (default = true)
    // If true, then the JavaScript and native code continue to run in the background
    // when another application (activity) is started.
    protected boolean keepRunning = true;
    

    Its main purpose is to disable JS timers when Cordova app is paused, in CordovaWebView.java:

    public void handlePause(boolean keepRunning)
    {
        LOG.d(TAG, "Handle the pause");
        // Send pause event to JavaScript
        this.loadUrl("javascript:try{cordova.fireDocumentEvent('pause');}catch(e){console.log('exception firing pause event from native');};");
    
        // Forward to plugins
        if (this.pluginManager != null) {
            this.pluginManager.onPause(keepRunning);
        }
    
        // If app doesn't want to run in background
        if (!keepRunning) {
            // Pause JavaScript timers (including setInterval)
            this.pauseTimers();
        }
        paused = true;
    
    }
    

    Note that plugins are also notified via PluginManager, so in theory they can handle app paused events, to stop (or not) their activity in background, depending on keepRunning flag.

    In my case I had an issue/bug when keepRunning was true, but JS timers were stopped anyway. It happened because there is additional functionality related to that flag, in CordovaActivity.java:

    /**
     * Launch an activity for which you would like a result when it finished. When this activity exits,
     * your onActivityResult() method will be called.
     *
     * @param command           The command object
     * @param intent            The intent to start
     * @param requestCode       The request code that is passed to callback to identify the activity
     */
    public void startActivityForResult(CordovaPlugin command, Intent intent, int requestCode) {
        this.activityResultCallback = command;
        this.activityResultKeepRunning = this.keepRunning;
    
        // If multitasking turned on, then disable it for activities that return results
        if (command != null) {
            this.keepRunning = false;
        }
    
        // Start activity
        super.startActivityForResult(intent, requestCode);
    }
    

    When Cordova app launches another Android activity, main Cordova activity (screen with WebView) goes to background and is therefore paused. In my case it was made via Google Maps plugin which started GM screen over Cordova app.

    The code above turns off keepRunning flag, and it means that JS timers are stopped anyway when the called activity appears (in CordovaActivity.onPause method) regardless keepRunning is true or false!

    It looks like a kind of trick implemented for some unclear (and not documented) purpose, I do not know its context. In my case it caused a bug, and I just removed keepRunning handling in startActivityForResult, recompiled Cordova and it worked OK.

    ADDED: About using a Service for GPS - you are quite right, I agree. As an Android developer with relevant (GPS) experience I can say that a right approach (and possible the only acceptable) is to use a service for that. As far as I know Cordova doesn't provide any functionality for it, so I think it should be made via a plugin. I mean you can write native Android code for GPS functionality (implemented as a Service) and access it from JS code. I believe it is a common solution in Cordova for such cases.

    0 讨论(0)
  • 2020-12-06 19:34

    Perfect answer, helped me a lot! I was searching for the solution to the problem for 2 days now.

    In my case I'm currently developing a cordova plugin for login purposes. For the login I use an external form which I load in a webview. For two days now I was struggling with the fact that the "Password forgotten" link and every other link on the page I loaded was working, but I wasn't able to submit my form. Only when I hit the back button and through this finished the intent holding the webview, it did submit and proceed.

    Turns out that the keepRunning handling was the only problem here. In the end I replaced: `

    cordova.startActivityForResult(this, intent, 0);
    

    by:

    cordova.setActivityResultCallback(this);
    cordova.getActivity().startActivityForResult(intent, 0);
    

    which basically fulfills the whole job Cordova's startActivityForResult would do The only thing that's left out is the whole keepRunninghandling which messed up my plugin in the first place.

    Thanks again, Mixaz!

    0 讨论(0)
提交回复
热议问题