首页 > 代码库 > 截屏 多难未遂

截屏 多难未遂

     看到未遂,就知道这只是一篇分享感受的文章,但是,或多或少,有过同样过程的人至少会有一点同感。。或有一点思路以及灵感。

     其实网上关于截屏的demo很多,以及思路也很多。我也不知道自己是哪里出了问题,总是未遂。

    但是还是有几个值得注意的:

    不管什么FrameBuffer呀,还是Android源码里面截屏的ScreenShot。。还是ScreenControll。。。and。。。这里要去掏Android更深,更底层或是最原始的都是需要root的。。。但是,本人root真不是很在行。

    开始,我问了很多大神,他们都说Android屏幕绝对来截到。。但是,,,等他们看到我应用的界面的时候,然后我将我的应用代码与他们所说的截屏代码放在一起的时候,oho。。。没戏了。不能,所谓的截屏也只能截到此界面的背影。要不,代码上起,堪忧大神能解不:

    if (null == mContext) {            mContext = getApplicationContext();        }        MyApplication.getInstance().addActivity(this);        webView = new WebView(mContext);        android.view.ViewGroup.LayoutParams params = new LayoutParams(                android.view.ViewGroup.LayoutParams.MATCH_PARENT,                android.view.ViewGroup.LayoutParams.MATCH_PARENT);        webView.setLayoutParams(params);        windowsMan = (WindowManager) getApplicationContext().getSystemService(                Context.WINDOW_SERVICE);        WindowManager.LayoutParams vmParams = new WindowManager.LayoutParams();        // TYPE_PHONE TYPE_SYSTEM_ERROR        vmParams.type = LayoutParams.TYPE_SYSTEM_ERROR;        vmParams.format = PixelFormat.RGBX_8888;        vmParams.flags = LayoutParams.FLAG_NOT_FOCUSABLE                | LayoutParams.FLAG_NOT_TOUCHABLE;        vmParams.gravity = Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL;        vmParams.x = 0;        vmParams.y = 0;        vmParams.width = WindowManager.LayoutParams.MATCH_PARENT;        vmParams.height = WindowManager.LayoutParams.MATCH_PARENT;        if (webView.getParent() == null) {            windowsMan.addView(webView, vmParams);        }

当当。。能知道是什么原因阻碍了我们的截屏吗?bingo,就是WindowManager,我用的是系统谈错误消息的那一层,如果我没有记错的话,这应该是窗口的第一层,而且,我还用了not touch这个属性,也就是这个界面只要我没让他死亡,你是拿他无可奈何的,他会一直浮在界面的上层。。遮盖了其他的界面。所以,若果大神不小心看见了,然后会解的话。。。。希望不吝赐教哦!

