Last active
April 9, 2018 12:43
-
-
Save andaag/b05ab66ed0f06167d6e0 to your computer and use it in GitHub Desktop.
workaround for shareactionprovider leak
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package no.finn.android.ui.objectpage; | |
import java.lang.reflect.InvocationTargetException; | |
import java.lang.reflect.Method; | |
import android.content.Context; | |
import android.content.Intent; | |
import android.support.v7.internal.widget.ActivityChooserModel; | |
import android.widget.ShareActionProvider; | |
public class SharedActionProviderMemoryLeakHack { | |
private static Class activityChooserModel = null; | |
private static Method activityChooserGetMethod = null; | |
public static void fix(Context context, ShareActionProvider actionProvider) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { | |
actionProvider.setOnShareTargetSelectedListener(new ShareActionProvider.OnShareTargetSelectedListener() { | |
@Override | |
public boolean onShareTargetSelected(ShareActionProvider source, Intent intent) { | |
return false; | |
} | |
}); | |
ActivityChooserModel dataModel = ActivityChooserModel.get(context, ShareActionProvider.DEFAULT_SHARE_HISTORY_FILE_NAME); | |
dataModel.setOnChooseActivityListener(new ActivityChooserModel.OnChooseActivityListener() { | |
@Override | |
public boolean onChooseActivity(ActivityChooserModel host, Intent intent) { | |
return false; | |
} | |
}); | |
fixInternalClass(context); | |
} | |
private static void fixInternalClass(Context context) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { | |
/* | |
Android 5.x seems to use the internal activityChooserModel | |
*/ | |
if (activityChooserGetMethod == null) { | |
activityChooserModel = Class.forName("android.widget.ActivityChooserModel"); | |
activityChooserGetMethod = activityChooserModel.getMethod("get", new Class[]{Context.class, String.class}); | |
} | |
Object activityChooserObject = activityChooserGetMethod.invoke(null, new Object[]{context, ShareActionProvider.DEFAULT_SHARE_HISTORY_FILE_NAME}); | |
for (Method method : activityChooserModel.getMethods()) { | |
if (method.getName().equals("setOnChooseActivityListener")) { | |
method.invoke(activityChooserObject, new Object[]{null}); | |
break; | |
} | |
} | |
} | |
} | |
From testing with LeakCanary, I've found that the fixInternalClass
used onStop
of any activity that uses the SharedActionProvider
is sufficient for the latest versions of the support library.
public class SharedActionProviderContextLeak {
public static void patch(Context context) {
try {
fixShareActionProvider(context);
} catch (ClassNotFoundException ignored) {
} catch (NoSuchMethodException ignored) {
} catch (InvocationTargetException ignored) {
} catch (IllegalAccessException ignored) { }
}
@SuppressWarnings({"RedundantArrayCreation", "unchecked", "PrivateApi"})
private static void fixShareActionProvider(Context context) throws ClassNotFoundException,
NoSuchMethodException,
InvocationTargetException,
IllegalAccessException {
/*
Android 5.x seems to use the internal activityChooserModel
*/
Class activityChooserModel = Class.forName("android.widget.ActivityChooserModel");
Method activityChooserGetMethod = activityChooserModel.getMethod("get", new Class[]{Context.class, String.class});
Object activityChooserObject = activityChooserGetMethod.invoke(null,
new Object[] { context, ShareActionProvider.DEFAULT_SHARE_HISTORY_FILE_NAME });
for (Method method : activityChooserModel.getMethods()) {
if (method.getName().equals("setOnChooseActivityListener")) {
method.invoke(activityChooserObject, new Object[]{null});
break;
}
}
}
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Also, Android Studio 2.1 doesn't resolve the import for
import android.support.v7.internal.widget.ActivityChooserModel;