Skip to content

Instantly share code, notes, and snippets.

@jankovd

jankovd/App.java Secret

Last active December 29, 2021 15:50
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jankovd/a210460b814c04d500eb12025902d60d to your computer and use it in GitHub Desktop.
Save jankovd/a210460b814c04d500eb12025902d60d to your computer and use it in GitHub Desktop.
[MIT License] Fixes a leak caused by SemEmergencyManager, see https://github.com/square/leakcanary/issues/762
public class App extends Application {
@Override protected void onCreate(Context context) {
SemEmergencyManagerLeakingActivity.applyFix(this);
}
}
/** Fixes a leak caused by SemEmergencyManager. Tracked at https://github.com/square/leakcanary/issues/762 */
public final class SemEmergencyManagerLeakingActivity implements Application.ActivityLifecycleCallbacks {
private Application application;
private SemEmergencyManagerLeakingActivity(Application application) {
this.application = application;
}
public static void applyFix(Application application) {
if (MANUFACTURER.equals("samsung") && SDK_INT >= KITKAT && SDK_INT <= N) {
application.registerActivityLifecycleCallbacks(new SemEmergencyManagerLeakingActivity(application));
}
}
@Override public void onActivityDestroyed(Activity activity) {
try {
swapActivityWithApplicationContext();
} catch (Exception ignored) {
// the same result is expected on subsequent tries.
}
application.unregisterActivityLifecycleCallbacks(this);
}
private void swapActivityWithApplicationContext()
throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
Class<?> semEmergencyManagerClass = Class.forName("com.samsung.android.emergencymode.SemEmergencyManager");
Field sInstanceField = semEmergencyManagerClass.getDeclaredField("sInstance");
sInstanceField.setAccessible(true);
Object sInstance = sInstanceField.get(null);
Field mContextField = semEmergencyManagerClass.getDeclaredField("mContext");
mContextField.setAccessible(true);
mContextField.set(sInstance, application);
}
@Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) {}
@Override public void onActivityStarted(Activity activity) {}
@Override public void onActivityResumed(Activity activity) {}
@Override public void onActivityPaused(Activity activity) {}
@Override public void onActivityStopped(Activity activity) {}
@Override public void onActivitySaveInstanceState(Activity activity, Bundle outState) {}
}
@okkes
Copy link

okkes commented Dec 12, 2017

So far this seems to fix the issue. :) GJ

@nscherer
Copy link

Do you intend this to be open source? If so, what license is it available under? My understanding is that by default gists are copyrighted, not open source, and may not be reproduced or distributed without permission.

@pcarm
Copy link

pcarm commented Sep 20, 2019

galaxy Note 5 ,The problem still exists

@NathanWA
Copy link

NathanWA commented Mar 4, 2020

If you unregister after one activity is destroyed, does that mean subsequent activities might leak?

@erdemolkun
Copy link

If you unregister after one activity is destroyed, does that mean subsequent activities might leak?

sInstance mContext field is updated with application context. other activities use same instance so does not leak.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment