Android6.0显示系统(三)管理图像缓冲区
Android应用内存优化与性能调优技巧

Android应用内存优化与性能调优技巧第一章:内存管理基础Android应用内存管理是确保应用平稳运行的重要环节,开发者需要了解内存管理的基础知识,以便进行有效的优化和调优。
在本章中,我们将介绍Android应用的内存管理原理、内存泄漏和内存溢出的区别以及常见的内存优化工具和技巧。
1.1 Android应用内存管理原理在Android应用中,每个应用都有一定的内存限制,称为最大堆(Max Heap)。
Android系统通过垃圾回收机制(GC)来回收未使用的内存,使其可供其他应用或系统使用。
内存管理器(Memory Manager)会根据应用的内存需求,动态分配和回收内存。
1.2 内存泄漏与内存溢出的区别内存泄漏(Memory Leak)和内存溢出(Memory Overflow)是常见的内存问题。
内存泄漏是指应用持有某些资源的引用,但无法释放这些资源,导致内存的持续增长。
内存溢出是指应用所需的内存超出了系统分配的内存限制,导致应用崩溃或系统变慢。
优化内存泄漏和避免内存溢出是提高应用性能的关键。
1.3 常见的内存优化工具和技巧为了帮助开发者有效地进行内存优化,Android提供了一系列的内存优化工具和技巧。
其中包括内存分析工具(如Android Profiler和MAT)、内存优化插件(如LeakCanary和MemoryMonitor)以及一些开发技巧(如使用弱引用和使用集合类的优化)。
第二章:内存优化技巧本章将介绍一些实用的内存优化技巧,帮助开发者减少内存消耗、降低应用占用内存的风险,提高应用的性能和响应速度。
2.1 减少内存消耗的技巧在开发应用时,可以采取以下技巧来减少内存消耗:- 使用资源引用(Resource References)来引用大型资源,减少内存占用;- 优化图像资源的大小和压缩方式,减少内存占用;- 使用懒加载(Lazy Loading)来延迟加载大型资源,减少应用启动时的内存占用。
Android GDI之屏幕设备管理-动态链接库

Android GDI之屏幕设备管理-动态链接库万丈高楼从地起,从最根源的硬件帧缓冲区开始。
我们知道显示FrameBuffer在系统中就是一段内存,GDI的工作就是把需要输出的内容放入到该段内存的某个位置。
我们从基本的点(像素点)和基本的缓冲区操作开始。
1 基本知识1.1点的格式对于不同的LCD来讲,FrameBuffer的二进制格式不一样,并且可以分为两部分:1)点的格式:通常将Depth,即表示多少位表示一个点。
1位表示一个点2位表示一个点16位表示一个点32位表示一个点(Alpha通道)2) 点内格式:RGB分量分布表示。
例如对于我们常见的16位表示一个点1.2.格式之间的转换所以屏幕输出实际上是一个值映射的关系。
我们可以有如下的点格式转换,源格式可能来自单色位图和彩色位图,对于具体的目标机来讲,我们的目标格式可能就是一种,例如16位(5/6/5)格式。
其实就只存在一种格式的转换,即从目标格式都是16位格式。
但是,在设计GDI时,基本要求有一个可移植性好,所以我们还是必须考虑对于不同点格式LCD之间的转换操作。
所以在GDI的驱动程序中涉及到如下几类主要操作:区域操作(Blit):我们在显示缓冲区上做的最多的操作就是区块搬运。
由此,很多的应用处理器使用了硬件图形加速器来完成区域搬运:blit.从我们的主要操作的对象来看,可以分为两个方向:1)内存区域到屏幕区域2)屏幕区域到屏幕区域3)屏幕区域到内存区域4)内存区域到内存区域在这里我们需要特别提出的是,由于在Linux不同进程之间的内存不能自由的访问,使得我们的每个Android应用对于内存区域和屏幕缓冲区的使用变得很复杂。
在Android的设计中,在屏幕缓冲区和显示内存缓冲区的管理分类很多的层次,最上层的对象是可以在进程间自由传递,但是对于缓冲区内容则使用共享内存的机制。
基于以上的基础知识,我们可以知道:(1)代码中Config及其Format的意义所在了。
Android权限管理之Permission权限机制及使用详解

Android权限管理之Permission权限机制及使⽤详解前⾔:最近突然喜欢上⼀句诗:“宠辱不惊,看庭前花开花落;去留⽆意,望天空云卷云舒。
” 哈哈~,这个和今天的主题⽆关,最近只要不学习总觉得⽣活中少了点什么,所以想着围绕着最近⾯试过程中讨论⽐较多的⼀个知识点Android 6.0 权限适配问题来进⾏学习,不过我不想直接进⼊这个主题,所以选择先去了解⼀下Android的Permission权限机制及使⽤Android权限机制:权限是⼀种安全机制。
Android权限主要⽤于限制应⽤程序内部某些具有限制性特性的功能使⽤以及应⽤程序之间的组件访问。
Android权限列表:访问登记属性android.permission.ACCESS_CHECKIN_PROPERTIES ,读取或写⼊登记check-in数据库属性表的权限获取错略位置android.permission.ACCESS_COARSE_LOCATION,通过WiFi或移动基站的⽅式获取⽤户错略的经纬度信息,定位精度⼤概误差在30~1500⽶获取精确位置android.permission.ACCESS_FINE_LOCATION,通过GPS芯⽚接收卫星的定位信息,定位精度达10⽶以内访问定位额外命令android.permission.ACCESS_LOCATION_EXTRA_COMMANDS,允许程序访问额外的定位提供者指令获取模拟定位信息android.permission.ACCESS_MOCK_LOCATION,获取模拟定位信息,⼀般⽤于帮助开发者调试应⽤获取⽹络状态android.permission.ACCESS_NETWORK_STATE,获取⽹络信息状态,如当前的⽹络连接是否有效访问Surface Flinger android.permission.ACCESS_SURFACE_FLINGER,Android平台上底层的图形显⽰⽀持,⼀般⽤于游戏或照相机预览界⾯和底层模式的屏幕截图获取WiFi状态android.permission.ACCESS_WIFI_STATE,获取当前WiFi接⼊的状态以及WLAN热点的信息账户管理android.permission.ACCOUNT_MANAGER,获取账户验证信息,主要为GMail账户信息,只有系统级进程才能访问的权限验证账户android.permission.AUTHENTICATE_ACCOUNTS,允许⼀个程序通过账户验证⽅式访问账户管理ACCOUNT_MANAGER相关信息电量统计android.permission.BATTERY_STATS,获取电池电量统计信息绑定⼩插件android.permission.BIND_APPWIDGET,允许⼀个程序告诉appWidget服务需要访问⼩插件的数据库,只有⾮常少的应⽤才⽤到此权限绑定设备管理android.permission.BIND_DEVICE_ADMIN,请求系统管理员接收者receiver,只有系统才能使⽤绑定输⼊法android.permission.BIND_INPUT_METHOD ,请求InputMethodService服务,只有系统才能使⽤绑定RemoteView android.permission.BIND_REMOTEVIEWS,必须通过RemoteViewsService服务来请求,只有系统才能⽤绑定壁纸android.permission.BIND_WALLPAPER,必须通过WallpaperService服务来请求,只有系统才能⽤使⽤蓝⽛android.permission.BLUETOOTH,允许程序连接配对过的蓝⽛设备蓝⽛管理android.permission.BLUETOOTH_ADMIN,允许程序进⾏发现和配对新的蓝⽛设备变成砖头android.permission.BRICK,能够禁⽤⼿机,⾮常危险,顾名思义就是让⼿机变成砖头应⽤删除时⼴播android.permission.BROADCAST_PACKAGE_REMOVED,当⼀个应⽤在删除时触发⼀个⼴播收到短信时⼴播android.permission.BROADCAST_SMS,当收到短信时触发⼀个⼴播连续⼴播android.permission.BROADCAST_STICKY,允许⼀个程序收到⼴播后快速收到下⼀个⼴播WAP PUSH⼴播android.permission.BROADCAST_WAP_PUSH,WAP PUSH服务收到后触发⼀个⼴播拨打电话android.permission.CALL_PHONE,允许程序从⾮系统拨号器⾥输⼊电话号码通话权限android.permission.CALL_PRIVILEGED,允许程序拨打电话,替换系统的拨号器界⾯拍照权限android.permission.CAMERA,允许访问摄像头进⾏拍照改变组件状态android.permission.CHANGE_COMPONENT_ENABLED_STATE,改变组件是否启⽤状态改变配置android.permission.CHANGE_CONFIGURATION,允许当前应⽤改变配置,如定位改变⽹络状态android.permission.CHANGE_NETWORK_STATE,改变⽹络状态如是否能联⽹android.permission.CHANGE_WIFI_MULTICAST_STATE,改变WiFi多播状态改变WiFi多播状态改变WiFi状态android.permission.CHANGE_WIFI_STATE,改变WiFi状态清除应⽤缓存android.permission.CLEAR_APP_CACHE,清除应⽤缓存清除⽤户数据android.permission.CLEAR_APP_USER_DATA,清除应⽤的⽤户数据底层访问权限android.permission.CWJ_GROUP,允许CWJ账户组访问底层信息android.permission.CELL_PHONE_MASTER_EX,⼿机优化⼤师扩展权限⼿机优化⼤师扩展权限控制定位更新android.permission.CONTROL_LOCATION_UPDATES,允许获得移动⽹络定位信息改变删除缓存⽂件android.permission.DELETE_CACHE_FILES,允许应⽤删除缓存⽂件删除应⽤android.permission.DELETE_PACKAGES,允许程序删除应⽤电源管理android.permission.DEVICE_POWER,允许访问底层电源管理应⽤诊断android.permission.DIAGNOSTIC,允许程序到RW到诊断资源禁⽤键盘锁android.permission.DISABLE_KEYGUARD,允许程序禁⽤键盘锁转存系统信息android.permission.DUMP,允许程序获取系统dump信息从系统服务状态栏控制android.permission.EXPAND_STATUS_BAR,允许程序扩展或收缩状态栏⼯⼚测试模式android.permission.FACTORY_TEST,允许程序运⾏⼯⼚测试模式使⽤闪光灯android.permission.FLASHLIGHT,允许访问闪光灯强制后退android.permission.FORCE_BACK,允许程序强制使⽤back后退按键,⽆论Activity是否在顶层android.permission.GET_ACCOUNTS,访问GMail账户列表访问账户Gmail列表获取应⽤⼤⼩android.permission.GET_PACKAGE_SIZE,获取应⽤的⽂件⼤⼩获取任务信息android.permission.GET_TASKS,允许程序获取当前或最近运⾏的应⽤允许全局搜索android.permission.GLOBAL_SEARCH,允许程序使⽤全局搜索功能硬件测试android.permission.HARDWARE_TEST,访问硬件辅助设备,⽤于硬件测试注射事件android.permission.INJECT_EVENTS,允许访问本程序的底层事件,获取按键、轨迹球的事件流安装定位提供android.permission.INSTALL_LOCATION_PROVIDER,安装定位提供安装应⽤程序android.permission.INSTALL_PACKAGES,允许程序安装应⽤内部系统窗⼝android.permission.INTERNAL_SYSTEM_WINDOW,允许程序打开内部窗⼝,不对第三⽅应⽤程序开放此权限访问⽹络android.permission.INTERNET,访问⽹络连接,可能产⽣GPRS流量结束后台进程android.permission.KILL_BACKGROUND_PROCESSES,允许程序调⽤killBackgroundProcesses(String).⽅法结束后台进程管理账户android.permission.MANAGE_ACCOUNTS,允许程序管理AccountManager中的账户列表管理程序引⽤android.permission.MANAGE_APP_TOKENS,管理创建、摧毁、Z轴顺序,仅⽤于系统⾼级权限android.permission.MTWEAK_USER,允许mTweak⽤户访问⾼级系统权限社区权限android.permission.MTWEAK_FORUM,允许使⽤mTweak社区权限软格式化android.permission.MASTER_CLEAR,允许程序执⾏软格式化,删除系统配置信息修改声⾳设置android.permission.MODIFY_AUDIO_SETTINGS,修改声⾳设置信息修改电话状态android.permission.MODIFY_PHONE_STATE,修改电话状态,如飞⾏模式,但不包含替换系统拨号器界⾯格式化⽂件系统android.permission.MOUNT_FORMAT_FILESYSTEMS,格式化可移动⽂件系统,⽐如格式化清空SD卡挂载⽂件系统android.permission.MOUNT_UNMOUNT_FILESYSTEMS,挂载、反挂载外部⽂件系统允许NFC通讯android.permission.NFC,允许程序执⾏NFC近距离通讯操作,⽤于移动⽀持永久Activity android.permission.PERSISTENT_ACTIVITY,创建⼀个永久的Activity,该功能标记为将来将被移除处理拨出电话android.permission.PROCESS_OUTGOING_CALLS,允许程序监视,修改或放弃播出电话读取⽇程提醒android.permission.READ_CALENDAR,允许程序读取⽤户的⽇程信息读取联系⼈android.permission.READ_CONTACTS,允许应⽤访问联系⼈通讯录信息屏幕截图android.permission.READ_FRAME_BUFFER,读取帧缓存⽤于屏幕截图com.android.browser.permission.READ_HISTORY_BOOKMARKS,读取浏览器收藏夹和历史记录读取收藏夹和历史记录读取输⼊状态android.permission.READ_INPUT_STATE,读取当前键的输⼊状态,仅⽤于系统读取系统⽇志android.permission.READ_LOGS,读取系统底层⽇志读取电话状态android.permission.READ_PHONE_STATE,访问电话状态读取短信内容android.permission.READ_SMS,读取短信内容读取同步设置android.permission.READ_SYNC_SETTINGS,读取同步设置,读取Google在线同步设置读取同步状态android.permission.READ_SYNC_STATS,读取同步状态,获得Google在线同步状态重启设备android.permission.REBOOT,允许程序重新启动设备开机⾃动允许android.permission.RECEIVE_BOOT_COMPLETED,允许程序开机⾃动运⾏接收彩信android.permission.RECEIVE_MMS,接收彩信接收短信android.permission.RECEIVE_SMS,接收短信接收Wap Push android.permission.RECEIVE_WAP_PUSH,接收WAP PUSH信息录⾳android.permission.RECORD_AUDIO,录制声⾳通过⼿机或⽿机的麦克排序系统任务android.permission.REORDER_TASKS,重新排序系统Z轴运⾏中的任务结束系统任务android.permission.RESTART_PACKAGES,结束任务通过restartPackage(String)⽅法,该⽅式将在外来放弃发送短信android.permission.SEND_SMS,发送短信android.permission.SET_ACTIVITY_WATCHER,设置Activity观察器⼀般⽤于monkey测试设置Activity观察其设置闹铃提醒com.android.alarm.permission.SET_ALARM,设置闹铃提醒设置总是退出android.permission.SET_ALWAYS_FINISH,设置程序在后台是否总是退出设置动画缩放android.permission.SET_ANIMATION_SCALE,设置全局动画缩放设置调试程序android.permission.SET_DEBUG_APP,设置调试程序,⼀般⽤于开发设置屏幕⽅向android.permission.SET_ORIENTATION,设置屏幕⽅向为横屏或标准⽅式显⽰,不⽤于普通应⽤设置应⽤参数android.permission.SET_PREFERRED_APPLICATIONS,设置应⽤的参数,已不再⼯作具体查看addPackageToPreferred(String) 介绍设置进程限制android.permission.SET_PROCESS_LIMIT,允许程序设置最⼤的进程数量的限制设置系统时间android.permission.SET_TIME,设置系统时间设置系统时区android.permission.SET_TIME_ZONE,设置系统时区设置桌⾯壁纸android.permission.SET_WALLPAPER,设置桌⾯壁纸设置壁纸建议android.permission.SET_WALLPAPER_HINTS,设置壁纸建议发送永久进程信号android.permission.SIGNAL_PERSISTENT_PROCESSES,发送⼀个永久的进程信号状态栏控制android.permission.STATUS_BAR,允许程序打开、关闭、禁⽤状态栏访问订阅内容android.permission.SUBSCRIBED_FEEDS_READ,访问订阅信息的数据库写⼊订阅内容android.permission.SUBSCRIBED_FEEDS_WRITE,写⼊或修改订阅内容的数据库显⽰系统窗⼝android.permission.SYSTEM_ALERT_WINDOW,显⽰系统窗⼝更新设备状态android.permission.UPDATE_DEVICE_STATS,更新设备状态使⽤证书E_CREDENTIALS,允许程序请求验证从AccountManager使⽤SIP视频E_SIP,允许程序使⽤SIP视频服务使⽤振动android.permission.VIBRATE,允许振动唤醒锁定android.permission.WAKE_LOCK,允许程序在⼿机屏幕关闭后后台进程仍然运⾏写⼊GPRS接⼊点设置android.permission.WRITE_APN_SETTINGS,写⼊⽹络GPRS接⼊点设置写⼊⽇程提醒android.permission.WRITE_CALENDAR,写⼊⽇程,但不可读取写⼊联系⼈android.permission.WRITE_CONTACTS,写⼊联系⼈,但不可读取写⼊外部存储android.permission.WRITE_EXTERNAL_STORAGE,允许程序写⼊外部存储,如SD卡上写⽂件写⼊Google地图数据android.permission.WRITE_GSERVICES,允许程序写⼊Google Map服务数据写⼊收藏夹和历史记录com.android.browser.permission.WRITE_HISTORY_BOOKMARKS,写⼊浏览器历史记录或收藏夹,但不可读取读写系统敏感设置android.permission.WRITE_SECURE_SETTINGS,允许程序读写系统安全敏感的设置项读写系统设置android.permission.WRITE_SETTINGS,允许读写系统设置项编写短信android.permission.WRITE_SMS,允许编写短信写⼊在线同步设置android.permission.WRITE_SYNC_SETTINGS,写⼊Google在线同步设置Android权限使⽤:1.)在 AndroidManifest.xml <manifest>标签内使⽤<uses-permission>声明使⽤某⼀个权限<uses-permission android:name="string"/>例如申请使⽤⽹络权限<uses-permission android:name="android.permission.INTERNET"/>如果特定的权限必须申明使⽤,如果没有申请使⽤就会报出Permission Denial错误,例如访问通讯录报出如下错误Caused by: ng.SecurityException: Permission Denial: reading com.androintacts.ContactsProvider2 uricontent://contacts/data/phones from pid=23763, uid=10036 requires android.permission.READ_CONTACTS解决此类错误我们只需根据提⽰添加对应的权限即可<uses-permission android:name="android.permission.READ_CONTACTS" />2.)⾃定义权限permission虽然这种使⽤场景不多见,但是在有些特定的场景下出于安全考虑就需要⾃定义权限了,⽐如两个APP之间需要共享数据⽽采⽤了ContentProvider,此时我们需要对⼀个app访问另外⼀个app的数据时需要添加权限申请。
Android6.0动态权限及跳转GPS设置界面的方法

Android6.0动态权限及跳转GPS设置界⾯的⽅法1.动态权限申请模糊的位置信息android.permission.ACCESS_COARSE_LOCATION权限为例在AndroidManifest⽂件中加⼊权限<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>然后java代码中动态申请//动态申请权限的测试⽅法public void test() {// 要申请的权限数组可以同时申请多个权限String[] permissions = {Manifest.permission.ACCESS_COARSE_LOCATION};if (Build.VERSION.SDK_INT >= 23) {//如果超过6.0才需要动态权限,否则不需要动态权限//如果同时申请多个权限,可以for循环遍历int check = ContextCompat.checkSelfPermission(this,permissions[0]);// 权限是否已经授权 GRANTED---授权 DINIED---拒绝if (check == PackageManager.PERMISSION_GRANTED) {//写⼊你需要权限才能使⽤的⽅法run();} else {//⼿动去请求⽤户打开权限(可以在数组中添加多个权限) 1 为请求码⼀般设置为final静态变量requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 1);}} else {//写⼊你需要权限才能使⽤的⽅法run();}}其中run()为你⾃⼰需要权限才能执⾏的⽅法然后重写申请权限的回掉⽅法@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,@NonNull int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);//回调,判断⽤户到底点击是还是否。
Android应用性能优化最佳实践

