keepRunning PhoneGap/Cordova - android

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 it affect the execution of the Android app ? Does it create an Service in background ?
If anyone can find the source where we can see how does it work, that will be great
Thanks.
Edit : I try to analyze the generated code, analyze the RAM, services and processus in the setting of Android. And my conclusion is..... that do nothing.
If you try to make a app which track the user with GPS, dont use Cordova. To track the user correctly, you need to make a Service with the START_STICKY option. So, it's in native code. you lost the interest of the CrossPlatform because you have to recode the service for all platforms and in my opinion, the communication between Native Service and Cordova App is not easy.
In conlusion, if you use Cordova, you have to know you can't use the power of all native, you have to make choise :
- easy dev (subjective) and crossplaform (really crossplatform ?)
and
- Native dev with its power and no compatibility problems but you have to make one app for one platform

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.

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!

Related

Event handler for close/force stop an ionic app

I am developing an ionic app. I am wondering if there is any event handler for this condition when the app is being stop/close in follow ways:
1) Settings -> Application -> Application Name -> Force stop
2) Swipe to close app.
I would expect something like this. But the best i could found is to cater for app exiting via $ionicPlatform.registerBackButtonAction which does not include the above two scenario.
Also, I am not sure whether this can be done in native platform as well. Please advise on this.
angular.module('app').run(function($ionicPlatform) {
$ionicPlatform.onAppStopOrForceClose(function() {
// Any function here
});
});
ionic.Platform.exitApp(); // stops the app
window.close();
see: http://ionicframework.com/docs/api/utility/ionic.Platform/
if you try in ios: you can't exit an IOS App, Apple do not allow apps to exit programmatically

PushNotifications and MVVMCross

I have a service which handles my push notification. When the app is running, everything is fine, but once the app is not running I am getting a null reference exception. I have traced it back to the following line :
newIntent = Mvx.Resolve<IMvxAndroidViewModelRequestTranslator> ().GetIntentFor (request);
This line is used to get the intent for the status bar notification so when the user clicked on it it will take him to the appropriate page inside the app. I am pretty sure that This is null because the application is not running and the MvvmCross framework did not have a chance to initialize and register the IMvxAndroidViewModelRequestTranslator.
My question is what should I use as an alternative?
UPDATE
So I dis some reading and I believe that a regular intent wont work and break my app. I was thinking about creating a dummy activity In my app which will get the regular intent I will send and move on to use the IMvxAndroidViewModelRequestTranslator (which should be not null since the app was started) and create an MvvmCross navigation request.
Any thoughts?
UPDATE 2
Tried the approach above with no luck... still failing on the same line...
So basically the question is how can I launch the app from the status bar while making the MvvmCross eco system start as well...
Thanks
Amit
So what I ended up doing is once the notification arrived and the Mvx.Resolve threw an exception I (meaning the app is not running), I saved the notification data to the app preferences and launched the app to its main activity and there I simpley checked for the notification data and if it existed I navigated to the appropriate activity.
When the Android UI starts, then MvvmCross runs Setup to initialise things like IoC, your application, etc
If you need to initialise your MvvmCross application within a non-UI setting, then try the answer from MvvmCross DataService in an Android Broadcast listener which shows how to access the same setup that the UI uses.

android Detect when an application is installing, pause installation and prompt an alert box

is it possible to run a broadcast receiver to detect, pause installing and alert when an application is installing.
onRecive
public class Receiver extends BroadcastReciver{
public void onReceive(Context context, Intent intent ){
if(intent.getAction().equals("android.intent.action.PACKAGE_INSTALL")){
//i want to pause the installing activity and prompt an alert box
}
}
}
Purpose would be, when an application is going to install, it ask are you really want to install this application.
After doing a lot of R & D I'm really stuck with a solution for this, if u please can help me out with this, thank you a lot.
This is possible according to this research paper. Look page 2 Figure 1.
You cannot pause it. There is no API for this. This is a system level function not meant to be handled by 3rd party applications.
This is a security measure. Image if every app could control the installation of all other apps! It would be a big security misstep! Hence it's not available.
You can, however detect the installation of a package. See this thread:
Receiving package install and uninstall events