当然,我们往往截屏会使用一种很简单的方法,如果截屏在此次任务中没有显得那么重要的话。

    private void CutImage() {        cur_Time = System.currentTimeMillis() / 1000;        if (null == isSdcard()) {            Toast.makeText(this, "内存卡不存在", Toast.LENGTH_SHORT).show();        } else {            Path = isSdcard() + fileName;            String SavePath = Path + mId + "_" + cur_Time + ".jpg";            bmp = shot();            File pathFile = new File(Path);            if (!pathFile.exists()) {                System.out.println("mkdir");                pathFile.mkdir();            }            File file = null;            try {                file = new File(SavePath);                if (!file.exists()) {                    file.createNewFile();                    System.out.println("createNewFile");                }            } catch (Exception e) {                e.printStackTrace();            }            FileOutputStream fos = null;            try {                fos = new FileOutputStream(file);            } catch (Exception e) {                // TODO Auto-generated catch block                e.printStackTrace();            }            if (null != fos) {                bmp.compress(Bitmap.CompressFormat.PNG, 90, fos);                System.out.println("compress");                try {                    fos.flush();                } catch (IOException e) {                    e.printStackTrace();                }                try {                    fos.close();                } catch (IOException e) {                    // TODO Auto-generated catch block                    e.printStackTrace();                }            } else {            }        }    }    /**     * 截屏方法     *      * @return     */    private Bitmap shot() {        View view = getWindow().getDecorView();        Display display = this.getWindowManager().getDefaultDisplay();        view.layout(0, 0, display.getWidth(), display.getHeight());        view.setDrawingCacheEnabled(true);// 允许当前窗口保存缓存信息,这样getDrawingCache()方法才会返回一个Bitmap        Bitmap bmp = Bitmap.createBitmap(view.getDrawingCache());        return bmp;    }    /**     * 先判断是否有SD卡     * */    private String isSdcard() {        File sdcardDir = null;        boolean isSDExist = Environment.getExternalStorageState().equals(                Environment.MEDIA_MOUNTED);        if (isSDExist) {            // 如果存在SDcard 就找到跟目录            sdcardDir = Environment.getExternalStorageDirectory();            return sdcardDir.toString();        } else {            return null;        }    }

上面的就是一个得到截屏,然后保存的写法,下面这个可以选择去掉标题栏。

   import java.io.File;  import java.io.FileNotFoundException;  import java.io.FileOutputStream;  import java.io.IOException;     import android.app.Activity;  import android.graphics.Bitmap;  import android.graphics.Rect;  import android.view.View;     public class ScreenShot {         private static Bitmap takeScreenShot(Activity activity) {          // View是你需要截图的View          View view = activity.getWindow().getDecorView();          view.setDrawingCacheEnabled(true);          view.buildDrawingCache();          Bitmap b1 = view.getDrawingCache();             // 获取状态栏高度          Rect frame = new Rect();          activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);          int statusBarHeight = frame.top;             // 获取屏幕长和高          int width = activity.getWindowManager().getDefaultDisplay().getWidth();          int height = activity.getWindowManager().getDefaultDisplay()                  .getHeight();          // 去掉标题栏          Bitmap b = Bitmap.createBitmap(b1, 0, statusBarHeight, width, height                  - statusBarHeight);          view.destroyDrawingCache();          return b;      }         private static void savePic(Bitmap b, File filePath) {          FileOutputStream fos = null;          try {              fos = new FileOutputStream(filePath);              if (null != fos) {                  b.compress(Bitmap.CompressFormat.PNG, 100, fos);                  fos.flush();                  fos.close();              }          } catch (FileNotFoundException e) {              // e.printStackTrace();          } catch (IOException e) {              // e.printStackTrace();          }      }         public static void shoot(Activity a, File filePath) {          if (filePath == null) {              return;          }          if (!filePath.getParentFile().exists()) {              filePath.getParentFile().mkdirs();          }          ScreenShot.savePic(ScreenShot.takeScreenShot(a), filePath);      }  }

 

以上两个代码都差不多而已。

所以,当我选择想要放弃截取当前这个应用的时候,想要自己打开一个服务,然后再后台定时扑捉界面,然后保存到一个我给定的目录下面,以便我能确认。所以,就动手在网上搜了一大堆关于标签是“android中实现后台截屏”,结果,得知的基本上是手机需要root或者这个程序需要root。我是哭的心都有了。本人自知自己水平连菜鸟都还不如,怎么会很快的吧程序给root了呢?说道root,曾经我也是试过很多方法。什么为了编译源码,使用NDK,什么在注册文件里面添加哈桑UId属性啦,或者在Android.mk里面添加

LOCAL_CERTIFICATE := platform

这样一句话呀,我算是折腾呀。但是,程序员就这宿命。

Notice:以前我一直认为,Android.mk需要每次把自己root权限的项目亲自给生成。但是,后来,我请教了一个我认为是大神的人,他告诉我,Android.mk可以直接从其他项目里面给copy过来。只要改几个地方就okay。嘿嘿

只要将:

LOCAL_PACKAGE_NAME 

给一个给自己本项目的name即可,没什么特殊要求。不知道我理解错没。

后来知道原来,Android‘一直默默在底层安装了一个缓存帧的小把戏。。呵呵,那就是FrameBuffer,但是,知道了又怎么样呢。因为这个还是需要一个root了的手机。而且,现在手机的多样化以及很多喜欢自己改装,所以导致FrameBuffer花屏呀,或者是他缓存的路径不对("/dev/graphics/fb0")都是可能的。

但是,还是为了能方便起见,还是把代码给出来吧。在我的文件里面的“FrameBuffer截屏.jar”里面也可以直接给看到:

当然,这里会有更直接的链接,我觉得够料哦!

http://pan.baidu.com/s/1jG43QfW

然后哦还有基于源码的截屏,我也直接给链接了吧:

http://blog.csdn.net/buptgshengod/article/details/21958183

当然,这里还有SurfaceControl.java的链接:

http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.4_r1/android/view/SurfaceControl.java/

有时候下载一个关于什么的资料或者Demo真够费我的小币的。所以,这里有一些关于截屏的demo:我给出了链接:

http://pan.baidu.com/s/1o6HSXOQ

。。。先就将这些外界来的信息写到这里吧。

毕竟我想要的是一个可以直接启动一个服务,然后来在后台打开这个程序的,然后运行截屏的。然后就考虑了一个不用root权限的。也就是DDMS原理的。但是也跟网上有朋友交流过,他们说这个方法行不通。但是,还是写了,但是。。。。在导入jar包的时候,总是报一个让我无法理解的错误。

[2014-11-19 01:08:39 - TakeSrenn] Conversion to Dalvik format failed with error 1

这个错误真的是让我无法理解。网上也查了很多,除了我没哟升级SDK外,其余的都检查了。而且,我觉得我的SDK已经可以不用升级了。

还有这里需要的dt.jar已经rt.jar都在jdk以及jre下面就可以找到。

但是就是这个dt.jar和rt.jar导入就报这样的错误。ddmlib.jar都不会引起。

这里还是把这个给贴出来。后台开启一个程序,然后定时去执行截屏。但是添加三面提到的三个包就okay。小人算是未遂了·。希望能有大神指点迷津。。

现有一个主类,用来启动服务:

package com.lhl.startservice;import java.io.File;import java.io.FileOutputStream;import com.lhl.service.StartService;import android.app.Activity;import android.content.Intent;import android.graphics.Bitmap;import android.graphics.Bitmap.Config;import android.os.Bundle;import android.os.Environment;import android.os.Handler;import android.os.Message;import android.util.Log;import android.view.Display;import android.view.Menu;import android.view.MenuItem;import android.view.View;import android.view.WindowManager;import android.widget.Button;import android.widget.Toast;/** *  * 主界面 * @author Catherine * */public class MainActivity extends Activity {    private Handler handler = new Myhandler();    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        initView();    }    private void initView() {        Intent in = new Intent(MainActivity.this, StartService.class);        startService(in);        finish();    }    private class Myhandler extends Handler {        @Override        public void handleMessage(Message msg) {            Toast.makeText(MainActivity.this, "接受了 消息", 0).show();            super.handleMessage(msg);        }    }    public void GetandSaveCurrentImage() {        WindowManager widowManager = getWindowManager();        Display display = widowManager.getDefaultDisplay();        int w = display.getWidth();        int h = display.getHeight();        Bitmap Bmp = Bitmap.createBitmap(w, h, Config.ARGB_8888);        View decorview = this.getWindow().getDecorView();        decorview.setDrawingCacheEnabled(true);        Bmp = decorview.getDrawingCache();        try {            String SavePath = getSDCardPath() + "/ScreenImage";            File path = new File(SavePath);            String filepath = SavePath + "/Screen_1.jpg";            File file = new File(filepath);            if (!path.exists()) {                path.mkdirs();            }            if (!file.exists()) {                file.createNewFile();            }            FileOutputStream fos = null;            fos = new FileOutputStream(file);            if (null != fos) {                Bmp.compress(Bitmap.CompressFormat.PNG, 90, fos);                fos.flush();                fos.close();                Log.i("LW", "截屏文件已保存至SDCard/ScreenImage/下");                Message m = handler.obtainMessage();                handler.sendMessage(m);            }        } catch (Exception e) {            e.printStackTrace();        }    }    private String getSDCardPath() {        File sdCardDir = null;        boolean sdcardExit = Environment.getExternalStorageState().equals(                android.os.Environment.MEDIA_MOUNTED);        if (sdcardExit) {            sdCardDir = Environment.getExternalStorageDirectory();        }        return sdCardDir.toString();    }}

 

然后一个服务打开:

package com.lhl.service;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.util.Timer;import java.util.TimerTask;import com.android.ddmlib.AdbCommandRejectedException;import com.android.ddmlib.AndroidDebugBridge;import com.android.ddmlib.IDevice;import com.android.ddmlib.RawImage;import com.android.ddmlib.TimeoutException;import com.lhl.application.GetApplication;import android.app.Service;import android.content.Intent;import android.graphics.Bitmap;import android.graphics.Bitmap.Config;import android.os.Environment;import android.os.IBinder;import android.util.Log;import android.view.Display;import android.view.View;import android.view.WindowManager;/** *  * 开启一个服务 * @author Catherine * */public class StartService extends Service {    @Override    public IBinder onBind(Intent intent) {        // TODO Auto-generated method stub        return null;    }    @Override    @Deprecated    public void onStart(Intent intent, int startId) {        // TODO Auto-generated method stub        super.onStart(intent, startId);    }    @Override    public void onCreate() {        // TODO Auto-generated method stub        super.onCreate();    }    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        new Timer().schedule(new TimerTask() {            @Override            public void run() {                // TODO Auto-generated method stub                System.out.println("123");                /**                 * 被注释的这个方法 可以截屏 指定的 某个界面                 */                // GetandSaveCurrentImage() ;                CunCrruntPage();            }            private void CunCrruntPage() {//                try {                    IDevice device;                    AndroidDebugBridge bridge = AndroidDebugBridge                            .createBridge();                    waitDeviceList(bridge);//                    IDevice devices[] = bridge.getDevices();                    device = devices[0];//                    RawImage rawScreen = device.getScreenshot();//                    if (rawScreen != null) {//                        BufferedImage image = null;//                        boolean landscape = false;//                        int width2 = landscape ? rawScreen.height//                                : rawScreen.width;//                        int height2 = landscape ? rawScreen.width//                                : rawScreen.height;//                        if (image == null) {//                            image = new BufferedImage(width2, height2,//                                    BufferedImage.TYPE_INT_RGB);//                        } else {//                            if (image.getHeight() != height2//                                    || image.getWidth() != width2) {//                                image = new BufferedImage(width2, height2,//                                        BufferedImage.TYPE_INT_RGB);//                            }//                        }//                        int index = 0;//                        int indexInc = rawScreen.bpp >> 3;//                        for (int y = 0; y < rawScreen.height; y++) {//                            for (int x = 0; x < rawScreen.width; x++, index += indexInc) {//                                int value = http://www.mamicode.com/rawScreen.getARGB(index);>//                                if (landscape)//                                    image.setRGB(y, rawScreen.width - x - 1,//                                            value);//                                else//                                    image.setRGB(x, y, value);//                            }//                        }//                        // ImageIO.write((RenderedImage)image,"PNG",new//                        // File("D:/temp.jpg"));////                        String SavePath = getSDCardPath() + "/ScreenImage";//                        File path = new File(SavePath);//                        String filepath = SavePath + "/Screen_1.jpg";//                        File file = new File(filepath);//                        if (!path.exists()) {//                            path.mkdirs();//                        }//                        if (!file.exists()) {//                            file.createNewFile();//                        }//                        ImageIO.write((RenderedImage) image, "PNG", file);////                        Log.i("LW", "截屏文件已保存至SDCard/ScreenImage/下");//                    }////                } catch (TimeoutException e) {//                    // TODO Auto-generated catch block//                    e.printStackTrace();//                } catch (AdbCommandRejectedException e) {//                    // TODO Auto-generated catch block//                    e.printStackTrace();//                } catch (IOException e) {//                    // TODO Auto-generated catch block//                    e.printStackTrace();//                }            }        }, 5000);        return super.onStartCommand(intent, flags, startId);    }    private static void waitDeviceList(AndroidDebugBridge bridge) {        int count = 0;        while (bridge.hasInitialDeviceList() == false) {            try {                Thread.sleep(100); // 如果没有获得设备列表,则等待                count++;            } catch (InterruptedException e) {            }            if (count > 300) {                // 设定时间超过300×100 ms的时候为连接超时                System.err.print("Time out");                break;            }        }    }    @Override    public void onDestroy() {        // TODO Auto-generated method stub        super.onDestroy();    }    public void GetandSaveCurrentImage() {        WindowManager widowManager = (WindowManager) getSystemService(getApplicationContext().WINDOW_SERVICE);        Display display = widowManager.getDefaultDisplay();        int w = display.getWidth();        int h = display.getHeight();        Bitmap Bmp = Bitmap.createBitmap(w, h, Config.ARGB_8888);        View decorview =GetApplication.getMain().getWindow().getDecorView();        decorview.setDrawingCacheEnabled(true);        Bmp = decorview.getDrawingCache();        try {            String SavePath = getSDCardPath() + "/ScreenImage";            File path = new File(SavePath);            String filepath = SavePath + "/Screen_1.jpg";            File file = new File(filepath);            if (!path.exists()) {                path.mkdirs();            }            if (!file.exists()) {                file.createNewFile();            }            FileOutputStream fos = null;            fos = new FileOutputStream(file);            if (null != fos) {                Bmp.compress(Bitmap.CompressFormat.PNG, 90, fos);                fos.flush();                fos.close();                Log.i("LW", "截屏文件已保存至SDCard/ScreenImage/下");            }        } catch (Exception e) {            e.printStackTrace();        }    }    private String getSDCardPath() {        File sdCardDir = null;        boolean sdcardExit = Environment.getExternalStorageState().equals(                android.os.Environment.MEDIA_MOUNTED);        if (sdcardExit) {            sdCardDir = Environment.getExternalStorageDirectory();        }        return sdCardDir.toString();    }}

 

最后这个只是aoolication:

package com.lhl.application;import com.lhl.startservice.MainActivity;import android.app.Application;/** *  * 用来锁定当前的application *  * @author Catherine * */public class GetApplication extends Application {    private static MainActivity main;    public static MainActivity getMain() {        return main;    }    public static void setMain(MainActivity main) {        GetApplication.main = main;    }}

 

这里给出链接,也可以直接下载源码,或者在我的文件里面也有下载。

http://pan.baidu.com/s/1pJ7H1Nl

截屏 多难未遂