目录分析
1.1 Android Studio的优势
1.2 Android Studio使用入 门
1.3 Android Studio实用技
巧
1.4本章小结
1.2 Android Studio使用入门
1.2.1 Android Studio安装 1.2.2创建一个Android Studio工程 1.2.3从Eclipse项目迁移到Android Studio
1.3 Android Studio实用技巧
1.3.1代码管理 1.3.2代码编辑技巧 1.3.3调试技巧
2.1 Android系统显 示原理
2.2性能分析工具
2.3布局优化 2.4避免过度绘制
1
2.5启动优化
2
2.6合理的刷 新机制
3
2.7提升动画 性能
4
2.8卡顿监控 方案与实现
5
2.9本章小结
读书笔记
读书笔记
性能优化还蛮系统的,部分内容深度不够,但是作为正常工作的注意点看一看还是挺好的。 所有的性能优化过程都差不多,即发现问题,再去寻找问题解决方案,最后解决问题。 对于安卓开发的优化有个系统全面的介绍,不错,更深入的需要自己再去研究。 性能优化是一个app的难点,但同时也是重点。 书中的笔误特别多,不知道是不是电子版的缘故后面两章写的很仓促整本书深度不够。 有些笔误,但瑕不掩瑜,毕竟有关性能优化写的这么全的太少了,后悔没早点看到[捂脸] 。 这本书作为Android移动测试的入门挺不错的,基本的知识都有介绍,包括移动测试的要点。 介绍挺全面的,涨了很多知识,某些方面深度不够,但对于一般的日常开发够用了。 作为性能优化知识框架还挺不错的,在这个基础上再总结下目前业界常见的优化手段,沉淀出APP优化的方 法论。 挑着看的,只看了绘制/内存/稳定/功耗,整体而言性能测试大同小异,基本上性能测试也比较少,不过书 中有些方案倒是蛮新颖有趣的~绘制和稳定讲的蛮详细的,给五颗星吧~~。
详解Android图片的三级缓存及图片压缩