In HTML5, how can I keep an Android device’s screen on?

We are developing an App in HTML5 using jQuery.
Is there a way/method, in JavaScript or another technology, to keep the screen "on"?
I think there is another way doing it without any java code. You can add a video of 1 second with infinite repeat and hidden and it will do the trick. I have read it somewhere but i don't remember where.
Maybe you could use one of the blank videos below:
https://github.com/esc0rtd3w/blank-intro-videos
https://github.com/kud/blank-video
IT WORKS!
Google's WebVR polyfill has a way to do this on Chrome. It basically creates a tiny video (with a data URL, so no extra downloads needed) and loops it.
It seems like a hack, so I wouldn't be surprised if it's not reliable in the future.
They have code that achieves the same thing on iOS too, by triggering a location update.
Here's the relevant code for Android:
var Util={};
Util.base64 = function(mimeType, base64) {
return 'data:' + mimeType + ';base64,' + base64;
};
var video = document.createElement('video');
video.setAttribute('loop', '');
function addSourceToVideo(element, type, dataURI) {
var source = document.createElement('source');
source.src = dataURI;
source.type = 'video/' + type;
element.appendChild(source);
}
addSourceToVideo(video,'webm', Util.base64('video/webm', 'GkXfo0AgQoaBAUL3gQFC8oEEQvOBCEKCQAR3ZWJtQoeBAkKFgQIYU4BnQI0VSalmQCgq17FAAw9CQE2AQAZ3aGFtbXlXQUAGd2hhbW15RIlACECPQAAAAAAAFlSua0AxrkAu14EBY8WBAZyBACK1nEADdW5khkAFVl9WUDglhohAA1ZQOIOBAeBABrCBCLqBCB9DtnVAIueBAKNAHIEAAIAwAQCdASoIAAgAAUAmJaQAA3AA/vz0AAA='));
addSourceToVideo(video, 'mp4', Util.base64('video/mp4', 'AAAAHGZ0eXBpc29tAAACAGlzb21pc28ybXA0MQAAAAhmcmVlAAAAG21kYXQAAAGzABAHAAABthADAowdbb9/AAAC6W1vb3YAAABsbXZoZAAAAAB8JbCAfCWwgAAAA+gAAAAAAAEAAAEAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAIVdHJhawAAAFx0a2hkAAAAD3wlsIB8JbCAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAQAAAAAAIAAAACAAAAAABsW1kaWEAAAAgbWRoZAAAAAB8JbCAfCWwgAAAA+gAAAAAVcQAAAAAAC1oZGxyAAAAAAAAAAB2aWRlAAAAAAAAAAAAAAAAVmlkZW9IYW5kbGVyAAAAAVxtaW5mAAAAFHZtaGQAAAABAAAAAAAAAAAAAAAkZGluZgAAABxkcmVmAAAAAAAAAAEAAAAMdXJsIAAAAAEAAAEcc3RibAAAALhzdHNkAAAAAAAAAAEAAACobXA0dgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAIAAgASAAAAEgAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABj//wAAAFJlc2RzAAAAAANEAAEABDwgEQAAAAADDUAAAAAABS0AAAGwAQAAAbWJEwAAAQAAAAEgAMSNiB9FAEQBFGMAAAGyTGF2YzUyLjg3LjQGAQIAAAAYc3R0cwAAAAAAAAABAAAAAQAAAAAAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAEAAAABAAAAFHN0c3oAAAAAAAAAEwAAAAEAAAAUc3RjbwAAAAAAAAABAAAALAAAAGB1ZHRhAAAAWG1ldGEAAAAAAAAAIWhkbHIAAAAAAAAAAG1kaXJhcHBsAAAAAAAAAAAAAAAAK2lsc3QAAAAjqXRvbwAAABtkYXRhAAAAAQAAAABMYXZmNTIuNzguMw=='));
video.play();
The future answer - because it's experimental now - is to use the new API called: Screen Wake Lock API
I think you can mix it with previous workaround answers
// Create a reference for the Wake Lock.
let wakeLock = null;
// create an async function to request a wake lock
try {
wakeLock = await navigator.wakeLock.request('screen');
statusElem.textContent = 'Wake Lock is active!';
} catch (err) {
// try other solutions here ...
}
You can follow the support of this feature here
There is no way to ONLY write javascript or other web code to keep the screen on, without writing at least a little java code.
To explain why I am so certain, if you are developing a web app through html5 you MUST use a WebView as the main "screen" of your application to host your html,javascript code. So your "web code" does not directly run in the application but uses a View as its holder. As you can guess you can't just lock the screen from some code that is not even running in the native part.
I can provide a very easy and simple way to keep the screen on if you are not an expert in android programming. In the first activity, that uses the WebView I guess, add in onCreate after super:
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
Simplest method is to go to the Settings, Developer Options, and to select "Stay awake while charging". No need to code anything!
This supposes that OP wants to keep the screen on while connected to an external power source, which is reasonable, otherwise no clever coding will prevent the screen from going off soon when the internal battery drains empty.
The external power source can be as simple as a portable usb battery. When that eventually gets empty, the device will go to sleep as usual, but will remain functional on its internal battery.
I found this solution here:
posting about keeping the screen on
Keeping the device on does not depend on the OS but on the browser. Chrome is in the process of implementing Wake Lock API, but it is still experimental.
Until fully available, there is a way to mock the api by playing a base64 video in the background. This locks the sleep mode with all browsers.
You can find a webcomponent implementation here https://github.com/madeInLagny/mil-no-sleep

