截屏 多难未遂

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

其实网上关于截屏的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 = 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

时间: 2024-10-01 02:22:28

截屏 多难未遂的相关文章

Android 7.1.1 系统截屏

frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java TakeScreenshotService.java package com.android.systemui.screenshot; import android.app.Service; import android.content.Intent; import android.os.Handler;

超好用的滚动屏幕截屏工具FastStone Capture

对于超级喜欢整理的技术控,一看到比较好技术文章就想收集下来,单纯的记录网页,又怕作者删除,我只能选择截图,可是有许多文章特别长,直到使用FastStone Capture截图工具,终于可以快速收集这些技术文章了. 1.截图工具是这样的 2.比较好用的滚动截屏使用方法: 图中第六个图标. 1)点击后,可以拖动窗口进行大范围的截图,比如可以将浏览器的网页做为截图对象,截取时,点击选取滚动条箭头就可以完成截图,ESC中断截图滚动! 2)在选定滚动截图图标后还可以按ctrl键进行滚动区域的选择. 3.图

Android自己定义截屏功能,相似QQ截屏

由于公司业务需求 须要对一个屏幕进行截屏.但自带的截屏功能是远远不够项目的功能需求 ,我们是做一个画板软件 .须要的像QQ那样截屏之后 ,能够看到我们自己定义的工具.有画笔,button等等 .android自带的功能非常easy,仅仅须要Intent隐式调用就全然足够了.但他是系统的应用 ,界面固定.无法定制改动.实现方法跟办法有非常多种,以下记录下我实现的方法 .我是这样一个思路 ,重写一个View组件 ,在OnDraw里面仅仅负责不绘图形(包含半透明的四个矩形,亮框矩形,亮框上的四个小圆点

Snipaste强大离线/在线截屏软件的下载、安装和使用

步骤一: https://zh.snipaste.com/  ,去此官网下载. 步骤二:由于此是个绿色软件,直接解压即可. 步骤三:使用,见官网.ttps://zh.snipaste.com  按F1开始截屏 感谢下面哥的精彩微信文章 http://mp.weixin.qq.com/s?__biz=MzIwNzYwODYwMw==&mid=2247483903&idx=1&sn=02121fe920320bbe7b2fae012a18e70a&chksm=970e8f8ba

iOS截屏保存至相册

#pragma mark 截屏并保存至相册 -(void)screenShotsComplete:(void(^)(UIImage * img)) complete { CGSize imageSize = [[UIScreen mainScreen] bounds].size; UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0); CGContextRef context = UIGraphicsGetCurrentContext(

phantomjs介绍-(js网页截屏、javascript网页解析渲染工具)

phantomjs介绍-(js网页截屏.javascript网页解析渲染工具) phantomjs 是一个基于js的webkit内核无头浏览器 也就是没有显示界面的浏览器,这样访问网页就省去了浏览器的界面绘制所消耗的系统资源,比较适合用于网络测试等应用 .利用这个工具,我们可以轻松的搭建一个接口用于获取我们想要的url的整页截屏. PhantomJS is a headless WebKit with JavaScript API. It has fast and native support

Java邮件发送与屏幕截屏

前几天七夕情人节孤独寂寞的程序猿闲来没事,花了一两个小时写了个小Demo主要实现Java的Mail发送功能和桌面截屏功能. 首先让我们先看看Java sendMail邮件发送和桌面屏幕截屏功能是怎么实现的基础知识. 一.Java  SendMail邮件发送 首先让我们来看看邮件发送的原理图: JavaMail 是一套sun 提供开发邮件收发程序API,JavaMail编写程序就是邮件客户端程序(和outlook.foxmail功能类似) * JavaMail开发需要类库 javamail API

Cocos2d-x 3.2 Lua示例 CaptureScreen(截屏)

Cocos2d-x 3.2 Lua示例 CaptureScreen(截屏) 转载请注明:IT_xiao小巫 Cocos2d-x截屏功能是从3.2开始提供的,本篇博客就是介绍Cocos2d-x 3.2中Lua示例中的截屏功能.效果如下所示: 例子代码如下: --[[ 截屏测试 CaptureScreenTest ]]-- -- 获取屏幕大小 local winSize = cc.Director:getInstance():getWinSize() local kTagSprite = 1 loc

Qt实现截屏并保存(转载)

原博地址:http://blog.csdn.net/qinchunwuhui/article/details/52869451?_t_t_t=0.28889142944202306 目前对应用实现截屏的方法还是比较多的,首先我们要了解Qt中的窗口的是如何设计的,不管是MFC下的窗口,还是其他窗口,仿佛都相似,曾经狂学MFC,结果毕业一次没用过已经还给老师,悲催,好了下面我们来介绍一下Qt的窗口设计吧!鸡冻吧-. 1.首先我们来看看我从手册上盗取的图片  我们了解了Qt的窗口框架,让我们来看看她(