From Firebase docs they say:
Multiple processes
Crash Reporting creates a separate background process to upload crash
info. If your app extends the Android Application class, you must
ensure it is multi-process safe. Otherwise, it may cause concurrency
issues. When an app extends an Application object, this object gets
instantiated for each process in a multi-process app. Two important
things to watch for are:
If the implementation of this object accesses any out-of-process state
(a database, the file system, shared preferences, etc), or performs
other actions not safe for a multi-process environment, concurrency
issues might arise. This is because multiple instances of the
Application object may run simultaneously. Many third-party libraries
keep out-of-process state (e.g. in a local database) and are subject
to the same concurrency issues if they are initialized from the
Application object. If your app fits the description above and you
plan to use Crash Reporting in your app, we strongly encourage you to
consider moving the Application logic to Content Providers, or to
Android Activities. Any Application logic that is not safe for a
multi-process environment can have unintended effects on your app.
How can I check from my Application class if theres another instance inside the Application onCreate to avoid crashes with Fabric or others?
Generally speaking, you don't "check to see" if there is another Application object from another process. You simply assume that there is always exactly one Application object created for every process in your app, and ensure for yourself that it will be safe to run in conjunction with other Applications objects in other processes. Just don't access any shared read/write resources from Application and you will be fine.
If you must initialize something from only the main process, a more reliable way of doing this is to create a ContentProvider (declare in your manifest and create an object for it like any other component), and use its onCreate(). ContentProviders are only created and initialized from the main process - never from other processes. This way you can be sure that your init will not be duplicated in any other process.
Or if you don't want to deal with this at all, just wait until Crash Reporting comes out of beta to full release, as it will not use an extra process at that time in the future. We (Google) can't say exactly when that will be, but we're not wasting any time in getting the full release published.
Related
I am new to Android and getting a bit confused in between Application class and Singleton.As I understood, it's not safe to store/maintain global value in Application or singleton class due to Out Of Memory Exception.So, any solution for that other than using persistence storage.and Apart from that, in which cases Application class useful?
I very much recommend singletons. If you have a singleton that needs a context, have:
MySingleton.getInstance(Context c) {
//
// ... needing to create ...
sInstance = new MySingleton(c.getApplicationContext());
}
I prefer singletons over Application because it helps keep an app much more organized and modular -- instead of having one place where all of your global state across the app needs to be maintained, each separate piece can take care of itself. Also the fact that singletons lazily initialize (at request) instead of leading you down the path of doing all initialization up-front in Application.onCreate() is good.
There is nothing intrinsically wrong with using singletons. Just use them correctly, when it makes sense. The Android framework actually has a lot of them, for it to maintain per-process caches of loaded resources and other such things.
Also for simple applications multithreading doesn't become an issue with singletons, because by design all standard callbacks to the app are dispatched on the main thread of the process so you won't have multi-threading happening unless you introduce it explicitly through threads or implicitly by publishing a content provider or service IBinder to other processes.
As per stated in https://firebase.google.com/docs/crash/android#known-issues,
Crash Reporting creates a separate background process to upload crash info. If your app extends the Android Application class, you must ensure it is multi-process safe
The item we need to watch out are
a database, the file system, shared preferences, etc
I read shared preferences from my Application. How do I ensure it is multi-process safe?
You may need to change your approach. Unfortunately, as documented in the Android API, SharedPreferences are not safe to use from multiple processes:
Note: This class does not support use across multiple processes.
Firebase Crash Reporting currently adds a second process to your app; Application.onCreate() is called once for each process, so the shared preferences would be accessed from multiple processes, which is likely to cause problems.
Your alternatives are to move the SharedPreferences logic out of the Application class, or to wait with integrating Crash Reporting until Firebase has changed their design to not use a second process - they are actively working on it and will have it changed before they leave Beta.
If you decide to move the SharedPreferences logic, one approach can be to move it into a ContentProvider, as those are run in just a single process, before Application.onCreate(). I shared an example of this design in another StackOverflow post.
I would like to add a SyncAdapter to my app to update server-side data with minimal battery-use. For this, I need to have my application's main activity write data to some shared storage location that the SyncAdapter can then read in the onPerformSync(...) method.
I'm trying to figure out where best to store this data and have the following questions:
Could the SyncAdapter ever be called in a background thread while my main activity is executing in the foreground thread? I.e. do I need to worry about thread-safety of my storage access between the SyncAdapter and my main activity?
Are there ever any situations in which two instances of my main activity could be in the "Created" state? I.e. do I need to worry about thread-safety between two instances of my main activity?
Assuming that I do have to worry about any sort of thread safety, I have the following questions about the different data storage options:
Files in internal storage:
Are there any atomic operations I can perform on files in internal storage?
How about file locks?
SharedPreferences:
If two editors in different threads simultaneously modify different!!! keys in the Shared-Preferences, could two simultaneous commits lead to the loss of one of the changes?
SQL database:
Is the Android SQL Lite framework thread-safe if I simultaneously open the same SQL Lite database file from different threads?
Are there other ways to share data among SyncAdapters and (multiple instances of (if that is even possible)) the main activity?
Aside: To maximize compatibility of my app, I would like to not use any APIs greater than level 5.
I think, it should be possible to fix this issue by using a ContentProvider.
ContentProviders don't inherently solve the multithreading issue, as stated in the documentation:
Data access methods (such as insert(Uri, ContentValues) and update(Uri, ContentValues, String, String[])) may be called from many threads at once, and must be thread-safe. Other methods (such as onCreate()) are only called from the application main thread, and must avoid performing lengthy operations. See the method descriptions for their expected thread behavior.
But, unless the ContentProvider is declared with android:multiprocess=true, there should only ever be a single instance of the ContentProvider (if I understand this correctly), or at least all instances will live in the same process, i.e. they should have access the same static fields in the class definition.
With this, it should be possible to use the standard Java synchronization features to manage access to the storage-backed resources.
Please comment if I'm missing something...
Aside: Why all the "should's"?
Because, unfortunately, with Android's documentation, I'm never 100% sure that it's reliable or complete. Example here: The quote above states that "[o]ther methods (such as onCreate()) are only called from the application main thread"... What happens when I set android:multiprocess=true? The docs there state that "if this flag is set to 'true', the system can create an instance in every process where there's a client that wants to interact with it". Would this lead to a call to onCreate() from a thread other than this application's main thread? Probably...
First time asking on stackoverflow here !
Okay so here's the context. I'm doing an android application, and I'm trying to implement something like a plug-in framework.
My main app's MainActivity's purpose is to manage and launch/show Fragments.
Each of my plug-in will contain (at least) a Fragment and it's layout.
Thus, the idea is to fetch the fragment and put it inside my main app's MainActivity, from it.
So I decided to put my Fragments/Plug-ins into different apps and give all my plug-ins and main app the same user_id. This way all of them are in the same process, and even if they appear in the phone's Application Manager, only the main app is launchable and visible in the Application Browser (which is great).
But here's my problem... How do I get access to my plug-ins Fragments ?
I thought I could fetch some class through the PackageManager and use relfexion to use my fragment, but apparently you can't (or I didn't find how).
I considered binding Services together on each end (Application - Plug-in) but I have no guarantee that the services will bind together. Especially since each app have the same copy of the service, aka not the same Service.
Maybe by using a common .jar to make sure the Services are the same, and thus pass an instance of my Fragment to the main app (yes an instance would suffice).
Or make a CustomClassLoader (but then I might need advice on how to load classes from my other app, because I don't know how to do that...)
I've been running in circles in my head and on the net to find a solution...
To make things clear:
How do i fetch the classe (CustomClassLoader) or an instance (via binding or maybe sharedPreference or wiriting my instance in a file and read it in the main ?) of another app, considering they share the same user_id and thus are in the same process ?
Just because apps share the same user_id this does not imply they are running in the same process. They may and propably have been started by the same process. Sharing resources amongst processes is commonly known as IPC.
AIDL , the android Interface Definition language is a way for implementing IPC. Still this will not allow you retrieve objects from a different application directly but the possibility to invoke methods on remote objects.
But your problem description to me seems more like accessing objects of an jar at runtime in an application. This could be done via classloading.
So your app could retrieve a jar from a Server and load your fragments from it. The definitions of the fragments than would be runtime updateable if you define your fragments completely by code.
I have an android application that is running. After a while when user quits the application by running something else, and returning to my app, the static variables in the application is seem to have been garbage collected.
In a nut shell, I'm keeping the entered username/password at startup of the application and keep them in a static variable, and use them for communication with server. I either need to find out when they are garbage collected at application re-launch (so that I redirect them to login view) or prevent this class from being garbage collected. Ideas?
One way you could implement your second scenario is by implementing your own class that inherits Application, and specify it in your manifest. You can put your static variables in that class. Android will create one instance of that class when it launches your process, and that instance will be alive as long as the process is alive too.
So, if you have a simple boolean in that class that denotes if a signin has been performed, you now have a reliable way to check at any point whether you should direct the user to the login activity, or try using the in-memory username/password.
In addition, you could use one of the standard Android persistence component (shared preference file, SQLLite, AccountManager, OBB, credential storage, etc) to persist the credentials across process restart. Note however, that doing so raises a whole new set of issues around how to properly secure that persisted copy of the user credentials, in order to protect it from unauthorized access by other applications (especially on rooted phones).
I suggest not trying to "prevent this class from being garbage collected". Instead, work within the framework as it was intended.
(Not addressing the topic of user authentication or credentials management...)
Android provides a few options for storing data, outlined at http://developer.android.com/guide/topics/data/data-storage.html. For your situation, using preferences might be a decent, light-weight, easy-to-implement option.
Also, note that keeping the values in an Activity's members might well-solve the problem, if the app has an Activity that's using the values. If so, then note that use of onSaveInstanceState(Bundle) and onRestoreInstanceState(Bundle) may be in order.