Last active
September 22, 2016 08:32
-
-
Save deskid/c8efca9a04765bc11ec4 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
import android.app.Application; | |
import android.os.Handler; | |
import android.os.Looper; | |
import java.lang.ref.WeakReference; | |
import java.lang.reflect.Field; | |
import java.lang.reflect.InvocationTargetException; | |
import java.lang.reflect.Method; | |
import java.util.concurrent.Semaphore; | |
/** | |
* 反射获取Application变量 | |
*/ | |
public class ApplicationContextProvider { | |
private static volatile ApplicationContextProvider sInstance; | |
private WeakReference<Application> mApplication; | |
private ApplicationContextProvider() { | |
try { | |
if (Thread.currentThread() == Looper.getMainLooper().getThread()) { | |
initApplicationContext(); | |
} else { | |
Class<?> clazz = Class.forName("android.app.ActivityThread"); | |
Field mainHandlerField = clazz.getDeclaredField("sMainThreadHandler"); | |
mainHandlerField.setAccessible(true); | |
Handler mainHandler = (Handler) mainHandlerField.get(null); | |
final Semaphore semaphore = new Semaphore(0); | |
mainHandler.post(new Runnable() { | |
@Override | |
public void run() { | |
try { | |
initApplicationContext(); | |
} catch (ClassNotFoundException e) { | |
e.printStackTrace(); | |
} | |
semaphore.release(); | |
} | |
}); | |
semaphore.acquire(); | |
} | |
} catch (ClassNotFoundException e) { | |
e.printStackTrace(); | |
} catch (InterruptedException e) { | |
e.printStackTrace(); | |
} catch (IllegalAccessException e) { | |
e.printStackTrace(); | |
} catch (NoSuchFieldException e) { | |
e.printStackTrace(); | |
} | |
} | |
public static synchronized ApplicationContextProvider instance() { | |
if (sInstance == null) { | |
sInstance = new ApplicationContextProvider(); | |
} | |
return sInstance; | |
} | |
private void initApplicationContext() throws ClassNotFoundException { | |
Application application = null; | |
try { | |
Class<?> clazz = Class.forName("android.app.ActivityThread"); | |
Method e = clazz.getDeclaredMethod("currentActivityThread"); | |
Object activityThreadInstance = e.invoke(null); | |
Field applicationField = clazz.getDeclaredField("mInitialApplication"); | |
application = (Application) applicationField.get(activityThreadInstance); | |
} catch (NoSuchMethodException e1) { | |
e1.printStackTrace(); | |
} catch (IllegalAccessException e1) { | |
e1.printStackTrace(); | |
} catch (InvocationTargetException e1) { | |
e1.printStackTrace(); | |
} catch (NoSuchFieldException e1) { | |
e1.printStackTrace(); | |
} | |
mApplication = new WeakReference<>(application); | |
} | |
public Application get() { | |
return mApplication == null ? null : mApplication.get(); | |
} | |
} | |
This file contains hidden or 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
/** | |
* 通过反射的方法获取最上层的Activity | |
* @return | |
*/ | |
private Activity getTopActivity() { | |
Activity topActivity = null; | |
try { | |
Class activityThreadClass = Class.forName("android.app.ActivityThread"); | |
Method getATMethod = activityThreadClass.getDeclaredMethod("currentActivityThread"); | |
Field activitiesField = activityThreadClass.getDeclaredField("mActivities"); | |
Object activityThread = getATMethod.invoke(null); | |
activitiesField.setAccessible(true); | |
Object activityClientRecord; | |
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { | |
ArrayMap activites = (ArrayMap) activitiesField.get(activityThread); | |
activityClientRecord = activites.valueAt(0); | |
}else{ | |
HashMap activites = (HashMap) activitiesField.get(activityThread); | |
activityClientRecord = activites.valueAt(0); | |
} | |
Class activityClientRecordClass = Class.forName("android.app.ActivityThread$ActivityClientRecord"); | |
Field activityField = activityClientRecordClass.getDeclaredField("activity"); | |
activityField.setAccessible(true); | |
topActivity = (Activity) activityField.get(activityClientRecord); | |
} catch (ClassNotFoundException e) { | |
e.printStackTrace(); | |
} catch (NoSuchMethodException e) { | |
e.printStackTrace(); | |
} catch (InvocationTargetException e) { | |
e.printStackTrace(); | |
} catch (IllegalAccessException e) { | |
e.printStackTrace(); | |
} catch (NoSuchFieldException e) { | |
e.printStackTrace(); | |
} | |
return topActivity; | |
} | |
@TargetApi(Build.VERSION_CODES.KITKAT) | |
public static Activity getRunningActivity() { | |
try { | |
Class activityThreadClass = Class.forName("android.app.ActivityThread"); | |
Object activityThread = activityThreadClass.getMethod("currentActivityThread") | |
.invoke(null); | |
Field activitiesField = activityThreadClass.getDeclaredField("mActivities"); | |
activitiesField.setAccessible(true); | |
Map activities = (Map) activitiesField.get(activityThread); | |
for (Object activityRecord : activities.values()) { | |
Class activityRecordClass = activityRecord.getClass(); | |
Field pausedField = activityRecordClass.getDeclaredField("paused"); | |
pausedField.setAccessible(true); | |
if (!pausedField.getBoolean(activityRecord)) { | |
Field activityField = activityRecordClass.getDeclaredField("activity"); | |
activityField.setAccessible(true); | |
return (Activity) activityField.get(activityRecord); | |
} | |
} | |
} catch (Exception e) { | |
throw new RuntimeException(e); | |
} | |
throw new RuntimeException("Didn't find the running activity"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment