我正在尝试使用以下代码以编程方式截取顶部运行活动视图,然后我将每个间隔将位图共享到套接字服务器程序。经过长时间的研究,我得到了这段代码。但问题是,这段代码没有采用顶级运行活动(无论我的应用程序中最常运行的活动),而是仅在编写此代码的情况下截取特定活动的屏幕截图。它没有截取正在前台运行的任何活动的屏幕截图。有人可以告诉我,这里可能有什么问题吗?
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);
答案 0 :(得分:1)
getWindow()是Activity的一种方法。每个活动都有一个不同的Window实例。
要查找顶级(前景)活动,请参阅: Android: How can I get the current foreground activity (from a service)?
答案 1 :(得分:0)
有一个非常好的方法来解决这个问题。创建一个类名CommonUtils
并在那里创建一个方法,用于拍摄屏幕截图并将其发送到像这样的流:
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"
>
要在捕获屏幕后显示活动,您可以将主题设置为默认值