I have an adobe air application - AS3 for iOs and Android.
Whenever the user clicks the home button, and thus the application is now in the background, the application automatically stops, which is the expected behavior. Now, if the user is in the application, and he double clicks his home button, showing all the multiple windows, the application continues running, which is not what i want. How can i access that state ( Not Background, not foreground )? If i can access it, i would then put my pausing code into that state, but how can i access that particular state?
When the user clicks the home button the app is moved to the background and suspended. The app isn't closed. The OS can close the app to free memory. If your app is a memory hog you'll see this happening.
You use events dispatched by the NativeApplication object. Below is example code to listen and handle these events.
import flash.events.Event;
import flash.desktop.NativeApplication;
import flash.desktop.SystemIdleMode;
// create listeners to NativeApplication
private var naApplication: NativeApplication;
naApplication = NativeApplication.nativeApplication;
naApplication.addEventListener(Event.ACTIVATE, eActivate);
naApplication.addEventListener(Event.DEACTIVATE, eDeactivate);
naApplication.addEventListener(Event.EXITING, eExiting);
private function eActivate(e: Event): void {
// app has opened or resumed
application.systemIdleMode = SystemIdleMode.KEEP_AWAKE;
}
private function eDeactivate(e: Event): void {
// app is going to be moved to background
application.systemIdleMode = SystemIdleMode.NORMAL;
}
private function eExiting(e: Event): void {
// app is going to be closed by user or by the OS (usually to free up memory)
// do whatever exit code here then remove all listeners (to be clean don't rely on OS to close them)
application.removeEventListener(Event.ACTIVATE, eActivate);
application.removeEventListener(Event.DEACTIVATE, eDeactivate);
application.removeEventListener(Event.EXITING, eExiting);
application.systemIdleMode = SystemIdleMode.NORMAL;
removeEventListener(Event.ENTER_FRAME, eMainTimer);
}
The systemIdleMode and ENTER_FRAME are just examples of typical code. Let me know of any questions.
Related
I have implemented AppOpenAds from Admob, they work as intended...To a point.
Unfortunately, when the viewer is watching a 'rewarded' video (ie to get coins in-game) after it finishes, it then shows an AppOpenAd, as it obviously thinks the user has left the app (when they have just watched a video instead). So they are getting a double-whammy ad!
Is there any way I can stop this?
It's using this;
private void OnAppStateChanged(AppState state)
{
// Display the app open ad when the app is foregrounded.
UnityEngine.Debug.Log("App State is " + state);
if (state == AppState.Foreground)
{
AppOpenAdManager.Instance.ShowAdIfAvailable();
}
}
Edit - just to clarify - Rewarded ads work, they just then show an AppOpenAd when the rewarded ad finishes due to it thinking I was outside of the app.
My app seems to randomly get stuck in a loading state after a user goes to lock screen or another app and then returns on iOS.
Scenario:
User is using the app to view images then clicks lock screen button.
[
The user unlocks their phone and the app is now stuck infinitely loading.
The only way to end the loading state is by shutting the app down and restarting it. It then works as normal.
This doesn't always happen. But the issue only crops up after the app has idled.
Does anyone have any idea what I could do to 'wake up' the app? I'm finding it hard to debug as it doesn't happen on the emulator.
Use this code in your root container (main screen)
import { AppState } from "react-native";
useEffect(() => {
const subscription = AppState.addEventListener("change", appState => {
if (appState === "active") {
console.log("App has come to the foreground!");
// call the function to remove loader here
}
console.log("AppState", appState);
});
return () => {
subscription.remove();
};
}, []);
Ref : AppState React Native
I have a requirement where I want to perform an action inside the electron app only when it is in foreground.
It is an electron-react application. On mounting of a component, I want to schedule a periodic task which only runs when the app is in focus or is being used by the user. And pause the task when the app goes in background.
How can we detect the Electron app being in foreground?
You can use the isFocused method from BrowserWindow. To get your own BrowserWindow, you can do this :
remote.BrowserWindow.getAllWindows();
This will return all your app's windows. So to get the first / primary window, you could deconstruct the array like this :
const [yourBrowserWindow] = remote.BrowserWindow.getAllWindows();
console.log(yourBrowserWindow.isFocused());
You can use the focus / blur events on your BrowserWindow to be notified when the app is focused / unfocused.
mainWindow = new BrowserWindow({})
mainWindow.on('focus', () => {
console.log('window got focus')
})
mainWindow.on('blur', () => {
console.log('window blur')
})
You may want to update the component's state within these event handlers or use any other method to keep track of the current focus status.
This assumes that you have a single application window. If you have multiple, you'll need to extend the check to cover all of your windows.
(edited to provide updated info)
I have a nativescript app that performs various tasks that I would like to continue going if the phone goes into background mode or is locked.
Focused on iOS, with Nativescript Angular. I am also new to using obj C code in Nativescript.
As an easy example, let's say I want to print to the console every 5 seconds after a user hits a button, so I have the following code in my component ts file:
coolComponent.ts:
#Component({...})
Export class coolComponent {
...
whenButtonClicked(){
setInterval(function(){
console.log('button has been clicked. show every 5 seconds!');
}, 5000);
}
Without further code, when the user hits the button, it will print to console every 5 seconds, but then stop when the app is in the background or phone is locked. How do I get the function to continue executing even when app is in the background or locked?
In seeing different sources, like here (NS docs on background execution) and here (docs on app delegate) , it looks like the first step is to create a custom-app-delegate, get that to work, and then identify the background task in info.plist.
I have gotten things generally to be functional, like this:
app/custom-app-delegate.ts:
import { ios, run as applicationRun } from "tns-core-modules/application";
export class CustomAppDelegate extends UIResponder implements
UIApplicationDelegate {
public static ObjCProtocols = [UIApplicationDelegate];
public applicationDidEnterBackground(application: UIApplication) {
console.log('in background mode!')
}
}
main.ts:
import { platformNativeScriptDynamic } from "nativescript-angular/platform";
import { AppModule } from "./app.module";
import * as application from "tns-core-modules/application";
import { CustomAppDelegate } from "./custom-app-delegate";
application.ios.delegate = CustomAppDelegate;
platformNativeScriptDynamic().bootstrapModule(AppModule);
app/app.module.ts:
import { CustomAppDelegate } from "./custom-app-delegate";
app/App_Resources/iOS/info.plist:
...
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
</array>
edit: create reference.d.ts:
/// <reference path="./node_modules/tns-platform-declarations/ios.d.ts" />
/// <reference path="./node_modules/tns-platform-declarations/android.d.ts" />
Edit: FYI, to get the custom-app-delegate to work, I also had to download "tns-platform-declerations", with the command:
$ npm i tns-platform-declarations --save-dev
With this, the app properly reads "in background mode!" when the app goes to the background. So the custom-app-delegate is functional.
However, the examples online assume that the code in the custom-app-delegate is independent of the rest of the app, so they assume there are new tasks to do when the app goes into background mode.
That is not the case here. I have a task that is being performed from the coolComponent function, and when the app goes into background or is locked I want that to continue.
This probably requires that coolComponent.ts communicate with custom-app-delegate, but I don't know how to do this.
Just repeating the code in both files--having the setInterval function appear in both coolComponent.ts and custom-app-delegate--does not work, because this would not result in the custom-app-delegate continuing on the same timing that began in coolComponent.ts after the user hit the button.
So how can I have the code start in coolComponent.ts and continue after the app is in background mode?
Technically you can't force your app to be active when user no longer wants it to be (by locking the phone / minimising the app). If you like to run anything in background, you will have to use background fetch in iOS.
iOS allows you to run code in the background only for certain situations. For instance (but not limited to):
Background location updates.
Audio and video playback (PiP in iPad)
Remote Push Notifications handling
among others...
If your app does not fit any of the available categories, the best you can do is to request to iOS more time to run in the background (by default is 10 seconds). This will allow you to run for 3 more minutes. Just keep running the task in an infinite loop and gracefully terminate your app before the granted 180 seconds.
Regarding background fetch, this mechanism allows apps to update its contents in the background. iOS will execute apps that declare background fetch at least once a day, so you, in your delegate can perform an update from the server. This mechanism is not suitable for what you are looking for.
I have EventManager and Reg class singleton (Obj-C):
EventManager
class EventManager : NSObject {
override init() {
super.init()
Reg.shared().id = myId
Reg.shared().delegate = self
}
}
Reg (singleton)
#implementation Reg
//...
+(Reg*) shared{
static dispatch_once_t once;
static Reg *manager;
dispatch_once(&once, ^ { manager = [[Reg alloc] init]; });
return manager;
}
//...
#end
So here is my call in Controller:
class ViewController: UIViewController {
let manager = EventManager()
override func viewDidLoad() {
super.viewDidLoad()
let a = SomeHandler.instance
}
DispatchQueue.global(qos: .default).async {
SomeHandler.instance.registerBlocks({ obj in
let m = EventManager()
}, failureBlock: { (a, b, e) in
let m = EventManager()
}, status: { (a, b, c) in
}) { value in
let m = EventManager()
}
}
I get callback from SomeHandler.instance.registerBlocks sometimes after 10-15 sec when device entered to background and turned back to foreground
My question is: what happens with Reg instance?
If application is always active, each time when I call EventManager() I should get same instance of Reg because its singleton.
But when device enters to background OS deallocs all instances so when user opens app again Reg.shared() should return different instance, is it true?
What happens if old instance of Reg.shared() did some long job like sending HTTP requests?
To further elaborate on Paulw11's comment, please refer to the documentation about an app's life cycle.
A lot of people don't really specify what they mean with "background":
They just pressed the home button so the home screen or some other app is shown on the screen
The just put the device to sleep
They did either of this some time ago
They terminated the app with Xcode or restarted the device, seeing the app in the task manager (double pressing home button), so they assume it is in a background mode
Some other common unclear usages of "background" might also exist, but I think you'll get the picture.
As Paulw11 correctly said the only time your singleton will be deallocated is when the app enters the "not running" state, i.e. it is terminated. Note that this happens in case 4 I listed, but whether the app is listed in the task manager or not is not indicative of it running or not! I'm saying this since I have met people saying "my app just went to background, but when I put it to foreground again it appears all my on-start code is executed again!"
Case 3 can also ultimately result in your app being terminated (i.e. it goes from "suspended" to "not running"), but it needn't be so (depends on device usage and so forth).
The first two cases will result in the app at first entering background mode (your singleton is still there) and then suspended mode (the app is not doing anything anymore, but the memory is still intact, so your singleton won't be re-inited later).
In the end, a (true) singleton will only ever be deallocated when the app terminates, everything else would be grossly mis-using the term (also note that here lies the danger of singletons). The OS doesn't randomly go into your app's memory allocation and takes away its stuff. The only thing it does do is sending the memory warnings to let the app decide how to save memory on its own (if it's not suspended already). Only if even that does not "reign in" the app's resource usage memory is "freed": By killing it entirely.
#Paulw11: I didn't want to steal your answer, so why don't you make one from your comment. snaggs can then accept that. :)