以编程方式截取顶级运行活动的屏幕截图

时间:2014-06-14 12:45:45

标签: android

我正在尝试使用以下代码以编程方式截取顶部运行活动视图,然后我将每个间隔将位图共享到套接字服务器程序。经过长时间的研究,我得到了这段代码。但问题是,这段代码没有采用顶级运行活动(无论我的应用程序中最常运行的活动),而是仅在编写此代码的情况下截取特定活动的屏幕截图。它没有截取正在前台运行的任何活动的屏幕截图。有人可以告诉我,这里可能有什么问题吗?

    private Runnable mUpdate = new Runnable() {

        public void run() {

            //ActivityManager mActivityManager = (ActivityManager) getSystemService(Activity.ACTIVITY_SERVICE);
            //List<ActivityManager.RunningTaskInfo> task = mActivityManager.getRunningTasks(1); 
            //ComponentName componentInfo = task.get(0).topActivity;
            //mActivityManager.getRunningTasks(1).get(0).topActivity.
            //View view = getWindow().getDecorView().findViewById(android.R.id.content);
            //getWindow().findViewById(android.R.id.content)


            View view = getWindow().getDecorView().findViewById(android.R.id.content);
            context = getApplicationContext(); 

            try {
               // HERE IS THE SCREENSHOT TAKEN PROGRAMMATICALLY
                bitmap = loadBitmapFromView(context,view);

                //bitmap = takeScreenshot();
                output = ((GlobalClass) RandomIDActivity.this.getApplication()).socket.getOutputStream();
                Log.d("ClientActivity", "C: image writing.");
                ByteArrayOutputStream stream = new ByteArrayOutputStream();
                bitmap.compress(CompressFormat.JPEG, 70, stream);
                byte[] imgbyte = stream.toByteArray();

                String endStr = "END";
                byte[] endByte = endStr.getBytes();

                byte[] finalByteToSend = new byte[imgbyte.length + endByte.length];
                System.arraycopy(imgbyte, 0, finalByteToSend, 0, imgbyte.length);
                System.arraycopy(endByte, 0, finalByteToSend, imgbyte.length, endByte.length);

                output.write(finalByteToSend,0,finalByteToSend.length);
                output.flush();
                imgbyte = null;
                endByte = null;
                finalByteToSend = null;

                }
                catch (Exception ex) {
                    ex.printStackTrace();
                } 

            shareHandler.postDelayed(this, 5000);
        }

        };

在此处提取位图,

public static Bitmap loadBitmapFromView(Context context, View v) {

        DisplayMetrics dm = context.getResources().getDisplayMetrics();

        v.measure(MeasureSpec.makeMeasureSpec(dm.widthPixels, MeasureSpec.EXACTLY),
                MeasureSpec.makeMeasureSpec(dm.heightPixels, MeasureSpec.EXACTLY));

        v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());

        Bitmap returnedBitmap = Bitmap.createBitmap(v.getMeasuredWidth(),
                v.getMeasuredHeight(), Bitmap.Config.ARGB_8888);

        Canvas canvas = new Canvas(returnedBitmap);

        v.draw(canvas);
        return returnedBitmap;
    }

更新代码:

ActivityManager mActivityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);

List<ActivityManager.RunningTaskInfo> task = mActivityManager.getRunningTasks(1); 

String currActivityString = task.get(0).topActivity.getClassName();

try {
            Log.d("currActivityString: ", "currActivityString: " + currActivityString);
            Log.d("Test 1111" , "Test 1111");
            myCurrClass = Class.forName(currActivityString);
            Log.d("Test 2222" , "Test 2222");
            } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            }

            try {
            Log.d("Test 3333" , "Test 3333");
            activityObj = (Activity) myCurrClass.newInstance();
            Log.d("Test 4444" , "Test 4444");
            } catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            }
*// CRASHING IN THIS LINE as Fatal Exception: NullPointerException*
View view = activityObj.getWindow().getDecorView().getRootView();

bitmap = loadBitmapFromView(activityObj,view);

3 个答案:

答案 0 :(得分:1)

getWindow()是Activity的一种方法。每个活动都有一个不同的Window实例。

要查找顶级(前景)活动,请参阅: Android: How can I get the current foreground activity (from a service)?

答案 1 :(得分:0)

有一个非常好的方法来解决这个问题。创建一个类名CommonUtils并在那里创建一个方法,用于拍摄屏幕截图并将其发送到像这样的流:

CommonUtils.java

public static byte[] takeScreenShot(Activity context){
    View view = context.getWindow().getDecorView().getRootView();
    view.setDrawingCacheEnabled(true);
    Bitmap bitmap = Bitmap.createBitmap(view.getDrawingCache());
    view.setDrawingCacheEnabled(false);
    ByteArrayOutputStream stream = new ByteArrayOutputStream();
    bitmap.compress(CompressFormat.JPEG, 70, stream);
    return stream.toByteArray();
    // now that you have the byte array you can send it when ever you want.
}

现在你所要做的就是在你的任何活动中调用这个方法:

CommonUtils.takeScreenShot(MyCurrentActivity.this);

[注意]:您可以使用byte[]

在同一方法内或其他任何地方立即发送

[编辑]:正如您在评论中提到的,您可以获得最佳的活动。存储其实例并在Runnable中进行以下更改:

假设您已将顶级活动的实例存储为topActivity

Activity topActivity = //your top activity;
View view = topActivity.getWindow().getDecorView().getRootView();

您需要在loadBitmapFromView()方法中进行微小的更改:

public static Bitmap loadBitmapFromView(Activity context, View v) {

你不需要改变这个方法中的其余部分。

并在Runnable

中调用此方式
bitmap = loadBitmapFromView(topActivity,view);

希望有所帮助:)

答案 2 :(得分:0)

问题可能与您的屏幕捕获功能无关(我没有检查)。

当您的代码执行时,它成为最热门的活动并截取它的截图。 最好的解决方案我认为让您的活动不可见并截屏,然后在执行您的活动之前获取最佳活动的屏幕截图。

使您的活动不可见应用此样式并检查

style.xml

<?xml version="1.0" encoding="UTF-8"?>
<resources>
    <style name="Invisible" parent="@android:style/Theme">
        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:windowIsTranslucent">true</item>
        <item name="android:windowIsFloating">true</item>
        <item name="android:windowNoTitle">true</item>
        <item name="android:windowContentOverlay">@null</item>
        <item name="android:backgroundDimEnabled">false</item>
    </style>
</resources>

并在AndroidManifet中将此应用于您的活动

<activity
    android:name=".MyActivity"
    android:label="@string/app_name"
    android:theme="@style/Invisible"
>

要在捕获屏幕后显示活动,您可以将主题设置为默认值

也检查一下 How do I create a transparent Activity on Android?