How to run an android app in background?

This code will run an app automatically after booting the system, but the app will close after pressing the back button.
If the app is run normally by clicking it's icon. It will continuously run even after pressing the back button or running other apps.
public class AutoBoot extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, MyActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
}
My question is, how to make this auto run code to continuously run even after pressing the back button or running other apps?
You can probably start a Service here if you want your Application to run in Background. This is what Service in Android are used for - running in background and doing longtime operations.
UDPATE
You can use START_STICKY to make your Service running continuously.
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
handleCommand(intent);
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}
As apps run in the background anyway, I'm assuming what your really asking is how do you make apps do stuff in the background. The solution below will make your app do stuff in the background after opening the app and after the system has rebooted.
Below, I've added a link to a fully working example (in the form of an Android Studio Project).
This subject seems to be out of the scope of the Android docs, and there doesn't seem to be any one comprehensive doc on this. The information is spread across a few docs.
The following docs tell you indirectly how to do this:
https://developer.android.com/reference/android/app/Service.html
https://developer.android.com/reference/android/content/BroadcastReceiver.html
https://developer.android.com/guide/components/bound-services.html
In the interests of getting your usage requirements correct, the important part of this above doc to read carefully is: #Binder, #Messenger and the components link below:
https://developer.android.com/guide/components/aidl.html
Here is the link to a fully working example (in Android Studio format):
https://developersfound.com/BackgroundServiceDemo.zip
This project will start an Activity which binds to a service; implementing the AIDL.
This project is also useful to re-factor for the purpose of IPC across different apps.
This project is also developed to start automatically when Android restarts (provided the app has been run at least one after installation and app is not installed on SD card).
When this app/project runs after reboot, it dynamically uses a transparent view to make it look like no app has started but the service of the associated app starts cleanly.
This code is written in such a way that it's very easy to tweak to simulate a scheduled service.
This project is developed in accordance to the above docs, and is subsequently a clean solution.
There is, however, a part of this project which is not clean: I have not found a way to start a service on reboot without using an Activity. If anyone reading this post has a clean way to do this, please post a comment.
Starting an Activity is not the right approach for this behavior. Instead have your BroadcastReceiver use an intent to start a Service which can continue to run as long as possible. (See http://developer.android.com/reference/android/app/Service.html#ProcessLifecycle)
See also Persistent service

Categories

Resources