Suppose you have a news app like Yahoo.
When a user runs your app and move out of your app (without quitting the app).
After a while (like an hour) he comes back, and you want to refresh the page (if he's seeing the front Yahoo page, it may have new news to show)
Is this a thing that I don't need to worry about because android actually disposes the long lived activity?
Or is this a thing that I have to implement it myself?
If I have to do it myself, should I implement this with saving 'exit time' and comparing it with 'resume time' and so forth or are there android/ios support or github library?
You can get an idea about Android life cycle and activity by browsing this
https://developer.android.com/reference/android/app/Activity
If you create an application using react-native and deploy it to both Android and IOS, you need to use a compatible react-native module for that.
If you only consider an android application. You can override onStart(), onResume(), onStop(), onPause() and onDestroy() methods to do what u want in certain states.
eg: If u want to reload new content when reopening the application, u need to override that refresh criterion in an overridden onResume() method.
Assuming you want to update the content after however long, assuming that your data is coming from a remote source that you are loading within your React Native application - you can hit one of the React Native JS lifecycle events.
For example, you can use componentDidMount():
componentDidMount() is invoked immediately after a component is mounted (inserted into the tree). Initialization that requires DOM nodes should go here. If you need to load data from a remote endpoint, this is a good place to instantiate the network request.
This method is a good place to set up any subscriptions. If you do that, don’t forget to unsubscribe in componentWillUnmount().
If youre wanting to create a custom React Native Module, then you'll need to create an Android Service - but assuming you have an API endpoint for your data and the data will only be refreshed when the user is interacting with the app - I don't see why you'd need a custom module. It's all built in already.
You should use facebook.github.io/react-native/docs/appstate to check when the app becomes active, and then you do stuff.
Related
When an Android App is sent to the background, it can persist its instance state in case it gets killed due to low memory (see Activity:onSaveInstanceState() and the bundle argument for Activity:onCreate(Bundle savedInstanceState)).
The default Activity behaviour is saving the state of the view hierarchy so for a lot of cases you don't have to write any code and it "just works"[tm].
Now for react-native this is not true. React native apps are hosted in a single MainActivity and their state is contained in the javascript interpreter in the app.
I created a sample repository with short documentation how to reproduce my problem here: https://github.com/einvalentin/react-native-state-test
I would want react-native to hook into the native android app state serialisation mechanism while providing application developers hooks to extend if they need custom serialisation. Alternatively I could see myself extending the MainActivity to forward the lifecycle events to the Javascript layer and do some custom state serialisation manually there - but this feels a bit clunky.
Is there an obvious way I have overlooked to save the state in react-native so that apps that are killed in the background are not restarted from scratch? This can always happen for example on low memory devices receiving a phone call while interacting with your app.
Thanks a lot!
If you are using Redux for state management you should probably use redux-persist. If not you have a couple of different options:
AsyncStorage
Realm React Native
My app needs to initially download data from two different web services (JSON) and import them into it's local database (Realm). I have two activities that need to display data from these web services. The first one (HomeActivity) is the initial activity that the app loads. The second one (LineupActivity) is created when navigating to it from the HomeActivity.
Currently, I've created an Application class (extending Application) in order to handle the web service downloading and importing. In it's onCreate(), it calls two methods, which are AsyncTasks that download and import each web service.
The reason I've added this download/import process into the Application class is for 2 reasons:
I want all the app data to be downloaded as soon as possible, so
when navigating to the second activity it doesn't need to initiate
another download.
Both these activities have swipe to refresh. They call each respective method in the Application class to re-download/import the
web service data.
Have I approached this incorrectly? Should I move the web service download/import logic out of the Application class? Also, does the onCreate() of the Application class get called more than once? Meaning, I know that it only gets called only once in the application's lifecycle, but does the Android OS eventually kill an app and have it call the onCreate() in the Application class when starting it again? I want the app to download fresh data upon startup, but not every time the user brings the app into focus.
Have I approached this incorrectly?
"Incorrectly" is a very relative term in this context.
Metaphorically, its like the context is never null but that doesn't determine boolean incorrect is true or false.
Should I move the web service download/import logic out of the Application class?
I would say Yes, as the download logic would not be related to the O.S. and the app being alive in its memory. Your requirement does not seem complex. Service would be necessary if the downloads are huge chunks of data, and if its not necessary, don't do it.
Also, does the onCreate() of the Application class get called more than once? Meaning, I know that it only gets called only once in the application's lifecycle...Application class when starting it again?
No, it won't be called more than once without app being killed and restarted. And what your are saying is correct, but for your requirement, there are probably more efficient and lighter ways to do it rather than combining it with an Application class.
For the rest of the logic, you could implement Asynctasks as a separate class and implement interfaces which are the callbacks of the result of your task. This would help in Swipe-to-refresh functionality.
In terms of documentation reference, Application class
There is normally no need to subclass Application. In most situation,
static singletons can provide the same functionality in a more modular
way.
Your case seems exactly that.
One thing you need to decide is When, how often do you need to refresh/download the data. For only start-up of the app or once daily, you can store date/day in SharedPreferences and check the value in onResume() of your Activity.
You can also implement inheritance with a Base Activity with the necessary download check logic in it and extend your classes. A Splash Screen would always help to initiate the downloads.
I suppose you could approach this anyway you want, though I like to implement one of the three options mentioned here: https://dl.google.com/googleio/2010/android-developing-RESTful-android-apps.pdf.
The presentation itself can be found here: https://www.youtube.com/watch?v=xHXn3Kg2IQE.
This does however not mention how you should sync on startup. But you could just set a SharedPreference in the application class and then use one of the patterns to sync in the background.
I'd recommend you instead of using Application to download your stuff to use a Service. If by any reason your app gets killed by the OS your dl's will never complete. Using a Service it will.
Also, you can use a Broadcast to your activity to signalize that the service has completed downloading and taking the necessary following steps.
first: I think it's bad to place the download at appliaction onCreate
as stated in documentation
Called when the application is starting, before any activity, service,
or receiver objects (excluding content providers) have been created.
Implementations should be as quick as possible (for example using lazy
initialization of state) since the time spent in this function
directly impacts the performance of starting the first activity,
service, or receiver in a process. If you override this method, be
sure to call super.onCreate().
pay attention to this part
Implementations should be as quick as possible (for example using lazy initialization of state) since the time spent in this function directly impacts the performance of starting the first activity
so any delay in download or import may cause the first activity to be delayed.
and the behavior is not clear, a black screen maybe?
Second suggestions for download/import:
1- use an AsyncTask in the first activity, where you display a small progress bar indicating the download/import process or even block the whole UI until completed (based on your business)
2- add a splash screen while downloading the data
regarding fresh data, you can store a timestamp, last_updated
and before starting the download/import process, check that value, if less than your accepted value (say 1 hour) don't start the download/import.
finally, regarding onCreate() call, i think it's not called everytime, only when app is re-created, like 1st run after reboot, or after being killed or forced close.
I am working on a solution or code that can be embedded inside of an Android APK to track how many times the app has been launched and how long the app has ran for. I know one way to do this is using the ActivityLifecycleMethods in API 14 and in lower versions of Android having code placed in all Activity Lifecycle events or by providing a base Activity class.
1) Is there a way to hook the ActivityLifecycleMethods without the developer having to make any changes to their code outside of dropping additional code into their App?
I believe this answer is no because even with an Enum Singleton it is not loaded until it is referenced. Also the Enum Singleton will go away once the activity is changed since a different class loader is used when activities change.
If I wanted to keep the Enum Singleton around would it be possible to store a reference to the applicationContext and thus it wouldn't be removed when the Activity changes? Is that what google means by
"There is normally no need to subclass Application. In most situation, static singletons can provide the same functionality in a more modular way. If your singleton needs a global context (for example to register broadcast receivers), the function to retrieve it can be given a Context which internally uses Context.getApplicationContext() when first constructing the singleton." on http://developer.android.com/reference/android/app/Application.html
2) I am not a fan of this solution for older API versions. It seems very likely developers could forget to modify their Activity Lifecycle methods or forget to inherit from the created BaseActivity. Are there any other unique solutions for these older platforms? Is there any other approaches that can be done to determine when an activity isn't running? Could any of the following work:
a) User a class loader to ensure the base activity with the proper metrics are always used
b) Implement some type of heart beat. Will a timer stop working if the app is paused or killed? Is there some other way? Could the ActivityManager be used?
You have many Analytic Agents like Flurry to do that.
When ever you want to track an event, you will add it to flurry and inturn it syncs with server after specific time.
You may use the same logic.
Better create a library file with following features:
Start Application
End Application and report time to db.
Track a specific event count and update to db.
Sync the data to server you like to.
Call appropriate events from your app.
I’ve written a library for Android, upon initialising the library I register for call backs for location updates, subscription status changes, library status changes and various other updates...
Originally, I wanted all these updates to call back to a controller in my android UI app, and then for the controller to launch activity A, pass on the messages from the controller to activity A and so on. Or launch activity B for signing up for a subscription and forward messages to this etc
However, it appears that there isn’t a way to achieve this - Because each activity is in isolation? Unless I’m mistaken?
So what are my options here? It sounds like I either have to use one activity for the whole app and swap the UI’s which after looking into it doesn’t appear to be the way to go?
I did try to subclass Application, which worked and gave me access to my library from an activity – but I want it the other way around. Is this possible? would wrapping the library in a service achieve what I want to do?
You could use broadcasts and send them from your library. Each of your activities would have to register a BroadcastReceiver in their onResume() method and unregister it in their onPause() method. This would be comparatively easy when you use a common base class for your activities. You could then send commands from your library to whatever activity is currently active.
I’m developing application for most major Mobile OS like iOS, Windows Phone and Android. I have a request from my client that simply possible to implement in iOS and WP but sounds really tricky in Android.
In iOS and WP, an application lifecycle is controlled through events which an object like UIApplication and Application receives.
In iOS, for ex., applicationDidEnterBackground:, applicationWillEnterForeground:, applicationWillTerminate: and the like, clearly define application states such as Inactive, Active and Background and make the app state management logic really straight forward.
In WP, Application receives well understanding events such as Launching, Deactivated, Activated, and Closing which make it really simple to decide what should be done in each app state logically to save as restore application wide object model.
But in Android, application state management sounds really difficult with Activities’ state changes such as onCreate, onRestart… onDestroy method overriding. My problem arises where I want to control the whole application state when the user session goes expired and I want to redirect user to the sign in activity and shuts down other open activity.
Regarding the fact that calling finish() in an activity’s onCreate(), onRestart() or onResume() is ignored by Android (according to the documentation) .
Even if I override android.app.Application and put the logic there, it sounds like controlling open activities is not possible.
I almost tried all possible combinations of activity launch mode (such as SingleTask and SingleInstance) though I cannot produce behavior like those exist in iOS and WP.
There is another post related to this question which may clarify my problem more.
The question exactly is, “Is it possible to produce iOS or WP application behavior in Android anyway?”
So essentially, once a "session" expires, no matter what the user tries to do, you want them to be redirected to a login activity, yes?
Assuming you have a method you can call which tells you whether or not a session has expired, why no simply check that method in onResume() etc. and if the session has expired, redirect the user to the login Activity?
There's an answer here about the application state that may interest you:
Checking if an Android application is running in the background
With Application, you get the onCreate and you can put some logic here.
So yeah, it's not as straight forward as in iOS but it's doable.
If it's just a session state, create a base activity that check against the session state
and inherit all your activities from it.
You can close all your activties by using the Android SDK before going to the login page or... lock the back button.