{ "id": "171505", "key": "TIMOB-25962", "fields": { "issuetype": { "id": "4", "description": "An improvement or enhancement to an existing feature or task.", "name": "Improvement", "subtask": false }, "project": { "id": "10153", "key": "TIMOB", "name": "Titanium SDK/CLI", "projectCategory": { "id": "10100", "description": "Titanium and related SDKs used in application development", "name": "Client" } }, "fixVersions": [], "resolution": { "id": "3", "description": "The problem is a duplicate of an existing issue.", "name": "Duplicate" }, "resolutiondate": "2018-10-29T23:14:09.000+0000", "created": "2018-04-12T14:20:44.000+0000", "priority": { "name": "Critical", "id": "1" }, "labels": [ "android", "parity", "pause", "resume", "ti.app" ], "versions": [], "issuelinks": [ { "id": "56900", "type": { "id": "10002", "name": "Duplicate", "inward": "is duplicated by", "outward": "duplicates" }, "inwardIssue": { "id": "172380", "key": "TIMOB-26424", "fields": { "summary": "Android: Added Ti.App \"pause\" and \"resume\" lifecycle events", "status": { "description": "The issue is considered finished, the resolution is correct. Issues which are closed can be reopened.", "name": "Closed", "id": "6", "statusCategory": { "id": 3, "key": "done", "colorName": "green", "name": "Done" } }, "priority": { "name": "High", "id": "2" }, "issuetype": { "id": "4", "description": "An improvement or enhancement to an existing feature or task.", "name": "Improvement", "subtask": false } } } } ], "assignee": { "name": "jquick", "key": "jquick", "displayName": "Joshua Quick", "active": true, "timeZone": "America/Los_Angeles" }, "updated": "2018-10-29T23:14:09.000+0000", "status": { "description": "The issue is considered finished, the resolution is correct. Issues which are closed can be reopened.", "name": "Closed", "id": "6", "statusCategory": { "id": 3, "key": "done", "colorName": "green", "name": "Done" } }, "components": [ { "id": "10202", "name": "Android", "description": "Android Platform" } ], "description": "This is a Feature request to add Ti.App.resume and Ti.App.pause event to Android.\r\n\r\nGoogle recently added [Lifecycle Components|https://developer.android.com/topic/libraries/architecture/lifecycle.html] and more specifically [LifecycleOwner|https://developer.android.com/reference/android/arch/lifecycle/LifecycleOwner.html] that has been designed specifically for this.\r\n\r\nFrom the Lifecycle Owner Docs: \r\n\"A class that has an Android lifecycle. These events can be used by custom components to handle lifecycle changes without implementing any code inside the Activity or the Fragment.\"\r\n\r\nThere is also a very good Blog post with examples and exactly what is needed here:\r\nhttps://proandroiddev.com/detecting-when-an-android-app-backgrounds-in-2018-4b5a94977d5c\r\n\r\nIt would be great if we could add this to the core to finally have Ti.App.resume and Ti.App.pause events and not have to count on all kinds of hacks, tools, modules etc.\r\n\r\nI will be working on getting this setup in my test project with Hyperloop and report back with a working example.", "attachment": [], "flagged": false, "summary": "Android: Ti.App.resume and Ti.App.pause Addition - Google has added Lifecycle Components (LifecycleOwner) specifically for this", "creator": { "name": "dieskim", "key": "dieskim", "displayName": "David van de Meer", "active": true, "timeZone": "America/Los_Angeles" }, "subtasks": [], "reporter": { "name": "dieskim", "key": "dieskim", "displayName": "David van de Meer", "active": true, "timeZone": "America/Los_Angeles" }, "environment": "Android", "comment": { "comments": [ { "id": "436863", "author": { "name": "dieskim", "key": "dieskim", "displayName": "David van de Meer", "active": true, "timeZone": "America/Los_Angeles" }, "body": "The actual Class Google has created for this is [ProcessLifecycleOwner|https://developer.android.com/reference/android/arch/lifecycle/ProcessLifecycleOwner.html]\r\n\r\nFrom the Docs:\r\nClass that provides lifecycle for the whole application process.\r\n\r\n\"You can consider this LifecycleOwner as the composite of all of your Activities, except that ON_CREATE will be dispatched once and ON_DESTROY will never be dispatched. Other lifecycle events will be dispatched with following rules: ProcessLifecycleOwner will dispatch ON_START, ON_RESUME events, as a first activity moves through these events. ON_PAUSE, ON_STOP, events will be dispatched with a delay after a last activity passed through them. This delay is long enough to guarantee that ProcessLifecycleOwner won't send any events if activities are destroyed and recreated due to a configuration change.\r\n\r\n{color:#14892c}*It is useful for use cases where you would like to react on your app coming to the foreground or going to the background and you don't need a milliseconds accuracy in receiving lifecycle events.*{color}\"\r\n\r\nI spent some time trying to get this to work with hyperloop but I was unable.\r\n\r\nIt should be as simple as:\r\n\r\n\r\n{code:java}\r\npublic class AppLifecycleListener implements LifecycleObserver {\r\n\r\n @OnLifecycleEvent(Lifecycle.Event.ON_START)\r\n public void onMoveToForeground() {\r\n // app moved to foreground\r\n }\r\n\r\n @OnLifecycleEvent(Lifecycle.Event.ON_STOP)\r\n public void onMoveToBackground() {\r\n // app moved to background\r\n }\r\n}\r\n\r\n// register observer\r\nProcessLifecycleOwner.get().getLifecycle().addObserver(new AppLifecycleListener());\r\n{code}\r\n", "updateAuthor": { "name": "dieskim", "key": "dieskim", "displayName": "David van de Meer", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2018-04-13T12:11:49.000+0000", "updated": "2018-04-13T12:48:19.000+0000" }, { "id": "436901", "author": { "name": "dieskim", "key": "dieskim", "displayName": "David van de Meer", "active": true, "timeZone": "America/Los_Angeles" }, "body": "Hi,\r\n\r\nI am willing to put in the work to get this implemented but I will need some advice from some of the main android devs on how they want it to be done.\r\n\r\n1. We will need to add dependencies - how would we add these?\r\n\r\n{code:java}\r\n // Lifecycles\r\n implementation 'android.arch.lifecycle:extensions:1.1.1'\r\n annotationProcessor 'android.arch.lifecycle:compiler:1.1.1'\r\n{code}\r\n\r\n2. From what I can see from the current SDK code we have 2 options to implement this - What would be the best or preferred way? \r\nOption 1:\r\nAdd to [onCreate|https://github.com/appcelerator/titanium_mobile/blob/b758504ce898d0e93e461849cbb8975283da85bc/android/titanium/src/java/org/appcelerator/titanium/TiApplication.java#L360] of Android app - with triggers that fire but only fire to the app level js if listeners are added\r\nThis would match what iOS does via [registerForNotifications|https://github.com/appcelerator/titanium_mobile/blob/8ab7ac87ef1663c4cd8b50afc59b3bea72f31d53/iphone/Classes/TiModule.m#L114]\r\n\r\nOption 2:\r\nAdd to [onHasListenersChanged|https://github.com/appcelerator/titanium_mobile/blob/b758504ce898d0e93e461849cbb8975283da85bc/android/modules/app/src/java/ti/modules/titanium/app/AppModule.java#L255] as was done when adding listeners for \"accessibilitychanged\".\r\n\r\nAgain I am not sure about this and there could be other better ways to do this, but I am willing to do the work, test etc to get this done, I would just need some guidance from one of the main Android devs.\r\n\r\n", "updateAuthor": { "name": "dieskim", "key": "dieskim", "displayName": "David van de Meer", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2018-04-16T06:24:01.000+0000", "updated": "2018-04-16T06:24:01.000+0000" }, { "id": "436920", "author": { "name": "jquick", "key": "jquick", "displayName": "Joshua Quick", "active": true, "timeZone": "America/Los_Angeles" }, "body": "We already have the ability to detect if a Titanium app is in the foreground/background on the Java side now. Internally, we monitor it via our {{TiApplication.addActivityTransitionListener()}} and {{TiApplication.isCurrentActivityInForeground()}}. We do this by tracking the state of all Titanium derived activities, which was your only option before Google's offered the ability to monitor activity lifecycles globally.\r\n\r\nFor example, we do this with our Titanium Gesture module so that it'll disable the accelerometer and gyroscope sensors when the app is backgrounded and re-enable them when put back into the foreground...\r\n[GestureModule.java#L80|https://github.com/appcelerator/titanium_mobile/blob/master/android/modules/gesture/src/java/ti/modules/titanium/gesture/GestureModule.java#L80]\r\n\r\nThe only goofy thing on Android that I recall is that if you press the power button while your app is in the foreground and then press the power button again to show the screen lock, the app's activity will be resumed even though the screen lock is still completely covering up the app. This is okay for normal UI apps, but any apps that play music/sound will typically still want it paused until the screenlock has been slid off. So, this could involve monitoring the screen lock via a BroadcastReceiver too... which is something Google's Lifecycle classes don't handle (last I tried it at least).\r\n\r\nI agree that supporting the {{Ti.App.pause}} and {{Ti.App.resume}} events would be good.", "updateAuthor": { "name": "jquick", "key": "jquick", "displayName": "Joshua Quick", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2018-04-16T17:37:30.000+0000", "updated": "2018-04-24T16:58:22.000+0000" }, { "id": "437088", "author": { "name": "dieskim", "key": "dieskim", "displayName": "David van de Meer", "active": true, "timeZone": "America/Los_Angeles" }, "body": "@Joshua Quick - So at this stage it does not seem like we are able to use the new Google global activity lifecycle monitors via Hyperloop, I think it would need to be added to the core.\r\n\r\nWould using Hyperloop with `TiApplication.isCurrentActivityInForeground` be a good option for monitoring app in foreground / background at this stage? Or what do you suggest?\r\n\r\nLike I said I am willing to put in the work to get the new proper Google Global monitors added to the core but I would need some guidance on what method to use to add this etc.\r\n\r\nLet me know", "updateAuthor": { "name": "dieskim", "key": "dieskim", "displayName": "David van de Meer", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2018-04-24T04:17:58.000+0000", "updated": "2018-04-24T04:17:58.000+0000" }, { "id": "437123", "author": { "name": "jquick", "key": "jquick", "displayName": "Joshua Quick", "active": true, "timeZone": "America/Los_Angeles" }, "body": "I don't think we need to add this library. We already have the APIs needed internally to do this. We'll look into this later.", "updateAuthor": { "name": "jquick", "key": "jquick", "displayName": "Joshua Quick", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2018-04-24T18:00:23.000+0000", "updated": "2018-04-24T18:00:23.000+0000" }, { "id": "437483", "author": { "name": "dieskim", "key": "dieskim", "displayName": "David van de Meer", "active": true, "timeZone": "America/Los_Angeles" }, "body": "@Rene Pot @Joshua Quick - Would using Hyperloop with `TiApplication.isCurrentActivityInForeground` be a good option for now until this is part of the core? I have tried to get that class imported with hyperloop using the code below but have not been able to - any suggestions? \r\n\r\n\r\n{code:java}\r\nvar TiApplicationClass = require('org.appcelerator.titanium.TiApplication');\r\n{code}\r\n\r\n", "updateAuthor": { "name": "dieskim", "key": "dieskim", "displayName": "David van de Meer", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2018-05-09T04:26:57.000+0000", "updated": "2018-05-09T04:26:57.000+0000" }, { "id": "437528", "author": { "name": "jquick", "key": "jquick", "displayName": "Joshua Quick", "active": true, "timeZone": "America/Los_Angeles" }, "body": "Unfortunately, hyperloop is not set up to access our core Titanium libraries. So, this isn't going to work. Unless you do it via Java reflection in hyperloop, but that would be kind of nuts. :P\r\n\r\nFor your info, we plan on updating our Google Support libraries in Titanium 7.2.0... and the newest libraries \"requires\" the lifecycle components as a dependency. So, perhaps you should wait until then if you can.", "updateAuthor": { "name": "jquick", "key": "jquick", "displayName": "Joshua Quick", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2018-05-09T17:49:19.000+0000", "updated": "2018-05-09T17:49:19.000+0000" }, { "id": "438462", "author": { "name": "dieskim", "key": "dieskim", "displayName": "David van de Meer", "active": true, "timeZone": "America/Los_Angeles" }, "body": "Hi @Joshua Quick - I see that Titanium 7.2.0. was released, does this contain the new Google Support libraries that could help us do this? If so how do we proceed at making this simpler and more possible?", "updateAuthor": { "name": "dieskim", "key": "dieskim", "displayName": "David van de Meer", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2018-06-18T07:16:51.000+0000", "updated": "2018-06-18T07:16:51.000+0000" }, { "id": "438484", "author": { "name": "jquick", "key": "jquick", "displayName": "Joshua Quick", "active": true, "timeZone": "America/Los_Angeles" }, "body": "No. The new support libraries providing the lifecycle components will be in Titanium 7.3.0.", "updateAuthor": { "name": "jquick", "key": "jquick", "displayName": "Joshua Quick", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2018-06-18T17:41:32.000+0000", "updated": "2018-06-18T17:41:32.000+0000" }, { "id": "438502", "author": { "name": "dieskim", "key": "dieskim", "displayName": "David van de Meer", "active": true, "timeZone": "America/Los_Angeles" }, "body": "For now I have built and released and Hyperloop Module for this:\r\n\r\nhttps://github.com/dieskim/Appcelerator.Hyperloop.appPauseResume\r\n\r\nCross-platform Hyperloop Module for detecting if app paused or resumed on both the iOS and Android\r\n\r\n- iOS uses core T.App EventListeners pause and resume\r\n- Android uses Narive Java Classes via Hyperloop and a setInterval to check and detect\r\n\r\n{code:java}\r\nExample:\r\n// require appPauseResumeModule\r\nvar appPauseResume = require('appPauseResume');\r\n// run appPauseResume and add resume and pause callbacks\r\nappPauseResume({pause: function(){\r\n Ti.API.info(\"appPauseResume - pause\");\r\n },\r\n resume: function(){\r\n Ti.API.info(\"appPauseResume - resume\");\r\n },\r\n setIntervalTime: 1000, // Optional - Default: 1000 miliseconds (1 second) \r\n});\r\n{code}\r\n", "updateAuthor": { "name": "dieskim", "key": "dieskim", "displayName": "David van de Meer", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2018-06-19T10:01:24.000+0000", "updated": "2018-06-19T10:01:24.000+0000" }, { "id": "443046", "author": { "name": "jquick", "key": "jquick", "displayName": "Joshua Quick", "active": true, "timeZone": "America/Los_Angeles" }, "body": "This was implemented by [TIMOB-26424] to be released in 7.5.0.\r\nClosing this ticket as duplicate.", "updateAuthor": { "name": "jquick", "key": "jquick", "displayName": "Joshua Quick", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2018-10-29T23:14:02.000+0000", "updated": "2018-10-29T23:14:02.000+0000" } ], "maxResults": 12, "total": 12, "startAt": 0 } } }