I am receiving this exception in LogCat every time I press the Back button in my app:
Activity has leaked ServiceConnection
com.android.vending.licensing.LicenseChecker#471cc039 that was
originally bound here
The code responsible for this leak in onCreate() is:
mLicenseCheckerCallback = new MyLicenseCheckerCallback();
mChecker.checkAccess(mLicenseCheckerCallback);
How do I get rid of this leak?
I tried not assigning MyLicenseCheckerCallback to a member, thinking perhaps when the activity goes onPause() the reference to the callback is responsible for the leak:
mChecker.checkAccess(new MyLicenseCheckerCallback());
But that didn't get rid of the leak.
Update: Thanks to #zapl's comment below, I looked at Google's LicenseChecker.java:
/** Unbinds service if necessary and removes reference to it. */
private void cleanupService() {
if (mService != null) {
try {
mContext.unbindService(this);
} catch (IllegalArgumentException e) {
// Somehow we've already been unbound. This is a non-fatal error.
Log.e(TAG, "Unable to unbind from licensing service (already unbound)");
}
mService = null;
}
}
At first I thought that I may be neglecting to call it, but I double-checked and I am calling mChecker.onDestroy(); in my activity's onDestroy().
I also checked onDestroy() in LicenseChecker.java and it is calling unbindService:
/**
* Inform the library that the context is about to be destroyed, so that
* any open connections can be cleaned up.
* <p>
* Failure to call this method can result in a crash under certain
* circumstances, such as during screen rotation if an Activity requests
* the license check or when the user exits the application.
*/
public synchronized void onDestroy() {
cleanupService();
mHandler.getLooper().quit();
}
So, what is really going on?
Is this a bug in LVL?
I just got the same problem, and with your update and zapl's comment I figured up that the problem is the emulator you are using.
This Emulators don't have the Google Play APIs, and the LVL can't bind to the service, leaving a connection open, at the end LVL can't close it with the onDestroy call.
Just create a new AVD using Google APIs instead of Android x.x and try your code there, if you don´t find the Google APIs in the Target pulldown when creating the new AVD download it with the Android SDK Manager.
I have also met the same problem later I got to know that i havn't added that android permission com.android.vending.CHECK_LICENSE . After correcting this my was problem is now solved. Try adding this line your android manifest
<uses-permission android:name="com.android.vending.CHECK_LICENSE" />
Just put
mChecker.onDestroy();
on your onDestroymethod of the activity that declares and uses the mChecker.
While Google's code in LicenceChecker looks like this:
public synchronized void onDestroy() {
cleanupService();
mHandler.getLooper().quit();
}
I don't know about google's LicenceChecker, but you should call StopService() before exit the Activity otherwise the service is still running and leaks memory.
Related
Whenever I start the app I want to know if the app recovered from a crash. Can I store it in a flag ?
Do the crash and regular app exit scenario go through the same steps(lifecycle) in android ?
You can override your crash exception by using Thread.setDefaultUncaughtExceptionHandler. But do not forget, If you would not close your application it will freeze the screen by OS.
Example code :
//variable that inside the application class
private Thread.UncaughtExceptionHandler defaultUEH;
public void onCreate(){
super.onCreate();
defaultUEH = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler(){
#Override
public void uncaughtException(Thread t, Throwable e) {
handleUncaughtException(t,e);
defaultUEH.uncaughtException(thread,e);
}
});
}
private void handleUncaughtException(Thread thread,Throwable e){
//do whatever you like!
}
NOTE : There is no way to understand how is your program is opened
You don't get this information at all from the Android SDK. There are two options you could try, first is would be to have extensive logging/tracking of the apps life-cycle. In all of your activities keep track of when you activities are started, resumed, paused, stopped, and destroyed. (Also handle special usecase of when the device is rotated and the activity will experience a tear-down and restart). From here you will have information of when an activity has been stopped and you check the last state in the onCreate, onStart, or onResume of you activities to make sure that you're expected life-cycles where hit. If not, then you more than likely experienced a crash. Also note, on older version of Android certain teardown life-cycle callbacks weren't guaranteed to be called.
Second option would be to try using Thread.setDefaultUncaughtExceptionHandler. I have never personally used it but it may help in the usecase where an uncaught exception occurs. You could log such an event and check that flag once, the app is resumed. I am not sure of all of the side effects of using this mechanism such as, will this override the default uncaught exception behavior and remove the default stack trace that gets printed out, which would be very very very bad.
There is no way for the app to know whether it started from a crash; this is indistinguishable from starting the application for the first time after booting. In both cases you will see the onCreate lifecycle event for your activity.
If your application crashes, it stops processing lifecycle events. So no, lifecycle events will not be processed in the same way.
If you want to know whether your application is crashing, perhaps a better approach is to directly record when the application crashes. There are tools like Errbit that help record this when the application is running on general users' devices.
Try to add Exception handling to the code to whatever is causing a crash.
try{
//code causing the crash
} catch (Exception e){
//code to set flags whenever an event causing crash occurs.
}
I am currently developing an Application for Android. One of the requirements is extensive logging about how the application is used. More specifically there should be logging about when the user closes the app. This logging consists of a server interaction. With respect to that specific requirement I stumbled onto:
Detect Application Exit(1) and Detect application Exit (2)
Both questions have an accepted answer relying on Service#onTaskRemoved(Intent).
In my case however this solution does not seem to work, i.e. AsyncTasks that are started in this method are only occasionally executed. More specifically, the onPreExecute is executed always but the doInBackground is not. I tested this on a Nexus 5 with Android 6 (Marshmallow) installed.
public class SomeService extends Service {
#Override
public IBinder onBind( Intent aIntent ) {
return null;
}
#Override
public void onTaskRemoved(Intent aRootIntent ) {
new DoSomethingTask().executeOnExecutor( Asyntask.THREAD_POOL_EXECUTOR );
}
private static final class DoSomethingTask extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
Log.e( DoSomethingTask.class.getName(), "This is executed always");
}
#Override
protected Void doInBackground( Void... aParams ) {
Log.e( DoSomethingTask.class.getName(), "This appears to be executed only sometimes... ");
// here an actual call to a Rest API should be made to inform the server that the user has closed the application.
}
#Override
protected void onCancelled( Void result ) {
super.onCancelled( result );
Log.e( DoSomethingTask.class.getName(), "Never invoked" );
}
#Override
protected void onCancelled() {
super.onCancelled();
Log.e( DoSomethingTask.class.getName(), "Never invoked" );
}
}
}
Here is an overview of everything I tried in addition to the above code sample:
I have tried various onStartCommand options (START_STICKY, START_NOT_STICKY, etc.) without success.
I have also tried restarting the service in the onTaskRemoved method and then executing the AsyncTask in the onStartCommand.
Starting an IntentService in the onTaskRemoved method (which starts the AsyncTask in its onHandleIntent method) solves the problem neither.
using a BroadcastReceiver in combination with a local broadcast (LocalBroadcastManager#sendBroadcast) does also not work (I double checked that the broadcast receiver is effectively registered as receiver for the sent broadcast).
EDIT:
I have also taken a look at the callbacks in the Application class:
- onTerminate : this method is only invoked in emulated environments and hence useless
- onTrimMemory(int) : this method can be used for detecting when the app goes to the background, but it has no distinct case for when the app exits.
I could keep an activity stack (which would be updated in Activity#onPause(), etc.). But this requires quite a lot of work in every single Activity instead of the above Service approach which only involves interference at a single place.
First of all: in Android you cannot guarantee execution for your requirement. Period. The system is free to gc your classes or kill your process at any time. Also the Android concept does not really have the concept of "closing app" actions the same way websites don't have it. So before you continue reading I urge you to rethink your requirements.
That being said. Here are some tips:
My understanding of Service#onTaskRemoved(Intent) is that it is only executed if you kill the app through task switcher, so I don't know if this is useful to you. In your instance I would keep a activity ref counter in the application object (+1 for every onResume(), -1 for every onPause() of any activity). With this you can check if your user has active UIs. Usually if you pressed back on the last activity that comes as close to the paradigm "closing" an app. Then just start your task at that point from the application object (this will probably be the last to get gc) or if that doesn't work try an unbound service the most uncoupled component you can generate.
Another, very very bad solution is overriding the finalize() method in an object (e.g. your activity). There are only very, very few reasons to use it since it will trigger an additional gc cycle and your code will be run on the main thread, but it is a way to execute code if the object is about to be gc'ed. Therefore it is discouraged to use by the android team, only use it if you have a gun up your head.
Is there any way to know your application is running ?
I want to run a piece of code when Android app is just closed. Any suggestion will be appreciated.
Just to answer my own question now after so much time. When user close the app, the process is terminated with no notice. onDestroy is not guaranteed to be called. only when you explicitly call finish().
I suggest you to make a custom application class and note store the visibility of application wether it is running in background or not.obviously if you don't close the application like this
How to close Android application?
have a look at this so that you don't close it from background and perform the visibility check like this.
public class MyApplication extends Application {
public static boolean isActivityVisible() {
return activityVisible;
}
public static void activityResumed() {
activityVisible = true;
}
public static void activityPaused() {
activityVisible = false;
}
private static boolean activityVisible;
}
and this is how you register you application class to the manifest file.
<application
android:name="your.app.package.MyApplication"
android:icon="#drawable/icon"
android:label="#string/app_name" >
and override these two methods like this.
#Override
protected void onResume() {
super.onResume();
MyApplication.activityResumed();
}
#Override
protected void onPause() {
super.onPause();
MyApplication.activityPaused();
}
now check this status and perform what you like if it is running in background.You can take help of Booleans to check if the application is not closed by other reasons.
In general, there's no such thing as closing applications in Android: the user just stops using the app. It's up to the programmer to make sure that the user does not mention process creation and termination.
Please note that Android may kill the application process when it lacks memory and restart the application later.
For example, one of old office-like apps had the following bug: the user wanted to insert a photo, the office application invoked the Camera app, and Android killed the office app. The office app was not ready for a restart and lost all document changes (which was the bug). Apparently, the buggy app ignored the bundle passed to onCreate().
So the process life cycle and the application life cycle are different things. The process restart is visible to the application: the static variables get reset to their initial values (most likely, null). So it is possible to have a non-null bundle and null static data structures.
One example of executing a piece of code when the process dies may be found below:
Android camera locked after force close .
The problem solved in that post was that Android by itself does not close the camera when the process dies. I cannot tell from your post whether or not your problem is similar to this one.
If you uses, in your Activity, an object derivated from the class: ViewModel, you can capture the event: onCleared(); which is called always, after onDestroy().
See: https://developer.android.com/topic/libraries/architecture/viewmodel
I'm using ACRA in my android application.
But I find that when exception happens within Application#onCreate() method,it only save the report file,rather than raising the dialog to send it.
It there something wrong with my code?
#ReportsCrashes(formKey="")
public class MyAndroidApplication extends Application
{
public void onCreate()
{
ACRAConfiguration config = ACRA.getConfig();
config.setMailTo("test#test.com");
config.setResToastText(R.string.acra_toast);
config.setResDialogText(R.string.acra_dlg_txt);
config.setResDialogCommentPrompt(R.string.acra_dlg_comment_prpmpt);
try
{
config.setMode(ReportingInteractionMode.DIALOG);
}
catch (ACRAConfigurationException e)
{
logger.error("fail to config ACRA", e);
return;
}
ACRA.setConfig(config);
ACRA.init(this);
someMethodThrowsException();
}
}
The onCreate of the Application is called before any Activity is created and does not have a UI, therefore ACRA cannot display a dialog. From the android docs for onCreate
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().
So, be sure to call super.onCreate(), which your example above is missing, and you should not be doing a whole lot in there that would cause exceptions.
I'm seeing two problems with your code.
You don't call super.onCreate() after initializing ACRA
Your class should have tha annotation #Reportscrashes even if the parameters are set at runtime. Otherwise you will get an error in logcat saying ACRA#init called but no ReportsCrashes annotation on Application
Also, I'm not sure if the Application can show a dialog because it has no UI layout associated with it. Toast reporting works fine if you change both points above.
If Java provides Garbage Collection, then what is the need of onDestroy() in Activity Lifecycle?
onDestroy: The final call you receive before your activity is destroyed. This can happen either because the activity is finishing (someone called finish() on it), or because the system is temporarily destroying this instance of the activity to save space.
Here is an example......
public void onDestroy() {
super.onDestroy();
}
OS decides when things "go away." The onDestroy is there to let your app have a final chance to clean things up before the activity does get destroyed but it does not mean that the activity will, in fact, be GCed. Here is a good article that I recommend people to read that relates to creating an exit button. While it's not exactly what you asked about, the concepts will help you understand what's going on.
You can use onDestroy() to finalise the program. I have used it in the code bellow to tell the server that the client is closing its socket to the server so I can notify the user on the server end that the client has disconnected.
client:
...
protected void onDestroy(){
super.onDestroy();
if(connected) {
clientMessage.println("exit");
clientMessage.close();
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
finish();
}
...
server:
...
while (connected) {
input = clientMessage.readLine();
if ("exit".equals(input)){
break;
}
...
}
...
onDestroy() is a method called by the framework when your activity is closing down. It is called to allow your activity to do any shut-down operations it may wish to do. The method doesn't really have anything to do with garbage collection (although your shut-down operations—if any—might involve releasing additional resources that can be gc'ed). In particular, it has nothing to do with C++ destuctors (despite its name).
If you have no shut-down operations to do, you don't need to override it. The base class does essentially nothing.
onDestroy may be called when an activity is destroyed, but you can not count on it. There are situations where the system will simply kill the activity's hosting process without calling this method (or any others) in it, so it should not be used to do things that are intended to remain around after the process goes away.
See: http://developer.android.com/reference/android/app/Activity.html#onDestroy()
In the Android Activity Lifecycle's onDestroy docs:
onDestroy() is called before the activity is destroyed. The system
invokes this callback either because:
the activity is finishing (due to the user completely dismissing the activity or due to finish() being called on the activity), or the
system is temporarily destroying the activity due to a configuration change (such as device rotation or multi-window mode)
The Activity#onDestroy() API docs also answers it quite well:
This method is usually implemented to free resources like threads that are associated with an activity, so that a destroyed activity does not leave such things around while the rest of its application is still running. source
As the quote from the docs say, its for preventing a destroyed activity leaving things around (e.g. memory leaks through referencing, threads), but only when the rest of the app still runs. If the application process ends, it doesn't matter if you forget to clean up threads or other resources since the OS will do it for you. You don't need to override onDestroy.
There is no need to do what sam786 is doing (overriding and just calling the super method) as that is absolutely useless. All other answers seem to go along the lines of "clean up", but don't explain what kind of clean-up or when. You should not be saving any data in onDestroy(), as you can't guarantee it will be called, so you will lose data sometimes. It won't be called when you press the home button, for example (the case where you want data to be saved).
The onDestroy is there to let your app have a final chance to clean things up before the activity does get destroyed
Article Exit Button in Android
It gives your program a chance to do things like cleanup resources (say threads) so that they don't pollute the associated application. If you don't have any use for it, then don't override it.
See:onDestroy()-Android Reference