I am developing an Android app and I am using a library I wrote. This library has a class that contains some static fields. One of them is a API key. This key is used by other classes in my library to make calls on a remote service.
I initialize the API key on my main Activity once when it is created and the savedInstanceState is null.
My problem lies in other activities as they sometimes use the correct API key when making calls with my library and sometimes they do not. It seems as if the API key has not been set.
In particular there is one activity that i call from my preferences activity that always fails as the API key is not set.
Are not static fields maintained across Activities as they are on normal Java applications? I thought that for a specific jvm instance, all static fields are retained. Is the Android platform using new jvm instances for new Activities?
Please read:
http://developer.android.com/guide/topics/fundamentals.html#procthread
Your app is running in a process. The process may need to be killed while it is in the background. Your app must correctly save whatever state is appropriate as it goes in the background (via for ex Activity.onSaveInstanceState()) and/or reconstruct its state when later restarting in a new process.
Are you accessing the static field in a direct or indirect way?Are other activities mess with the Api key?If so you should synchronized before accessing it
Related
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.
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 want know i pass a variable via Intent to another activity and that activity changes that variable, will it reflect in original activity without passing back the intent.
If answer is no then is it better to use global variable using application then passing intent and getting back data. in my program, i am having round 5+ activities and all of them need to access a list of class objects.
any recommendations apart from above
Create your own extension of Application to store the state of your app and share data between the different activities that make up your app. The Application acts as the context for your whole app and Android guarantees there will always only be one instance across your app. Hence it works similar to defining your own Singleton, but using Application will allow Android to take control of the life cycle of your shared data and basically do the memory management for you.
To summarize:
Create your own subclass of Application.
Specify that class in the application tag in your manifest.
After this you will be able to safely cast the result of all call to getApplication() (from an Activity instance) and getApplicationContext() (from any Context instance) to the subclass you defined in step #1. This means you can use any getter/setter method defined in your application extension to store/retrieve data.
Have a read here for more details.
I need to access com.android.internal.telephony.gsm.GsmSmsDispatcher's sendRawPdu method.
I've done a little research and found that GSMPhone class contains GsmSmsDispatcher instance. I hoped to obtain GSMPhone instance from PhoneFactory but it seems to be uninitialized (it's static variables are null).
Android API version >= 8.
You can't access Android's internal classes using reflection. Each application in Android runs in its own process with its own instance of the Dalvik VM. Classes loaded in one process are not visible to another process. So when you try to access static variables from PhoneFactory, you end up loading the PhoneFactory class with unintialized variables.
Your best will be to do whatever you want to get done using the Android APIs. There are a few ways to get access to some private Android services, but it won't get you too far. The only relevant one for SMS is the isms service. You can look through the methods available in it in the ISms.aidl file present in the com.android.internal.telephony package.
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.