When I try using the code bellow in the onDestroy() method in MainActivity it seams it does not work. What I am doing wrong?
Code:
#Override
protected void onDestroy() {
super.onDestroy();
deleteCacheData();
}
public void deleteCacheData() {
File cacheDir = this.getCacheDir();
File[] files = cacheDir.listFiles();
if (files != null) {
for (File file : files) {
file.delete();
}
}
}
There is two cases with your code:
You can't reliably depends on the case that onDestroy() method will be called. Because there is no such guarantee that it will always be called by the system. Here the excerpt from onDestroy() documentation:
protected void onDestroy ()
Perform any final cleanup before an 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. You can distinguish between these two scenarios with the isFinishing() method.
Note: do not count on this method being called as a place for saving data! For example, if an activity is editing data in a content provider, those edits should be committed in either onPause() or onSaveInstanceState(Bundle), not here. 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. 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.
Derived classes must call through to the super class's implementation of this method. If they do not, an exception will be thrown.
You should call your deleteCacheData() before calling the super.onDestroy(). So, this is incorrect:
#Override
protected void onDestroy() {
super.onDestroy();
deleteCacheData();
}
this is the correct one:
#Override
protected void onDestroy() {
deleteCacheData();
super.onDestroy();
}
If you using Windows OS
Because In your Windows task manaegr one Process is Running when the android studio start or build run or stop named
Java Jmt first stop it then your can directly delete the both build folder not need to clear cache
Related
Using LeakCanary library in the statement of a memory leak I get encrypted method names. For example:
static hk.o
references ht.a
leaks Activity instance
Can anybody explain this report? Why it not write the names of the methods that I use?
I use the debug version of the code without Proguard.
I (probably) had the same problem. Are you using AdMob/Firebase NativeExpressAdView?
If so, pause and destroy the NativeExpressAdView instances before leaving the activity:
#Overrride
protected void onDestroy() {
mAdView.pause();
mAdView.destroy();
super.onDestroy();
}
When we press this button
We see the apps which we didn't close, like this
But when we want to close an app from this screen (below image), the method onDestroy() isn't called, however the app is closed. I need to call onDestroy() when the app is closed in this way. How can I do this?
As specified in the Android documentation, it is not guaranteed that onDestroy() will be called when exiting your application.
"There are situations where the system will simply kill the activity's hosting process without calling this method"
https://developer.android.com/reference/android/app/Activity.html#onDestroy%28%29
Instead, you can create a service which will be notified when the Task your activities are running inside is destroyed.
Create the service class:
public class ClosingService extends Service {
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
// Handle application closing
fireClosingNotification();
// Destroy the service
stopSelf();
}
}
Declare / register your service in the manifest (within the application tag, but outside any activity tags):
<service android:name=".services.ClosingService"
android:stopWithTask="false"/>
Specifying stopWithTask="false" will cause the onTaskRemoved() method to be triggered in your service when the task is removed from the Process.
Here you can run your closing application logic, before calling stopSelf() to destroy the Service.
You should read some info about Activity lifecycle. There is one thing about onDestroy method, it doesn't get called all time. You mustn't rely on it.
Specify please what are you trying to achive and I'll try to offer better solution.
Suggestion
So, if I understood you right, I can suggest one thing. Start a Service that will fire LocalBroadcast every N seconds (it's not really heavy to system). Register and BroadcastReceiver for this broadcast in Activities. This way you'll get true or false depending on if there is any BroadcastReceiver that can catch your LocalBroadcast. And if no receivers than check for some SharedPreferences value that indicates if Button was pressed.
More promising approach than using a bound service would be using activity lifecycle callbacks in the Application. Though the approach shown in the accepted answer would work but the service would be running in the background until the activity is terminated which is expensive. Instead, I would suggest the use of your implementation of Application.
1) Make a class extending Application, then use it by providing its name in the name attribute of Application tag in Manifest file
class MusicPlayerApplication: Application() {
private val TAG = MusicPlayerApplication::class.java.simpleName
override fun onCreate() {
super.onCreate()
registerActivityLifecycleCallbacks(object: ActivityLifecycleCallbacks {
override fun onActivityPaused(activity: Activity?) {
}
override fun onActivityResumed(activity: Activity?) {
}
override fun onActivityStarted(activity: Activity?) {
}
override fun onActivityDestroyed(activity: Activity?) {
Log.d(TAG, "onActivityDestroyed: ")
val activityName = activity!!.localClassName
}
override fun onActivitySaveInstanceState(activity: Activity?, outState: Bundle?) {
}
override fun onActivityStopped(activity: Activity?) {
}
override fun onActivityCreated(activity: Activity?, savedInstanceState: Bundle?) {
}
})
}
}
AndroidManifest.xml
<application
android:name=".MusicPlayerApplication"
....
I have tested this approach using logcat, my onDestory is not getting called but onActivityDestroyed in the callback is getting called every time I kill the activity from RAM but this doc says that onActivityDestroyed would be called when onDestory of an activity is called but that doesn't seem to happen. However, I find this approach better than using services.
I'm writting my own plug-in for an existing game engine (so to say it's 3rd-party lib in relation to the main application).
So, I have no access to the MainActivity sources.
Nevertheless I have to react somehow on main activity lifecycle events (onCreate, onDestroy, onPause, onResume, onNewIntent and some unimportant others).
Thanks to Application.ActivityLifecycleCallbacks, I have no problems with most of them.
The problem occurs with onNewIntent(). I can't find out a listener for this event and imagine a way to handle it.
Does anybody know how to catch onNewIntent event (surely, except overriding it)?
onNewIntent() works for singleTop or singleTask activities which already run somewhere else in the stack. if the MainActivity is not declared with singleTop or singleTask attributes, even if you use below code, it won't work:
#Override //won't be called if no singleTop/singleTask attributes are used
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
// ...
}
To assure all setup logic hooked, it is best use onResume() by utilizing getIntent().
#Override
protected void onResume() { //will be called in any cases
super.onResume();
// getIntent() should always return the most recent
}
The java and/or XML file seems to reload on wake from pause but I thought #Override would stop that. How do I stop this from happening?
#Override
public void onPause() {
super.onPause();
Playsound2.stop();
}
#Override
public void onResume() {
super.onResume();
SoundManager.getInstance();
SoundManager.initSounds(this);
SoundManager.loadSounds();
}
Perhaps I was unclear. How do I stop the activity restarting on wakeup?
onResume Method will be called every time your activity gets Resumed. if you do not want that, use your code in some method of your own apart from activity because activity methods have a life cycle and they follow the same hierarchy.
#Override means you override the method from the parent class.
onResume is part of the Activity's lifecycle and will be called automatically.
I have an app in which I want to perform lookup some data every, say, 15 mins. I have a service that I start with an alarm, but I also want to make sure that there is a network connection before I start looking.
To do this I think I should use a BroadcastReceiver to watch for changes to the network state. I have wrapped a broadcast receiver to help with this:
public abstract class NetworkMonitor extends BroadcastReceiver
{
boolean mDoingStuff;
public abstract void doStuff();
public NetworkMonitor()
{
mDoingStuff = false;
IntentFilter networkStateFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
MyApp.getContext().registerReceiver(this, networkStateFilter);
}
#Override
public void onReceive(Context context, Intent intent)
{
// network state changes, you can process it, information in intent
ConnectivityManager cn = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = ConnectivityManagerCompat.getNetworkInfoFromBroadcast(cn, intent);
// Only use Wifi Connections for updating this
if (info.isConnectedOrConnecting() && !mDoingStuff)
{
mDoingStuff = true;
doStuff();
}
}
}
I then use that in a service like:
public class WidgetUpdateService extends Service
{
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
// Build the async task to get the data
final MyAsyncTask mTask = new MyAsyncTask();
// Register an interest in when the network changes
new NetworkMonitor(false)
{
public void doStuff()
{
mTask.execute();
}
};
// Make sure that if we get shut down then we get started again correctly.
return START_REDELIVER_INTENT;
}
protected class MyAsyncTask extends AsyncTask<Void, Void, Void>
{
public MyAsyncTask()
{
}
#Override
protected Integer doInBackground(Void... arg0)
{
// do work
}
#Override
protected void onPostExecute(Integer result)
{
WidgetUpdateService.this.stopSelf();
}
#Override
protected void onCancelled(Integer result)
{
WidgetUpdateService.this.stopSelf();
}
}
}
Where MyAsyncTask is an inner class that will cause the service to stopSelf() when it has completed.
This kinda works but:
I'm getting (according to logcat) far more calls to NetworkMonitor.doStuff() than I would expect. It seems that even when the service has been stopped (after the async task has finished correctly) the NetworkMonitor instance is still being receiving intents about changes to the network state. Why is this?
Do I need to have a variable to store the NetworkMonitor() instance in the service, or can I just have an anonymous instance like this? Looking at the docs the BroadcastReceiver should clear itself up after onReceive() has finished.
Why do I need NetworkMonitor.mDoingStuff? I'm guessing that if I can work out why the NetworkMonitor is not clearing itself up after onReceive() has finished then I may not need it any more?
Is this a sensible way of doing this or am I asking for trouble?
Please let me know if you need any more info, I'll be happy to supply it.
This kinda works
It's ghastly code, IMHO.
It seems that even when the service has been stopped (after the async task has finished correctly) the NetworkMonitor instance is still being receiving intents about changes to the network state. Why is this?
Because you never unregister the receiver. It will keep going -- and leaking memory like a sieve -- until your process is terminated.
Do I need to have a variable to store the NetworkMonitor() instance in the service, or can I just have an anonymous instance like this?
You need to have an instance so you can unregister it later. Registration and unregistration of the receiver should be done by the service; your register-the-receiver-in-its-constructor is part of what makes your code ghastly IMHO.
Looking at the docs the BroadcastReceiver should clear itself up after onReceive() has finished
A manifest-registered BroadcastReceiver lives for a single broadcast. A BroadcastReceiver registered via registerReceiver() lives until unregisterReceiver().
Why do I need NetworkMonitor.mDoingStuff?
You have bigger problems.
Is this a sensible way of doing this
Not really.
First, you will crash on your second broadcast, as you cannot execute() an AsyncTask instance multiple times.
Second, see the aforementioned failing-to-unregister issues.
Third, if you want to have a service that does one thing, then goes away, use an IntentService.
So, let's roll all the way back to the top:
I have an app in which I want to perform lookup some data every, say, 15 mins. I have a service that I start with an alarm, but I also want to make sure that there is a network connection before I start looking.
The right way to do this is:
Have your AlarmManager event route to a BroadcastReceiver. This is particularly important if you are using a _WAKEUP alarm type, as such events are only reliable if you use a BroadcastReceiver PendingIntent.
In that BroadcastReceiver, in onReceive(), if you have a network connection, send a command to an IntentService to do the work (and, if you are using a _WAKEUP alarm type, consider my WakefulIntentService, so the device stay awake while you're doing this).
If, instead, there does not appear to be a network connection, have your BroadcastReceiver enable another manifest-registered BroadcastReceiver set up to watch for CONNECTIVITY_ACTION events -- use PackageManager and setComponentEnabledSetting() for this.
In the CONNECTIVITY_ACTION BroadcastReceiver, in onReceive(), if you determine that you now have a network connection, kick off your IntentService (same as what you would do from the AlarmManager receiver if you already had a connection).
In the IntentService/WakefulIntentService, do your work in onHandleIntent(). This already has a background thread and will already call stopSelf() when there is no more work to be done.
In the IntentService/WakefulIntentService, in onDestroy(), disable the CONNECTIVITY_ACTION BroadcastReceiver via PackageManager and setComponentEnabledSetting(), returning you to your original state.
This way:
You don't leak memory, as you are doing here.
You don't have to mess with threading code, as you are doing here.
You don't have to worry about whether or not your process gets kicked out of memory in between the alarm and gaining connectivity.
If connectivity is blocked for some time (e.g., airplane mode), you don't register N receivers and set up N AsyncTasks, as you are doing here. Instead, you will get control again whenever connectivity changes occur in the future after your alarm has gone off.