Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-23433] Android: Background service loses activity context and properties when restarted

GitHub Issuen/a
TypeBug
PriorityCritical
StatusClosed
ResolutionCannot Reproduce
Resolution Date2019-10-03T17:22:17.000+0000
Affected Version/sn/a
Fix Version/sn/a
ComponentsAndroid
LabelsAndroid, engTriage
ReporterJörgen Buder
AssigneeEric Merriman
Created2016-05-25T07:02:21.000+0000
Updated2019-10-03T17:22:17.000+0000

Description

For a long time we have been using a background service backed up with a alarm manger to implement a reoccurring service that runs some code and talks to a backend. This is a very common thing to do. To develop this feature according to google guide lines the use of a alarm manager is required to avoid having the service die due to different Android SDK limitations in power schemes and standby. Over time (2 years) I have seen Android 4, 5 and now 6 implement harsher and more restricted limitations on services. Too make sure a service is kept alive after a shutdown of the app for what ever reason you use the START_STICKY option to make the service restart. This is to make sure the service restarts if the main app (activity) is shut down by the user or by the system. The START_STICKY option makes the service restart regardless of the main app (activity) Along with this setting the Alarm manager will make sure to reenable/ restart the service if for any reason the Android system shut down the service for battery or other standby / doze reasons. For the moment we have a service running as expected when it comes to these settings and issues, however for a long time we have seen that the service that are restarted loses its original inheritance from the main app. For instance if you make an app and a service (see your own docs) the service can access the Alloy.Globals properties as long as the service is not restarted. This is most probably due to the fact that the service (thread) inherits the main apps memory area. This is at least how a Linux system would work. So far all good, but now if the service is restarted from a START_STYCKY setting, making sure that the service stays aline even if the main app (activity) is killed the service can no longer use the Alloy.Globals. We have of course worked around this by require the Alloy framework, however that will not solve the variables to come back, we also have to reinitiate them and set them "again" to make sure they are available everytime the service is restarted. Over time we have however found a problem we cannot solve without having to patch your SDK every time and at all code lines where you use it. In many many places in your code of the SDK you use something like: public boolean hasLocationPermissions() { if (Build.VERSION.SDK_INT < 23) { return true; } Activity currentActivity = TiApplication.getInstance().getCurrentActivity(); if (currentActivity.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { return true; } return false; } this is found in the file: and at the latest nightly builds android/modules/geolocation/src/java/ti/modules/titanium/geolocation/GeolocationModule.java As you can see you are using the : Activity currentActivity = TiApplication.getInstance().getCurrentActivity(); the problem is this is available when the service is still alive and inherited from main context, then the service is restarted the .getCurrentActivity is not available anymore, instead you have to use: .getApplicationContext So for every API that you have and use the TiApplication.getInstance().getCurrentActivity(); it means that the service in Android will crash, we have made some initial searches i your SDK and you use the TiApplication.getInstance().getCurrentActivity(); everywhere. To make the service remain working using the common APIs that can be run in a background service like location above you have to change all these lines of code into .getApplicationContext Now this is a CRITICAL VERY HIGH PRIO problem as this means (unless we are wrong) that no service in android can remain active when the main app is shut down and using START_STICKY is very common and the right way to use a service in the background, as well as using Alarm manager. We also found the same problem here: ndroid/modules/platform/src/java/ti/modules/titanium/platform/PlatformModule.java also an API that is a must in the background service, that one uses : Activity a = getActivity(); There are more. We have had to patch EVERY API to have our Service continue service after the more and more common doze and standby along with limitations from the system. This is a none wanted situation and should be quite critical to you too making sure the community and professionals can use the backgrund service continually. The last problem we encountered was that you probably use the same lines of code in your Analytics proprietary module making the Analytics to effectively crash in the service when used after a restart of the service, this also is a BIG problem as you want the analytics to report as well as not crashing the app. Here we havd to go into the SDK and remove the call to the Analytics module.. since we cant patch that code. Can we PLEASE have some attention to this serious bug in Android and sort this thing out. I do not have the time to make a example app of this right now but may help you later, just make sure to make a background service that uses START_STICKY and then kill the main app in the monitor (DDMS) observe the service restart (you do not have to use Alarm Manager as well) and then make sure you use one API that uses that getCurrentActivity call and you will see the service stop running...

Comments

  1. Jörgen Buder 2016-05-25

    We made one more test excluding the alarm manager accessing the geolocation permission call, and we get this result: 05-25 10:02:26.590 780 789 I art : Background sticky concurrent mark sweep GC freed 75110(5MB) AllocSpace objects, 182(3MB) LOS objects, 2% free, 316MB/325MB, paused 1.156ms total 145.227ms 05-25 10:02:45.544 780 884 D WifiStateMachine: starting scan for "GWS_DEVEL"WPA_PSK with 2437,2462,5220,5180 05-25 10:02:56.296 780 793 I ActivityManager: Start proc 15925:com.purplescout.dev.gws/u0a446 for service com.purplescout.dev.gws/.Background_locationservice_androidService 05-25 10:02:56.299 15925 15925 I art : Late-enabling -Xcheck:jni 05-25 10:02:56.352 15925 15925 I TiApplication: (main) [0,0] checkpoint, app created. 05-25 10:02:56.398 15925 15931 I art : Debugger is no longer active 05-25 10:02:56.664 15925 15925 I TiApplication: (main) [312,312] Titanium 1.0.0 (2016/03/10 14:23 HEAD) 05-25 10:02:56.809 15925 15925 I TiApplication: (main) [145,457] Titanium Javascript runtime: v8 05-25 10:02:56.816 15925 15925 D SmsModule: (main) [7,464] inside onAppCreate 05-25 10:02:56.816 15925 15925 D GCMModule: (main) [0,464] onAppCreate com.purplescout.dev.gws.ErvApplication@5db3fef (false) 05-25 10:02:56.816 15925 15925 D ExtendandroidModule: (main) [0,464] inside onAppCreate 05-25 10:02:56.817 15925 15925 D WebviewfragmentModule: (main) [1,465] inside onAppCreate 05-25 10:02:56.962 15925 15944 W V8Object: (KrollRuntimeThread) [144,609] Runtime disposed, cannot set property 'userAgent' 05-25 10:02:57.061 15925 15944 I TiAPI : SERVICE: Background Location Service BEGIN 05-25 10:02:57.063 15925 15944 D Module : Loading module: alloy -> Resources/alloy.js 05-25 10:02:57.073 15925 15944 D Module : Loading module: alloy/underscore -> Resources/alloy/underscore.js 05-25 10:02:57.116 15925 15944 D Module : Loading module: alloy/backbone -> Resources/alloy/backbone.js 05-25 10:02:57.138 15925 15944 D Module : Loading module: alloy/constants -> Resources/alloy/constants.js 05-25 10:02:57.148 15925 15944 D Module : Loading module: alloy/CFG -> Resources/alloy/CFG.js 05-25 10:02:57.152 15925 15944 D Module : Loading module: logger -> Resources/logger.js 05-25 10:02:57.154 15925 15944 D Module : Loading module: gps_service -> Resources/gps_service.js 05-25 10:02:57.158 15925 15944 D Module : Loading module: api -> Resources/api.js 05-25 10:02:57.169 15925 15944 D Module : Loading module: utils/GWSCipher -> Resources/utils/GWSCipher.js 05-25 10:02:57.173 15925 15944 D Module : Loading module: vendor/base64 -> Resources/vendor/base64.js 05-25 10:02:57.177 15925 15944 D Module : Loading module: vendor/pack -> Resources/vendor/pack.js 05-25 10:02:57.179 15925 15944 D Module : Loading module: vendor/aes -> Resources/vendor/aes.js 05-25 10:02:57.209 15925 15944 D Module : Loading module: vendor/q -> Resources/vendor/q.js 05-25 10:02:57.245 15925 15944 I TiAPI : SERVICE: Android Background Location Service start 05-25 10:02:57.245 15925 15944 D Module : Loading module: permissions -> Resources/permissions.js 05-25 10:02:57.248 15925 15944 I TiAPI : ==== API : Waiting getReceiverMessagesMD5 ... 05-25 10:02:57.251 15925 15944 I TiAPI : SERVICE: Time since last phone status update: 211.31 s 05-25 10:02:57.254 15925 15944 D TipermissionsModule: (KrollRuntimeThread) [293,902] Ti Permissions Module ctor 05-25 10:02:57.255 15925 15944 D TipermissionsModule: (KrollRuntimeThread) [1,903] check for granted permission: android.permission.ACCESS_FINE_LOCATION 05-25 10:02:57.263 15925 15925 D AndroidRuntime: Shutting down VM 05-25 10:02:57.264 15925 15925 E AndroidRuntime: FATAL EXCEPTION: main 05-25 10:02:57.264 15925 15925 E AndroidRuntime: Process: com.purplescout.dev.gws, PID: 15925 05-25 10:02:57.264 15925 15925 E AndroidRuntime: java.lang.NullPointerException: Attempt to invoke virtual method 'int android.app.Activity.checkSelfPermission(java.lang.String)' on a null object reference

  2. Jörgen Buder 2016-05-25

    NOTE this is only one example, this is true for any of these API accesses.
  3. Ashraf Abu 2016-05-26

    [~buder] Thanks for creating this issue. I notice you mention that you had to patch every API in the SDK. It would save time if you have that changes done as a Pull Request to be reviewed. Would that be possible?
  4. Riduanul Islam 2018-07-02

    Do we have any progress or any workaround, So we can update to the customer?
  5. Jörgen Buder 2018-08-06

    Eric, if you need any more info I am watching this, but I have no time to make you examples and such, I think my description is VERY clear and it is quite easy to make a background service like I describe and test this for your self. Hope you solve this problem this time, it has been around for some time now and limits the use of for instance the analytics module (cannot be used) and so on. Thanks
  6. Alan Hutton 2019-10-02

    We have entered this into engTriage for review. [~buder] Thanks for the offer we will reach out if we need further information.
  7. Joshua Quick 2019-10-03

  8. Alan Hutton 2019-10-03

    Closing per developer comments.

JSON Source