Skip to content

Instantly share code, notes, and snippets.

@stuartjmoore
Created July 7, 2012 16:44
Show Gist options
  • Save stuartjmoore/3067159 to your computer and use it in GitHub Desktop.
Save stuartjmoore/3067159 to your computer and use it in GitHub Desktop.
Help me get thumbnails from Android's running apps?
/*
* This code doesn't work, I'm hoping for some help.
*
* I'm trying to use reflection to dig into Android's @hide classes that store screenshots
* of the currently running apps.
*
* The code compiles and runs perfectly, but mThumbnailReceiver is never called back with
* the bitmaps.
*
* I've never done Android development before (I'm an iOS dev) but I'd love to get this
* (or any other thumbnail code) to work for a personal project I'm starting. Any and all
* help is welcome.
*
* I've spent hours on Google looking for other people who've done the same thing, no one
* has without modifying their ROM.
*
* Google's working source code for reference
* The recent tasks app calling the thumbnails: http://androidxref.com/4.0.4/xref/frameworks/ex/carousel/test/src/com/android/carouseltest/TaskSwitcherActivity.java#245
*
* The callback it uses: http://androidxref.com/4.0.4/xref/frameworks/ex/carousel/test/src/com/android/carouseltest/TaskSwitcherActivity.java#167
*
* The IThumbnailReceiver class: http://code.google.com/p/coffee/source/browse/trunk/froyo/android/android/app/IThumbnailReceiver.java?r=392
*/
try
{
ActivityManager am = (ActivityManager)this.getSystemService(ACTIVITY_SERVICE);
Class IThumbnailReceiver = Class.forName("android.app.IThumbnailReceiver");
Class StubClass = Class.forName("android.app.IThumbnailReceiver$Stub");
java.lang.reflect.Constructor stub = StubClass.getConstructor();
Object mThumbnailReceiver = java.lang.reflect.Proxy.newProxyInstance(IThumbnailReceiver.getClassLoader(), new java.lang.Class[]{IThumbnailReceiver}, new java.lang.reflect.InvocationHandler()
{
@Override
public Object invoke(Object proxy, java.lang.reflect.Method method, Object[] args) throws java.lang.Throwable
{
Log.d(LOG_TAG, "invoke method: " + method.getName());
String method_name = method.getName();
Class<?>[] classes = method.getParameterTypes();
if(method_name.equals("finished"))
{
}
else if(method_name.equals("newThumbnail"))
{
Bitmap bitmap = (Bitmap)args[1];
int w = bitmap.getWidth();
int h = bitmap.getHeight();
Log.d(LOG_TAG, "New thumbnail for id=" + args[0] + ", dimensions=" + w + "x" + h + " description '" + args[2] + "'");
}
else if(method_name.equals("asBinder"))
{
}
return null;
}
});
Class c = Class.forName("android.app.ActivityManager");
Class[] args = new Class[3];
args[0] = Integer.TYPE;
args[1] = Integer.TYPE;
args[2] = Class.forName("android.app.IThumbnailReceiver");
java.lang.reflect.Method method = c.getMethod("getRunningTasks", args);
Object[] input = {new Integer(5), new Integer(0), mThumbnailReceiver};
List<ActivityManager.RunningTaskInfo> lru = (List<ActivityManager.RunningTaskInfo>)method.invoke(am, input);
for(ActivityManager.RunningTaskInfo rti : lru)
{
Log.d(LOG_TAG, "LRU: " + rti.topActivity.getClassName());
Bitmap b = rti.thumbnail;
if(b != null)
{
Log.d(LOG_TAG, " Bitmap found: " + b);
}
else
{
Log.d(LOG_TAG, " Bitmap is null");
}
}
}
catch(Exception e)
{
Log.d(LOG_TAG, "Exception" + e);
}
@Tombarr
Copy link

Tombarr commented Oct 8, 2012

Did you ever get this working? I've wanted to do something similar, but couldn't quite figure out how to. From what I know you need use the same API that SystemUI uses, which requires the READ_FRAME_BUFFER permission and that is only available to system apps. But if you've found a way around this I'd love to know.

@xzy2046
Copy link

xzy2046 commented Dec 4, 2013

You need add GET_TASKS permission in your AndroidManifest.xml
and Line 76: Bitmap b = rti.thumbnail; will always be Null. See: http://developer.android.com/reference/android/app/ActivityManager.RunningTaskInfo.html#thumbnail

@ertos12
Copy link

ertos12 commented Jul 10, 2014

Did you solved this issue? I tried this code but i got the null on all apps list. If you solved this issue, can you explain the solution of this issue?

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