Some words about me

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas a urna sit amet leo sagittis cursus a at lectus. Donec bibendum facilisis ultricies. Maecenas nec arcu dui, ut lobortis erat. In nec condimentum quam. Vivamus euismod scelerisque ligula vitae fermentum. Nulla dignissim rutrum eleifend.

Donec mi eros, congue ut consectetur eget, pretium vitae orci. Aliquam pharetra ultricies lobortis. Morbi eget nisi lectus. Maecenas felis augue, molestie in vestibulum et, lacinia et leo. Suspendisse potenti. Maecenas eget est augue. Donec tincidunt mollis fermentum.

Contact me?

 
 
 

Donec mi eros, congue ut consectetur eget, pretium vitae orci. Aliquam pharetra ultricies lobortis. Morbi eget nisi lectus. Maecenas felis augue, molestie in vestibulum et, lacinia et leo. Suspendisse potenti. Maecenas eget est augue. Donec tincidunt mollis fermentum.

Send the message
 

截屏 多难未遂

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

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

posted @ 2014-11-19 09:20  Catherine_Brain  阅读(504)  评论(0编辑  收藏  举报