Android6.0显示系统(三)管理图像缓冲区

合集下载

Android应用内存优化与性能调优技巧

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之屏幕设备管理-动态链接库

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权限管理之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设置界面的方法

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应用性能优化最佳实践

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图⽚的三级缓存及图⽚压缩为什么需要图⽚缓存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权限管理之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等操作系统的智能手机,最终用户可通过手机上的浏览器接入系统,实现随时随地的移动办公.
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 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);。

相关文档
最新文档