Skip to content

Instantly share code, notes, and snippets.

@deskid
Last active September 22, 2016 08:32
Show Gist options
  • Save deskid/c8efca9a04765bc11ec4 to your computer and use it in GitHub Desktop.
Save deskid/c8efca9a04765bc11ec4 to your computer and use it in GitHub Desktop.
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();
}
}
/**
* 通过反射的方法获取最上层的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