前几天,在网上总结了一个方法,实现了在Android当前Activity的截图,本人测试确实通过了,不过有朋友说截出来的图是黑色的,不能看。我心想,这没有问题啊,相同的代码我就可以执行通过,并没有没有在意这个问题。可是,今天我再调用那个方法时,截出来的图部分是黑屏。我当时就郁闷了。网上的东西很全,但同时很乱。有一个大神用的是引用Linux下编译出来的库,又用到什么JNI我完全不懂,貌似可以实现截屏。当时这个方法太麻烦,我看了一下觉得没有信心,就又继续寻找其他的方法。

我截图出现黑屏的原因是在Activity中用到了SurfaceView控件,在XML布局中的控件可以完整的显示出来但是有surfaceView的时候就出现黑屏了。具体原因我想的是因为在surfaceView中用线程不停的绘图,操作太频繁了,原来那种方法没有办法截出来。在surfaceView中绘图的原理:

用另外一个Canvas对象不停的把要画到surfaceView中的对象画到这个额外的canvas中,再声明一个Bitmap bitmap对象,注意这个bitmap不是你画在surfaceView中的对象,而是你的目标对象,就是需要截的图。你只需要这样:Canvas canvas=new Canvas(bitmap),接着用canvas.drawBitmap(curBitmap, 0, 0, null),你就可以把当前的的要画的到SurfaceView保存到bitmap中,然后把bitmap保存出来就可以了。PS:这只是截出来SurfaceView中图像,如果想截取背景图片,可以把surfaceView设置为透明。网上有很多种方法,这里就不介绍了。

贴出网上可以运行的代码:

menu.xml:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/screenshot" android:title="@string/screenshot"></item>
</menu>


Element.java

import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;

public class Element {
private float mX;
private float mY;

private Bitmap mBitmap;

public Element(Resources res, int x, int y) {
mBitmap = BitmapFactory.decodeStream(new BufferedInputStream(res.openRawResource(R.drawable.icon)));
mX = x - mBitmap.getWidth() / 2;
mY = y - mBitmap.getHeight() / 2;
}

public void doDraw(Canvas canvas) {
canvas.drawBitmap(mBitmap, mX, mY, null);
}
}

Panel.java

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Environment;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class Panel extends SurfaceView implements SurfaceHolder.Callback
{

public static float mWidth;
public static float mHeight;

private ViewThread mThread;
private ArrayList<Element> mElements = new ArrayList<Element>();
private int mElementNumber = 0;

private Paint mPaint = new Paint();
private String mScreenshotPath = Environment.getExternalStorageDirectory()
+ "/droidnova";

public Panel(Context context)
{
super(context);
getHolder().addCallback(this);
mThread = new ViewThread(this);
mPaint.setColor(Color.WHITE);
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height)
{
mWidth = width;
mHeight = height;
}

@Override
public void surfaceCreated(SurfaceHolder holder)
{
if (!mThread.isAlive())
{
mThread = new ViewThread(this);
mThread.setRunning(true);
mThread.start();
}
}

@Override
public void surfaceDestroyed(SurfaceHolder holder)
{
if (mThread.isAlive())
{
mThread.setRunning(false);
}
}

@Override
public boolean onTouchEvent(MotionEvent event)
{
synchronized (mElements)
{
mElements.add(new Element(getResources(), (int) event.getX(),
(int) event.getY()));
mElementNumber = mElements.size();
}
return super.onTouchEvent(event);
}

/**
* If called, creates a screenshot and saves it as a JPG in the folder
* "droidnova" on the sdcard.
*/
//在surfaceView上不停的绘图
public void doDraw(long elapsed, Canvas canvas)
{
canvas.drawColor(Color.BLACK);
synchronized (mElements)
{
for (Element element : mElements)
{
element.doDraw(canvas);
}
}
canvas.drawText("FPS: " + Math.round(1000f / elapsed) + " Elements: "
+ mElementNumber, 10, 10, mPaint);
}
public void saveScreenshot()
{
if (ensureSDCardAccess())
{
Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(),
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
//在surfaceView上不停的绘图
doDraw(1, canvas);
File file = new File(mScreenshotPath + "/"
+ System.currentTimeMillis() + ".jpg");
FileOutputStream fos;
try
{
fos = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.close();
}
catch (FileNotFoundException e)
{
Log.e("Panel", "FileNotFoundException", e);
}
catch (IOException e)
{
Log.e("Panel", "IOEception", e);
}
}
}

/**
* Helper method to ensure that the given path exists. TODO: check external
* storage state
*/
private boolean ensureSDCardAccess()
{
File file = new File(mScreenshotPath);
if (file.exists())
{
return true;
}
else if (file.mkdirs())
{
return true;
}
return false;
}
}

ScreenshotActivity.java

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.Window;

public class ScreenshotActivity extends Activity {
private Panel mPanel;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
mPanel = new Panel(this);
setContentView(mPanel);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.screenshot:
mPanel.saveScreenshot();
break;
}
return true;
}
}

ViewThread.java

import android.graphics.Canvas;
import android.view.SurfaceHolder;

public class ViewThread extends Thread {
private Panel mPanel;
private SurfaceHolder mHolder;
private boolean mRun = false;
private long mStartTime;
private long mElapsed;

public ViewThread(Panel panel) {
mPanel = panel;
mHolder = mPanel.getHolder();
}

public void setRunning(boolean run) {
mRun = run;
}

@Override
public void run() {
Canvas canvas = null;
mStartTime = System.currentTimeMillis();
while (mRun) {
canvas = mHolder.lockCanvas();
if (canvas != null) {
mPanel.doDraw(mElapsed, canvas);
mElapsed = System.currentTimeMillis() - mStartTime;
mHolder.unlockCanvasAndPost(canvas);
}
mStartTime = System.currentTimeMillis();
}
}
}

其实这很好理解。由于我的代码写在整个项目中,跌出来比较麻烦,就贴了一个以可以完整通过的工程。

下载地址:http://download.csdn.net/detail/yilip/4428045

关于截屏,暂时我的需求已经满足了,不知道这符合其他情况么?欢迎有兴趣的人一起交流。

更多相关文章

  1. 【原】[webkit移动开发笔记]之兼容iPhone4和iPhone5的方法
  2. Android使用AsyncTask实现可以断点续传的DownloadManager功能
  3. android利用httpclient实现post、get请求restful接口进行json和f
  4. android-Activity读书笔记
  5. Android(安卓)AsyncTask 的使用
  6. Qt for Android编译报错提示:Install to device:No Buildfile:bui
  7. Android(安卓)图片平铺效果bitmap
  8. android中Retrofit2.0的封装:设计到请求前后的操作,比如添加请求头
  9. 热更新-Android与Lua相互通信

随机推荐

  1. 培训学web前端前景如何?
  2. 索刻科技CRM用户手册
  3. html基础:table入门
  4. html基础:form表单
  5. php第一课vscode安装
  6. 第二课 课程表与注册表单
  7. HTML Study 01
  8. Mac 终端以及常用终端命令
  9. kubernetes 集群中Flannel的使用说明
  10. HULK运维团队交流分享小记