android截屏代码实现方法
最近由于项目需要,在学习android系统。android是一个基于linux的专门针对手机平台的操作系统。当然,现在的android 3似乎也将进入平板电脑的市场。由于至今为止,大部分的智能手机采用的是ARM的硬件平台,因此android本身对ARM的平台进行了全面的支持,从源代码中可以看出,也在逐步加入对x86平台的支持,暂时没有看到第三个平台的身影。
这篇文章是我对android系统认识的一个总结,同时介绍一下我至今为止发现的获取屏幕图像数据的方法。经过一定的搜索,我发现方法有很多种,而实现效果会有所差别。其中,有通过最顶层的Android SDK进行截屏,也可以通过C直接读取framebuffer实现。由于framebuffer的方法网上虽然有很多,但是很多我认为并没有写的十分清楚,特别是在编译的方法上,没有找到很好的文章,可能是因为自己找的不够,或者android本身就在不断发展。对此,我在最后给出了一个Android Native Programming的Hello World Howto,需要先到github上mirror下来Android的源代码(2.多G),里边将会带所有的编译器和Emulator等工具。
1 android之我的粗浅理解
android的版本号很有意思,一个版本号对应一个API Level(比如android 2.3.3则对应Android API Level 10)。写这篇文章的时候,最新的android版本号为3.1,而API Level为12。
学习android,首先需要了解的是其系统框架。如下图所示:
android操作系统框架图
这个图在网上比比皆是,这里还是贴了一下,因为的确可以比较好的描述这个系统。它的最底层是linux的内核,只有这一层是工作在内核级的,其余三层都是工作在用户级的。这里,android也不是使用的标准的linux内核,而是一个经过了裁剪,并添加了一些特定功能的内核。其中一个让我记得的比较有意思的feature是,android内核中会有一个叫做Low Memory Killer的驱动,它的主要功能是在系统缺少内存的情况下,杀死进程。显然,我们平时的电脑中,往往不是很需要这个东西;而在手机中,由于资源十分有限,缺少内存的现象或许会发生的非常频繁,这个功能似乎就显得十分重要了(或许还有一个原因是手机没有虚拟内存?毕竟它是用Flash作为长期存储介质,而Flash的特性似乎并不适合作为虚拟内存来使用)。我想这是android针对手机定制进行优化的一个很好的例子。
第二层就是所谓的Native层,由C/C++实现。如果熟悉ARM的应用程序开发的话,我理解这一层就是ARM平台的应用开发层。我们仍然可以用一个类似arm-linux-gcc的交叉编译工具对C程序进行编译(这里是arm-linux-androideabi-gcc)进行编译,具体的方法一会详细介绍。而在这一层,系统给我们提供的库可是比较少的,往往就是最基本的libc等(从提供的可用C基础库来看,数量上肯定是android<ARM<x86/64)。随着android的发展,提供的库也在不断增多。详细的关于Native API的信息需要参考Android NDK Dev Guide文档中有关Stable API的部分。这一层还有一个最核心的东西,就是Dalvik虚拟机。我想,android的核心就是这个虚拟机(或者可以说:Java的核心就是虚拟机?简直是废话!而虚拟机的核心是Portable,即可移植)。
第三层由Java实现,是Android SDK的核心,是android最上层的框架。所有的Android SDK的接口我想就是在这一层实现的了。
最上面就不说了,我们基于android SDK使用Java开发出来的东西应该都在这了。
因为我之前对通用ARM平台有一定的了解,而android也是一个ARM平台,但是比较特殊。让我用我现在的理解来对android总结一下的话:Android=(ARM平台)+(针对手机平台的定制)+(Dalvik虚拟机核心 & Android SDK)。
2 开发平台搭建
在android平台下,我想有三个开发内容。第一个,就是最好入门、最常见的应用程序开发了(也就是我们所说的基于SDK的开发),我们需要搭建一个SDK的环境,还需要懂得Java语言。如何搭建我就不说了,来看看这里吧!另外两个,一个就是ative代码的开发(比如,用C写一个native库,通过JNI给Java调用,或者直接写一个native application),还一个就是牛人们才能搞定的android源代码开发了(我短期恐怕是入不了门了),这些工作都最好搞到android的source tree比较好(这里也包括了所谓的NDK,也就是Native Development Kit)。方法我也不说了,来看这里!
基本的实验方法,SDK在上面的developer网站上写的很详细,有一个HelloWorld的demo,走一遍肯定就知道了。一会我会给出一个利用NDK开发的helloworld。
3 截屏方法种种
是的,让我们开始截屏吧!这里我截屏的环境都是在Android Emulator中(这个基于qemu的模拟器在Android SDK和NDK中都有提供)
3.1 基于Android SDK的截屏方法
主要就是利用SDK提供的View.getDrawingCache()方法。网上已经有很多的实例了。首先创建一个android project,然后进行Layout,画一个按键(res/layout/main.xml):
<? xml version = "1.0" encoding = "utf-8" ?>
< LinearLayout xmlns:android = "http://schemas.android.com/apk/res/android"
android:orientation = "vertical"
android:layout_width = "fill_parent"
android:layout_height = "fill_parent"
>
< TextView
android:layout_width = "fill_parent"
android:layout_height = "wrap_content"
android:text = "@string/hello"
/>
< Button
android:text = "NiceButton"
android:id = "@+id/my_button"
android:layout_width = "fill_parent"
android:layout_height = "wrap_content"
android:layout_alignParentBottom = "true" ></ Button >
</ LinearLayout >
|
HelloAndroid.java实现代码为:
package com.example.helloandroid;
import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import android.app.Activity;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class HelloAndroid extends Activity {
private Button button;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
this .setContentView(R.layout.main);
this .button = (Button) this .findViewById(R.id.my_button);
this .button.setOnClickListener( new OnClickListener() {
public void onClick(View v) {
SimpleDateFormat sdf = new SimpleDateFormat(
"yyyy-MM-dd_HH-mm-ss" , Locale.US);
String fname = "/sdcard/" + sdf.format( new Date()) + ".png" ;
View view = v.getRootView();
view.setDrawingCacheEnabled( true );
view.buildDrawingCache();
Bitmap bitmap = view.getDrawingCache();
if (bitmap != null ) {
System.out.println( "bitmap got!" );
try {
FileOutputStream out = new FileOutputStream(fname);
bitmap.compress(Bitmap.CompressFormat.PNG, 100 , out);
System.out.println( "file " + fname + "output done." );
} catch (Exception e) {
e.printStackTrace();
}
} else {
System.out.println( "bitmap is NULL!" );
}
}
});
}
}
|
这个代码会在按下app中按键的时候自动在手机的/sdcard/目录下生成一个时间戳命名的png截屏文件。
这种截屏有一个问题,就是只能截到一部分,比如电池指示部分就截不出来了。
3.2 基于Android ddmlib进行截屏
这种方法网上有很多相关资料。我也没有测试过,此处略过。
3.3 Android本地编程(Native Programming)读取framebuffer
这是我现在使用的方法。它的优点是整个屏幕都可以截下来,同时不需要写JNI,也不需要Java层的实现。而且如果是emulator的话,也可以直接用adb来操作,十分方便(其实,有一个库android-screenshot-lib应该实现了类似的功能,但是我尝试了一下没有截图成功,图片大小不正确,且是黑屏。就没有进一步尝试了)。
3.3.1 Android的framebuffer介绍
framebuffer是linux内核对显示的最底层驱动。在一般的linux文件系统中,通过/dev/fb0设备文件来提供给应用程序对framebuffer进行读写的访问。这里,如果有多个显示设备,就将依次出现fb1,fb2,…等文件。而在我们所说的android系统中,这个设备文件被放在了/dev/graphics/fb0,而且往往只有这一个。
3.3.2 framebuffer的读取
读取的方法很简单,就将/dev/graphics/fb0当作一般的文件读取即可。可以通过ioctl()方法获取图像的长宽,以及每一个pixel对应的数据量。在android系统中,采用的是rbg565的编码方式。这里编程的方法是C最基本的,难点主要是编译器的配置。我会在第4节介绍一个Native的tutorial: hello world程序,这里会讲到编译的方法和具体配置。
3.3.3 在android emulator中利用命令直接进行截屏
这一篇文章有一个大致的流程。主要是用cat读取fb,后用ffmpeg转换编码的方法。此处略。
4 Android本地编程入门:”hello world!” again!
我简单介绍一下怎么在android上开发基本的C程序。如果做过ARM的C应用程序开发的话会发现,ARM一般情况下提供了十分完备的编译器,而android没有而已(android提供了完善的Java层开发工具,C的却不是那么完善)。
4.1 编写hello.c
这个太简单了,不是么?
#include <stdio.h>
int main( void )
{
printf ( "hello world!\n" );
return 0;
}
|
4.2 编写Android的编译器配置文件make_android
在Android SDK中,并没有提供Android系统的C编译器。就算是在NDK中,也只是提供了ndk-build工具,用来编译native static/dynamic library。只有仔细翻阅NDK的手册(它的手册位于NDK根目录的doc/OVERVIEW.html,比较简略),才会发现有一个STANDALONE-TOOLCHAIN的页面,会提到单独编译C Level应用程序的方法。我这里提供一段简单的makefile,命名文件为make_android,用来配置CC宏:
# make_android: this is a sub makefile for android native compile
# you have to set ANDROID_VER and ANDROID_ROOT to your flavor to work
### these two things have to be set first!!!
ANDROID_VER=android-8
ANDROID_ROOT=/home/xzpeter/android
PLATFORM_DIR=${ANDROID_ROOT}/prebuilt/ndk/android-ndk-r4/platforms
SYSROOT=${PLATFORM_DIR}/${ANDROID_VER}/arch-arm
EABI_GCC=${ANDROID_ROOT}/prebuilt/linux-x86/toolchain/arm-linux-androideabi-4.4.x/bin/arm-linux-androideabi-gcc
CC=${EABI_GCC} --sysroot=${SYSROOT}
|
这里,ANDROID_ROOT和ANDROID_VER是需要针对自己的android source目录地址和android API level修改一下的。这里的android source是我用repo sync从github上mirror下来的android源代码。
4.3 编写Makefile
利用上面的make_android,写Makefile:
# to make x86 version of code, run: "make X86=1"
ifdef X86
CC=gcc
CLFAGS=-g
else
include make_android
endif
default: hello
hello: hello.o
clean:
rm hello *.o
|
我们提供了X86和android两种编译方式,默认是android方式。
4.4 编译
可以用make X86=1先在本地编译一下,并运行./hello试试看。如果想编译android版本,先make clean一下,然后直接make就可以了。
4.5 在模拟器中运行
利用shell命令启动emulator并将文件放到目标模拟器上去:
emulator - avd my_avd # my_avd is my config name of avd
# wait for some time to boot up
adb push . / hello / data / hello
adb shell chmod 0755 / data / hello
adb shell . / data / hello
|
应该可以看到返回的”hello world!”字符串了。
转载地址为:
http://xzpeter.org/?p=229
android截屏代码实现方法相关推荐
- android开发截屏代码,android截屏代码:C++实现
android截屏代码:C++实现 示例代码在: frameworks\base\services\surfaceflinger\tests\screencap\screencap.cpp /* * ...
- Android截屏方法总结
最近研究了一些Android的截屏方法,做一个总结. 图片剪裁方法 使用View.getDrawingCache()得到Bitmap.非常简单但是只能截图本应用的图片,并且没办法控制截图的范围. 对B ...
- android 截屏函数_android截屏功能实现代码
这篇文章主要为大家详细介绍了android截屏功能的实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 android开发中通过View的getDrawingCache方法可以达到截屏的目的, ...
- android获取activity截图,Android Activity 不能被截屏的解决方法
Android Activity 不能被截屏的解决方法 在Activity 添加即可 getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECU ...
- Android截屏截图的几种方法总结
Android截屏 Android截屏的原理:获取具体需要截屏的区域的Bitmap,然后绘制在画布上,保存为图片后进行分享或者其它用途 一.Activity截屏 1.截Activity界面(包含空白的 ...
- android盒子截图,Android截屏截图的几种方法总结
Android截屏 Android截屏的原理:获取具体需要截屏的区域的Bitmap,然后绘制在画布上,保存为图片后进行分享或者其它用途 一.Activity截屏 1.截Activity界面(包含空白的 ...
- Android截屏截图方法汇总(Activity、View、ScrollView、ListView、RecycleView、WebView截屏截图)
Android截屏 Android截屏的原理:获取具体需要截屏的区域的Bitmap,然后绘制在画布上,保存为图片后进行分享或者其它用途 一.Activity截屏 1.截Activity界面(包含空白的 ...
- 三星 android截屏快捷键,三星手机截图快捷键以及截图方法【图文】
三星手机的出货量仍然占据着全球绝大多数的分量,而三星手机之所以会深受国内外消费者喜欢,主要是因为它拥有非常强大的性能以及非常好的使用体验.而三星手机为了不断增加消费者的使用体验,因此三星为人们开发出了 ...
- 三星android截屏快捷键是什么,三星手机怎么快速截屏快捷键(必知这3种截屏方法)...
对于大部分的用户们来说,相信大家对于智能手机的截屏功能一定不会陌生,在使用手机的过程中也会经常遇到.但是对于一些新手们来说,大家可能还不清楚三星S7怎么截屏,因此今天本文就来和大家分享下三星S7的三种 ...
最新文章
- boos里的AHCI RAID_安徒恩Raid删除,安徒恩讨伐战上线,详细攻略快速看,成为新的摸金圣地...
- Android—RecyclerView相关内容
- HTML5 上传图片预览
- C++ 获取函数耗时
- 《Python编程从入门到实践》记录之Python函数返回值
- 请允许我像亲人一样去爱你
- C++ STL 源码剖析之 Traits 编程技法
- 大革命修改后无法连接服务器,刺客信条大革命常见问题解决方法 中文设置教学...
- zigbee学习之JN5169 串口UARTs
- 千锋web前端教学知识点记录及个人理解2
- 自适应Simpson法P4525 【模板】自适应辛普森法1
- DirectX11 交换链是什么
- php小于neq qe,ThinkPHP eq neq if 标签
- SAP Scripting Tracker基本使用技巧
- FxFactory 7 for Mac(视觉特效软件包)
- IT类实习/工作习惯心得
- 【IoT】14.Identify Customer Need 拿捏住客户的想法
- px4+ros+gazebo+ORB_SLAM2室内视觉无人机导航
- vmm_xactor
- 以太网物理层协议整理(1)-百兆/千兆以太网