详解Android图⽚的三级缓存及图⽚压缩为什么需要图⽚缓存Android默认给每个应⽤只分配16M的内存,所以如果加载过多的图⽚,为了防⽌内存溢出,应该将图⽚缓存起来。
图⽚的三级缓存分别是:内存缓存本地缓存⽹络缓存其中,内存缓存应优先加载,它速度最快;本地缓存次优先加载,它速度也快;⽹络缓存不应该优先加载,它⾛⽹络,速度慢且耗流量。
三级缓存的具体实现⽹络缓存根据图⽚的url去加载图⽚在本地和内存中缓存public class NetCacheUtils {private LocalCacheUtils mLocalCacheUtils;private MemoryCacheUtils mMemoryCacheUtils;public NetCacheUtils(LocalCacheUtils localCacheUtils,MemoryCacheUtils memoryCacheUtils) {mLocalCacheUtils = localCacheUtils;mMemoryCacheUtils = memoryCacheUtils;}/*** 从⽹络下载图⽚** @param ivPic* @param url*/public void getBitmapFromNet(ImageView ivPic, String url) {new BitmapTask().execute(ivPic, url);// 启动AsyncTask,// 参数会在doInbackground中获取}/*** Handler和线程池的封装** 第⼀个泛型: 参数类型第⼆个泛型: 更新进度的泛型, 第三个泛型是onPostExecute的返回结果***/class BitmapTask extends AsyncTask<Object, Void, Bitmap> {private ImageView ivPic;private String url;/*** 后台耗时⽅法在此执⾏, ⼦线程*/@Overrideprotected Bitmap doInBackground(Object... params) {ivPic = (ImageView) params[0];url = (String) params[1];ivPic.setTag(url);// 将url和imageview绑定return downloadBitmap(url);}/*** 更新进度, 主线程@Overrideprotected void onProgressUpdate(Void... values) {super.onProgressUpdate(values);}/*** 耗时⽅法结束后,执⾏该⽅法, 主线程*/@Overrideprotected void onPostExecute(Bitmap result) {if (result != null) {String bindUrl = (String) ivPic.getTag();if (url.equals(bindUrl)) {// 确保图⽚设定给了正确的imageviewivPic.setImageBitmap(result);mLocalCacheUtils.setBitmapToLocal(url, result);// 将图⽚保存在本地mMemoryCacheUtils.setBitmapToMemory(url, result);// 将图⽚保存在内存System.out.println("从⽹络缓存读取图⽚啦...");}}}}/*** 下载图⽚** @param url* @return*/private Bitmap downloadBitmap(String url) {HttpURLConnection conn = null;try {conn = (HttpURLConnection) new URL(url).openConnection();conn.setConnectTimeout(5000);conn.setReadTimeout(5000);conn.setRequestMethod("GET");conn.connect();int responseCode = conn.getResponseCode();if (responseCode == 200) {InputStream inputStream = conn.getInputStream();//图⽚压缩处理BitmapFactory.Options option = new BitmapFactory.Options();option.inSampleSize = 2;//宽⾼都压缩为原来的⼆分之⼀, 此参数需要根据图⽚要展⽰的⼤⼩来确定 option.inPreferredConfig = Bitmap.Config.RGB_565;//设置图⽚格式Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, option);return bitmap;}} catch (Exception e) {e.printStackTrace();} finally {conn.disconnect();}return null;}}本地缓存两个⽅法:设置本地缓存,获取本地缓存public class LocalCacheUtils {public static final String CACHE_PATH = Environment.getExternalStorageDirectory().getAbsolutePath() + "/local_cache";/*** 从本地sdcard读图⽚public Bitmap getBitmapFromLocal(String url) {try {String fileName = MD5Encoder.encode(url);File file = new File(CACHE_PATH, fileName);if (file.exists()) {Bitmap bitmap = BitmapFactory.decodeStream(new FileInputStream(file));return bitmap;}} catch (Exception e) {e.printStackTrace();}return null;}/*** 向sdcard写图⽚** @param url* @param bitmap*/public void setBitmapToLocal(String url, Bitmap bitmap) {try {String fileName = MD5Encoder.encode(url);File file = new File(CACHE_PATH, fileName);File parentFile = file.getParentFile();if (!parentFile.exists()) {// 如果⽂件夹不存在, 创建⽂件夹parentFile.mkdirs();}// 将图⽚保存在本地press(CompressFormat.JPEG, 100,new FileOutputStream(file));} catch (Exception e) {e.printStackTrace();}}}内存缓存两个⽅法:设置内存缓存,获取内存缓存问题:如果使⽤HashMap存储图⽚时,当图⽚越来越多时,会导致内存溢出,因为它是强引⽤,java的垃圾回收器不会回收。
详解Android权限管理之RxPermission解决Android6.0适配问题

详解Android权限管理之RxPermission解决Android6.0适配问题前⾔:上篇重点学习了Android 6.0的运⾏时权限,今天还是围绕着Android 6.0权限适配来总结学习,这⾥主要介绍⼀下我们公司解决Android 6.0权限适配的⽅案:RxJava+RxPermission。
这⾥不再介绍Android 6.0运⾏时权限了,直接看下如何使⽤RxPermission。
RxPermission:⽤于适配Android 6.0新的权限模型的开源框架。
下载地址:如何使⽤?1.)在app module的build.gradle中添加如下配置使⽤该开源框架minSdkVersion 必须⼩于9repositories {jcenter() // If not already there}dependencies {compile 'com.tbruyelle.rxpermissions:rxpermissions:0.9.0@aar'}如果使⽤的RxJava2的话使⽤下⾯的配置与RxJava不同的是包名变成了com.tbruyelle.rxpermissions2,不过说实话RxJava2我还没使⽤过。
dependencies {compile 'com.tbruyelle.rxpermissions2:rxpermissions:0.8.2@aar'}2.)直接申请权限使⽤RxPermissions.getInstance(this)是以单例的形式使⽤的,这⾥以申请拍照权限为例RxPermissions.getInstance(this).request(permissions).subscribe(new Action1<Boolean>() {@Overridepublic void call(Boolean granted) {if (granted) { // 在android 6.0之前会默认返回true// 已经获取权限String jpgPath = getCacheDir() + "test.jpg";takePhotoByPath(jpgPath, 2);} else {// 未获取权限Toast.makeText(MainActivity.this, "您没有授权该权限,请在设置中打开授权", Toast.LENGTH_SHORT).show();}}});这⾥直接返回是否授权,我们可以根据这个值进⾏不同的处理。
蓝凌协同管理平台功能列表

门户全局设置
进行系统初始化时的Logo、版权信息维护。
系统应用设置
系统相关配置信息管理,如WindowsAD账号同步设置、KK集成设置、Discuz论坛集成设置、短信参数设置(可以二次开发)、邮件参数设置、消息服务设置、多语言设置、全文搜索设置等。配置后需重启IIS。
系统参数设置
系统各类参数管理,配置后,无需重启IIS。
短信平台
用户可以在Web上发送信息到用户手机,方便快捷;待办流程、通知公告、会议等提醒自动发送到用户手机,让您随时了解工作事项。
扩展模块
辅助办公模块:用品管理、固资管理、人事信息、表单管理、报表管理、
四、系统管理模块(核心基础组件)
企业门户管理
门户配置管理
创建和维护门户,可以设置门户的基本信息、主题、功能导航、快捷菜单、常用链接、Logo背景、版本信息以及对门户进行授权(访问权限和默认)
操作日志管理
记录管理员操作管理系统的各项操作日志.
登陆日志管理
记录系统用户登录和退出系统日志。
外部数据源
可以配置其他关系型数据库链接(MSSQL、Oracle、DB2、Sybase、Informix)为系统提供表单、报表数据读取使用。
系统报表管理
系统内置知识类、积分类、流程效率类的报表。
通 讯 录
记录联系人具体通讯信息,包括个人通讯录、公共通讯录和员工通讯录三种类型.并支持个人群组和公共群组设置.
个人中心
将您所有的经验值、财富值、消息、收藏、发布和审批的知识、发布和回答的问题、发布和审批过的地图及使用过的标签,进行统一展示.
移动办公组件
手机移动办公
EIS 移动组件是专为智能终端设备量身打造的新一代商务智能办公平台,支持主流Iphone OS 、Symbian、Android、WindowsMobile等操作系统的智能手机,最终用户可通过手机上的浏览器接入系统,实现随时随地的移动办公.
Android程序设计智慧树知到答案章节测试2023年

第一章测试1. Android1.1 的发布年份是() A:2009 B:2008 C:2011 D:2010 答案:B2. 应用图标资源,存放在文件夹() A:mipmap B:test C:drawable D:re s答案:A3. 布局定义位置在文件夹() A:layout B:main C:java D:drawable答案:A4. 关于res/raw 目录说法正确的是() A:这里的文件最终不会以二进制的格式存储到指定的包中B:这里的文件最终以二进制的格式存储到指定的包中C: 这里的文件是原封不动的存储到设备上会转换为二进制的格式D:这里的文件是原封不动的存储到设备上不会转换为二进制的格式答案:D5. 在android 程序中Log.wO 用于输出什么级别的日志信息() A:警告B:调试C:错误D:信息答案:A6. 以下属于Android 的Libraries层( ) A:View System B:Webkit C:SQLiteD:Phone答案:BC7. 以下属于Log 类输出的有() A:info(I) B:debug(D)C:verbose(V)D:warning(W) 答案:ABCD8. 导入图片时,需要特别注意图片的名称只能以字母开头。
() A:错B:对答案:B9. resxml 文件不可以大写。
() A:对B:错答案:A10. 主题定义在res/values 目录下的styles.xml 文件中() A:错B:对答案:B第二章测试1. 系统默认创建的活动名字是() A:ActivityMain B:Main ActivityC:MainActivity D:Activity Main 答案:C2. 第一次运行程序时调用的生命周期方法为() A:onStart(O-onCreateO-onPause 0 B:onCreateO-onStartO-onResumeO C:onCreateO-onStartO-onPause(O D:onStartO-onCreateO-onResumeO 答案:B3. 下列选项哪个不是Activity启动的方法? () A:goToActivityB:startActivityFromChild C:startActivityForResult D:startActivity答案:A4. 下列哪个不是Activity 的生命周期方法之一? () A:onStart B:onResumeC:startActivity D:onCreate答案:C5. onPause 什么时候调用() A:当界面启动时B:当界面重新显示时C:当界面被隐藏时D:当onCreate 方法被执行之后答案:C6. 当发送一个隐式Intent后,Android系统会将他与程序中的每一个组件的过滤器进行匹配,匹配属性有(),需要这几个属性匹配成功才能唤起相应的组件。
【Android开发Wiki】进阶篇高效的显示位图(三)—缓存位图

其余的活动或者应用程序都是很耗内存的嘛?
大量的图片是如何立刻出现在屏幕上的?需要多少即将在屏幕上显示的?
设备的屏幕的大小和分辨率是多少?一个额外的高密度屏(xhdpi)设备,例如Galaxy Nexus 将需要一个更大的缓存来维持内存中相同数量的图片,与像Nexus S(hdpi)设备比较起来.
位图是什么尺寸和配置以及每张图片要占用多少内存?
图片访问频繁嘛?比起别的将会被频繁地访问吗?也许你可能总是想要在内存中保存一定项,甚至对于不同的位图组来说有多个LRUCache对象.
你能在数量和质量之间取得平衡嘛?有时对于存储更多的低质量的位图是更有用的,潜在地在另外的后台任务中加载一个更高质量版本.
没有具体的大小以及适合所有应用程序的公式,它是由你来分析您的使用情况,并拿出一个合适的解决方案.缓存太小会导致额外的没有益处的开销,缓存过大会再次导致ng.
情况下,由于图片填充到activity时几乎马上从内存加载,你应当注意到几乎没有滞后的感觉.任何图片都是先在内存缓存中找,没有的话再从磁盘缓存中找,如果都没有的话,就会像往常获取图片一样处理.
文章来源:/page/Caching_Bitmaps。
Android帧缓冲区(Frame Buffer)硬件抽象层(HAL)模块Gralloc的实现原理分析

Android帧缓冲区(Frame Buffer)硬件抽象层(HAL)模块Gralloc的实现原理分析分类:Android2012-07-2301:251529人阅读评论(16)收藏举报前面在介绍Android系统的开机画面时提到,Android设备的显示屏被抽象为一个帧缓冲区,而Android系统中的SurfaceFlinger服务就是通过向这个帧缓冲区写入内容来绘制应用程序的用户界面的。
Android系统在硬件抽象层中提供了一个Gralloc模块,封装了对帧缓冲区的所有访问操作。
本文将详细分析Gralloc模块的实现,为后续分析SurfaceFlinger服务的实现打下基础。
在前面Android系统的开机画面显示过程分析一文中提到,Linux内核在启动的过程中会创建一个类别和名称分别为“graphics”和“fb0”的设备,用来描述系统中的第一个帧缓冲区,即第一个显示屏,其中,数字0表示从设备号。
注意,系统中至少要存在一个显示屏,因此,名称为“fb0”的设备是肯定会存在的,否则的话,就是出错了。
Android系统和Linux内核本身的设计都是支持多个显示屏的,不过,在Android目前的实现中,只支持一个显示屏。
在前面Android系统的开机画面显示过程分析一文中还提到,init进程在启动的过程中,会启动另外一个进程ueventd来管理系统的设备文件。
当ueventd进程启动起来之后,会通过netlink接口来Linux内核通信,以便可以获得内核中的硬件设备变化通知。
而当ueventd进程发现内核中创建了一个类型和名称分别为“graphics”和“fb0”的设备的时候,就会这个设备创建一个/dev/graphics/fb0设备文件。
这样,用户空间的应用程序就可以通过设备文件/dev/graphics/fb0来访问内核中的帧缓冲区,即在设备的显示屏中绘制指定的画面。
注意,用户空间的应用程序一般是通过内存映射的方式来访问设备文件/dev/graphics/fb0的。
Android6.0 显示系统(三) 管理图像缓冲区

Android6.0 显示系统(三)管理图像缓冲区一、BufferQueueCore BufferQueueProducer BufferQueueConsumer上篇博客在Layer的onFirstRef函数中,调用了下面函数,创建了3个对象BufferQueueCore BufferQueueProducer BufferQueueConsumer。
其中BufferCore是核心,把BufferQueueProducer 和BufferQueueConsumer对象连接在一起。
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,sp<IGraphicBufferConsumer>* outConsumer,const sp<IGraphicBufferAlloc>& allocator) {sp<BufferQueueCore> core(new BufferQueueCore(allocator));sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core));sp<IGraphicBufferConsumer> consumer(new BufferQueueConsumer(core));*outProducer = producer;*outConsumer = consumer;}1.1 生产者和core的联系IGraphicBufferProducer 的大致接口如下,BufferQueueProducer类是接口IGraphicBufferProducer 的实现,使用BufferQueueProducer之前先要调用connect函数,使用结束后调用disconnect断开连接。
android6.0功能介绍

1.1 应用权限管理Android 6.0系统加入了新的权限管理系统。
在之前的Android系统中,App安装的时候会列出App所请求的权限。
用户读过后,可以决定是否安装App。
Android 6.0将允许用户在设置选项对每个授权许可进行开启/关闭,例如你并不希望你的短信应用获取你的地理信息,那么你可以在新设置页面中在“Lacation”中对相应的短信应用进行调整。
其次,用户在安装App的时候,不再会有长长的权限列表列出。
但是,用户首次使用一个App的时候,使用过程中实际用到哪些权限就会向用户发出提醒,申请获得授权。
Android 6.0的权限管理策略将带来更安全的权限管理服务。
这个模型改善了用户可以直观地进行操控权限,简化了开发人员安装和自动更新的过程。
用户可以授予或单独撤销安装的应用程序的权限。
1.2 场景助手“Now on Tap”功能,浏览网页时,长按 home 键,会根据目前屏幕上的内容给出建议与相关应用。
例如可直接进入谷歌商店在其它应用中也可使用 Now on Tap。
例如在 Facebook 中长按 home 键,可以直接点选 YouTube 看这歌手的歌1.3 文本操作在文本被选中之后,在浮动工具条中会有拷贝、分享、搜索选项,所有应用中都可以注册并使用选择浮动工具条来操作文本。
在使用外接实体键盘时,可以用ctrl-C,ctrl-Z等操作。
备注:此功能中的搜索必须要使用GMS完成。
1.4 自动应用备份当应用被安装到一个新的设备上或者设备在恢复出厂设置的时候,自动备份会自动与用户联系收集以前的数据、账户、信息、设置、游戏分数和甚至桌面图标排列顺序来恢复。
开发者可以通过应用申明文件控制哪些数据可以备份。
查看自动应用备份获取更多细节。
这个版本也可以扩展已备份的系统设置、默认应用设置、同步设置、和键盘,并且将他们在新设备上恢复过来。
概要说明:通过google框架自动备份应用,设置,手机信息等内容,以便在新手机上进行恢复,有点类似云备份。
Android中Glide加载库的图片缓存配置究极指南

Android中Glide加载库的图⽚缓存配置究极指南零、选择Glide为什么图⽚加载我⾸先推荐Glide?图⽚加载框架⽤了不少,从afinal框架的afinalBitmap,Xutils的BitmapUtils,⽼牌框架universalImageLoader,著名开源组织square的picasso,google推荐的glide到FaceBook推出的fresco。
这些我前前后后都体验过,那么⾯对这么多的框架,该如何选择呢?下⾯简单分析下我的看法。
afinal和Xuils在github上作者已经停⽌维护了,开源社区最新的框架要属KJFramework,不过这种快速开发框架看似很好⽤,功能也应有尽有,⼩型项⽬也罢,⼤型项⽬我不是很推荐,这样做项⽬的耦合度太⾼,⼀旦出现停⽌维护,⽽新的问题不断增加,没⼈处理就⿇烦了。
在glide和fresco还未出来的时候,当时最⽕的莫过于universalImageLoader和picasso了,当时觉得universalImageLoader配置相对picasso⿇烦,虽然提供了各种配置,但是没有实践过,根本不知道如何配置,还不如都采⽤默认配置,就选择了picasso作为图⽚加载框架,⽤了近⼀年的时间,没有太⼤的问题,且使⽤简单,或许是因为之前的项⽬太过于简单,周期也并不是很长,还有使⽤eclipse开发,⼀个很⼤的问题⼀直都没有暴露出来,换上了最新的Android Studio可以清晰的看到各种性能相关的监控,如cpu还有内存监控,终于知道了之前做的项⽬都那么的卡顿的罪魁祸⾸,picasso加载稍微⼤⼀点的图⽚就特别耗内存,通常⼀个listView或者顶部滑动⼴告栏都含有多张图⽚,这使得做出的页⾯只要含图⽚较多就异常卡顿(之前的时候还把它归结为测试机不好),知道这⼀点后我就有点想把picasso给替换掉,但这⼀次我不能那么粗⼼。
测试了picasso,glide,universalImageLoader,fresco这四个框架,测试内容⼤概有以下⼏项,内存测试,⼤图⽚测试,⼩图⽚测试,本地图⽚,⽹络图⽚当然还结合官⽅⽂档体验其特⾊功能,内存测试中,glide,universalImageLoader,fresco表现都⾮常优秀,picasso这⼀点上实在是太糟糕了,⼩图⽚差别也不是很⼤,稍微⼤点图⽚内存消耗就要⽐其他⾼出⼏倍,这⼀点上证明了我的猜想,picasso不能再⽤了,下⾯⼀项项分析其他框架,在⾼于2M左右⼤图测试中fresco的表现则和picasso ⼀样直接神马都不显⽰,项⽬中要实现⼤图预览功能,这点上是不⾏的,接着看universalImageLoader和glide在这⼏项测试中成绩都很好,到底该如何选择呢?因为我项⽬之前⽤的picasso,glide从⽤法上⼏乎就是另⼀个picasso,从picasso转移到glide相对改动较少,还有⼀点就是这个项⽬是google在维护,我也能给它更多的信任,相⽐较universalImageLoader,glide可以⽀持gif和短视频,后期也需要⽤到,这⾥不得不谈⼀下glide优秀的缓存机制了,glide图⽚缓存默认使⽤RGB565相当于ARGB8888可以节省不少的空间,⽀持与activity,fragment,application⽣命周期的联动,更智能管理图⽚请求当然还有其他的扩展更多可以看?glide介绍?当然,glide的⽅法数量⽐universalImageLoader多了1000多个,遇到64k问题的会⽐较关注这个。
Android6.0 显示系统GraphicBuffer分配内存

Android6.0 显示系统GraphicBuffer分配内存之前分析了显示系统的大致流程,其中有几个地方不是很清楚,这里我专门写几篇专题。
这篇先来看GraphicBuffer分配内存,我们在之前的博客中分析到用户进程创建一个Surface,最后返回的参数gbp是sp<IGraphicBufferProducer>类型的,过程之前都分析过了,我们就不分析了,这个gbp是在Layer的onFirstRef中创建的。
在BufferQueue的createBufferQueue中创建了producer和consumer,然后创建了MonitoredProducer对象,并且用producer来作为参数。
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片void Layer::onFirstRef() {// Creates a custom BufferQueue for SurfaceFlingerConsumer to usesp<IGraphicBufferProducer> producer;sp<IGraphicBufferConsumer> consumer;BufferQueue::createBufferQueue(&producer, &consumer);mProducer = new MonitoredProducer(producer, mFlinger);......用户进程和SurfaceFlinger通信的Binder类MonitoredProducer是继承IGraphicBufferProducer 类。
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片class MonitoredProducer : public IGraphicBufferProducer {我们再来看看IGraphicBufferProducer 类的实现,典型的Binder用法,在这个类中有Bp端和Bn端的实现。
Android6.0显示系统(六)图像的输出过程阳和移动开发

Android6.0显示系统(六)图像的输出过程阳和移动开发文章目录• 1.1 每个Layer的onFrameAvailable函数• 1.2 绘制流程上篇博客分析到SurfaceFlinger收到了VSync信号后,调用了handleMessageRefresh函数,这篇博客主要就是分析这个函数,我们先看看它的代码:void SurfaceFlinger::handleMessageRefresh() {ATRACE_CALL();static nsecs_t previousExpectedPresent = 0;nsecs_t expectedPresent = puteNextRefresh(0);static bool previousFrameMissed = false;bool frameMissed = (expectedPresent == previousExpectedPresent);if (frameMissed != previousFrameMissed) {ATRACE_INT('FrameMissed', static_cast(frameMissed));}previousFrameMissed = frameMissed;if (CC_UNLIKELY(mDropMissedFrames && frameMissed)) { // Latch buffers, but don't send anything to HWC, then signal another// wakeup for the next vsyncpreComposition();repaintEverything();} else {preComposition();rebuildLayerStacks();setUpHWComposer();doDebugFlashRegions();doComposition();postComposition();}previousExpectedPresent = puteNextRefresh(0);}我们主要看下下面几个函数。
Android6.0显示系统(四)图像显示相关

Android6.0显示系统(四)图像显示相关Linux通常使用Framebuffer来用作显示输出,Framebuffer就是一块内存区域,它通常是显示驱动的内部缓冲区在内存中的映射。
一旦用户进程把图像数据复制到Framebuffer中,显示驱动会一个像素一个像素地扫描整个Framebuffer,并根据其中的值更新屏幕上像素点的颜色。
驱动中这种更新屏幕的动作是固定的,它的周期就是我们常说的刷新率。
但是在屏幕更新一半时,用户进程更新了Framebuffer中的数据,将导致屏幕上画面的上半部分是前一帧的画面,下半部分变成了新的画面。
当然错误会在下次刷新时纠正过来,但是这样也会有闪烁的感觉。
这个可以使用双缓冲机制,双缓冲就是提供两块Framebuffer,一块用于显示,一块用于数据更新。
数据准备好后,通过ioctl操作告诉显示设备切换用于显示的FrameBuffer,这样图像就能快速的显示出来。
但是双缓冲并没有完全解决问题,虽然双缓冲切换的速度很快,但是如果切换的时间点不对,在画面更新一半的时候切换,还是会出现闪烁的问题。
当然,我们可以在底层进行控制,收到切换请求的时候,内部并不马上执行,等到刷新完成后再切换,这样完全避免了画面重叠问题。
但是这样也有问题,如果用ioctl操作告诉底层可以进行切换了,但是缓冲区没有切换,这样应用层就不能确定何时可以再使用缓冲区,因此只能不断的通过ioctl来查询缓冲区的状态,一直到切换完成了。
这种方式效率太低,拖慢了整个系统。
解决这个问题就是底层固定发送信号给用户进程,通知进程切换的时机。
这个信号就是VSync信号。
VSync信号是一个硬件信号,一般是显示设备刷新的周期到了会发送。
一、VSync信号的产生Android通过VSync机制来提高显示效果,那么VSync是如何产生的?通常这个信号是由显示驱动产生,这样才能达到最佳效果。
但是Android为了能运行在不支持VSync机制的设备上,也提供了软件模拟产生VSync信号的手段。
Android6.0 显示系统(三) 管理图像缓冲区

Android6.0 显示系统(三)管理图像缓冲区一、BufferQueueCore BufferQueueProducer BufferQueueConsumer上篇博客在Layer的onFirstRef函数中,调用了下面函数,创建了3个对象BufferQueueCore BufferQueueProducer BufferQueueConsumer。
其中BufferCore是核心,把BufferQueueProducer 和BufferQueueConsumer对象连接在一起。
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,sp<IGraphicBufferConsumer>* outConsumer,const sp<IGraphicBufferAlloc>& allocator) {sp<BufferQueueCore> core(new BufferQueueCore(allocator));sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core));sp<IGraphicBufferConsumer> consumer(new BufferQueueConsumer(core));*outProducer = producer;*outConsumer = consumer;}1.1 生产者和core的联系IGraphicBufferProducer 的大致接口如下,BufferQueueProducer类是接口IGraphicBufferProducer 的实现,使用BufferQueueProducer之前先要调用connect函数,使用结束后调用disconnect断开连接。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Android6.0 显示系统(三)管理图像缓冲区一、BufferQueueCore BufferQueueProducer BufferQueueConsumer上篇博客在Layer的onFirstRef函数中,调用了下面函数,创建了3个对象BufferQueueCore BufferQueueProducer BufferQueueConsumer。
其中BufferCore是核心,把BufferQueueProducer 和BufferQueueConsumer对象连接在一起。
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,sp<IGraphicBufferConsumer>* outConsumer,const sp<IGraphicBufferAlloc>& allocator) {sp<BufferQueueCore> core(new BufferQueueCore(allocator));sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core));sp<IGraphicBufferConsumer> consumer(new BufferQueueConsumer(core));*outProducer = producer;*outConsumer = consumer;}1.1 生产者和core的联系IGraphicBufferProducer 的大致接口如下,BufferQueueProducer类是接口IGraphicBufferProducer 的实现,使用BufferQueueProducer之前先要调用connect函数,使用结束后调用disconnect断开连接。
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片class IGraphicBufferProducer : public IInterface{public:virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) = 0;virtual status_t setBufferCount(int bufferCount) = 0;virtual status_t dequeueBuffer(int* slot, sp<Fence>* fence, bool async,uint32_t w, uint32_t h, PixelFormat format, uint32_t usage) = 0;virtual status_t detachBuffer(int slot) = 0;virtual status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer,sp<Fence>* outFence) = 0;virtual status_t attachBuffer(int* outSlot,const sp<GraphicBuffer>& buffer) = 0;virtual status_t queueBuffer(int slot,const QueueBufferInput& input, QueueBufferOutput* output) = 0;virtual void cancelBuffer(int slot, const sp<Fence>& fence) = 0;virtual int query(int what, int* value) = 0;virtual status_t connect(const sp<IProducerListener>& listener,int api, bool producerControlledByApp, QueueBufferOutput* output) = 0;virtual status_t disconnect(int api) = 0;virtual status_t setSidebandStream(const sp<NativeHandle>& stream) = 0;virtual void allocateBuffers(bool async, uint32_t width, uint32_t height,PixelFormat format, uint32_t usage) = 0;virtual status_t allowAllocation(bool allow) = 0;virtual status_t setGenerationNumber(uint32_t generationNumber) = 0;virtual String8 getConsumerName() const = 0;};在BufferQueueCore类中定义了一个64项的数据mSlots。
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片BufferQueueDefs::SlotsType mSlots;[cpp] view plain copy 在CODE上查看代码片派生到我的代码片typedef BufferSlot SlotsType[NUM_BUFFER_SLOTS];每个缓冲区的类型是BufferSlot类型。
它有两个重要的成员变量,mGraphicBuffer是指向图像缓冲区GraphicBuffer的指针,mBufferState表示图像缓冲区的状态。
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片sp<GraphicBuffer> mGraphicBuffer;......BufferState mBufferState;BufferState的状态有下面几个[cpp] view plain copy 在CODE上查看代码片派生到我的代码片enum BufferState {FREE = 0,//空闲DEQUEUED = 1,//生产状态,被生产者拥有QUEUED = 2,//保存数据状态,被BufferQueue拥有ACQUIRED = 3//消费状态,被消费者拥有};BufferQueueProducer的dequeueBuffer函数用来向BufferQueueCore申请一个空闲的slot,这个slot可能已经有缓冲区,也可能没有,如果没有缓冲区,dequeueBuffer函数会分配一块新的缓冲区。
得到空闲的slot后,还需要调用requestBuffer函数来取得一块缓冲区。
得到缓冲区,如果不需要了,可以使用cancelBuffer函数来释放这个slot。
调用dequeueBuffer函数之后,缓冲区的拥有者是生产者,缓冲区处于DEQUEUED状态。
一旦缓冲区复制数据完成,通过queueBuffer函数把缓冲区的控制权交还给BufferQueueCore,这时候缓冲区将处于QUEUED状态。
1.2 消费者和core的联系下面是IGraphicBufferComsumer接口的几个主要函数:[cpp] view plain copy 在CODE上查看代码片派生到我的代码片virtual status_t acquireBuffer(BufferItem* outBuffer,nsecs_t expectedPresent, uint64_t maxFrameNumber = 0) override;......virtual status_t releaseBuffer(int slot, uint64_t frameNumber,const sp<Fence>& releaseFence, EGLDisplay display,EGLSyncKHR fence);virtual status_t connect(const sp<IConsumerListener>& consumerListener,bool controlledByApp);virtual status_t disconnect();BufferQueueConsumer类是接口IGraphicBufferComsumer的实现,在使用它之前,先要调用connect函数建立联系,这里传递的参数是IConsumerListener对象,是一个回调接口,如果BufferQueue中有数据准备好了就会调用它的onFrameAvailable函数来通知消费者取走数据。
取走数据的时候,需要调用acquireBuffer函数,将缓冲区状态变成ACQUIRED,使用完之后调用releaseBuffer函数可以吧缓冲区数据归还给BufferQueueCore,这样缓冲区就变成FREE。
1.3 三者联系对象BufferQueueProducer和BufferQueueConsumer好像没有直接联系,其实都是通过共同的BufferQueueCore对象连接在一起的,很多操作时直接使用BufferQueueCore对象的成员变量而不是函数来完成的。
二、GraphicBuffer对象的创建对Surface而言,图像缓冲区是一个重要的数据结构,它是用户进程和图像显示器之间的纽带,下面我们来看看Surface的图像缓冲区是如何创建的。
2.1 内存缓冲区的创建前面介绍了过dequeueBuffer函数,图像缓冲区GraphicBuffer就是在这个函数中创建的,当从BufferQueueCore中获取到空间的slot时,如果这个slot没有缓冲区就要新建一个。
下面是dequeueBuffer函数的部分代码,在从BufferQueueCore中获取到slot的时候,如果需要重新分配图像缓冲区就会调用mCore->mAllocator->createGraphicBuffer函数来重新创建一个图像缓冲区。
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片......*outSlot = found;//found复制到outslotA TRACE_BUFFER_INDEX(found);attachedByConsumer = mSlots[found].mAttachedByConsumer;mSlots[found].mBufferState = BufferSlot::DEQUEUED;//slot的状态修改变成生产状态const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);if ((buffer == NULL) ||//为空,或者需要重新分配buffer->needsReallocation(width, height, format, usage)){mSlots[found].mAcquireCalled = false;mSlots[found].mGraphicBuffer = NULL;mSlots[found].mRequestBufferCalled = false;mSlots[found].mEglDisplay = EGL_NO_DISPLAY;mSlots[found].mEglFence = EGL_NO_SYNC_KHR;mSlots[found].mFence = Fence::NO_FENCE;mCore->mBufferAge = 0;returnFlags |= BUFFER_NEEDS_REALLOCATION;//需要重启分配缓冲区} else {// We add 1 because that will be the frame number when this buffer// is queuedmCore->mBufferAge =mCore->mFrameCounter + 1 - mSlots[found].mFrameNumber;}BQ_LOGV("dequeueBuffer: setting buffer age to %" PRIu64,mCore->mBufferAge);。