[翻译]深入理解fitsSystemWindows

翻译自《Why would I want to fitsSystemWindows?》 原作者:Ian Lake

说到fitSystemWindows,那什么是System Windows呢?System Windows一般而言就是指的由SystemUI在屏幕绘制的组件,一般而言包含非交互的UI(如:Status Bar)、交互UI(如:Navigation Bar)。

大部分情况下,你的App应该不需要扩展到Status bar或者Navigation Bar下面,不过如果需要,你需要确保交互元素(比如Button)不要被遮挡在它们下面。这也就是android:fitsSystemWindows=“true”属性的作用:自动设置View的padding从而确保内容不会被System windows组件遮挡。

需要记住的是:

  • fitsSystemWindows is applied depth first– ordering matters: it’s the first View that consumes the insets that makes a difference
  • Insets are always relative to the full window– insets may be applied even before layout happens, so don’t assume the default behavior knows anything about the position of a View when applying its padding
  • Any other padding you’ve set is overwritten –you’ll note that paddingLeft/paddingTop/etc is ineffective if you are using android:fitsSystemWindows=”true” on the same View

另外,在全屏视频播放等众多例子中,这些就足够了。出血View不设置该属性,其他全屏的ViewGroup设置android:fitsSystemWindows=”true”

Android Studio 快捷文档加载缓慢或无法加载问题解决

Android Studio 快捷文档加载缓慢或无法加载问题大家可能都会遇到过,其原因是您所安装版本的Android Studio的Android SDK文档路径被默认设置为:https://developer.android.com/reference/ 

要想提高加载速度,应该将其修改为本地Android SDK的文档路径。所以您只需到$HOME/.AndroidStudio$VERSION/config/options/jdk.table.map.xml文件内,将所有的jdk项内的javadocPath的url修改为:$ANDROID_HOME/docs/reference

注:

  • $HOME:用户根目录;
  • $VERSION:为当前Android Studio的版本,如果为非稳定版本则版本前添加:Preview;
  • $ANDROID_HOME:Android SDK根目录;

 

公共开发资源搜集

记录一些用到的公共服务资源

公共NTP服务器
类Unix操作系统
  • time1.aliyun.com ~time7.aliyun.com
  • ntp1.aliyun.com ~ ntp5.aliyun.com
Windows时间同步服务器

time.pool.aliyun.com

IP地址库
  • 淘宝IP地址库:http://ip.aliyun.com/
公共镜像站
  • 阿里云公共镜像站:http://mirrors.aliyun.com/ 镜像同步频率是每天凌晨2:00-4:00,覆盖了大多数开源软件及Linux发行版。
  • 网易公共镜像站:http://mirrors.163.com/ 所提供的镜像服务包括: Ubuntu, Fedora, Debian, Arch, Gentoo, Slackware, CentOS等等
公共DNS
  • 阿里云DNS:223.5.5.5/223.6.6.6

从Git中彻底移除版本控制中的文件

众所周知从git版本控制中删除一个文件仅需要使用 git rm 即可。然而,有时候我们不小心将敏感文件或者没有必要的大文件包含进版本控制时,这个时候仅仅简单删除时无法做到将其从版本控制中完全删掉的,因为删掉的文件还存在于版本控制的历史中。这个时候需要我们的主角命令登场:

该命令执行完毕后,文件已经从本地的版本控制库中完全删除了,你所需要做的就是通过强制push覆盖掉远程服务器的中心库即可。

然后熟悉git原理的朋友应该都知道,我们的文件提交都对应了objects,我们删掉的文件虽然已经从本地版本控制中彻底删除,但是文件的objects依然停留在硬盘上,它们占用存储。我们需要使用GC命令进行垃圾回收,彻底清除这些文件,回收其占用的磁盘空间。

 

AppOps应对Android应用流氓权限行为及肆无忌惮的后台服务

AppOps是Android 自4.3加入的应用权限授权管理框架,虽然到了后来6.0引入了另外一套方案Android Runtime Permission,但是 AppOps并没有被废弃掉,它依然存在于系统框架内,只不过没有图形管理入口而已,但是依然保留并增加了API,而且AppOps命令行管理工具依然可用。我们所用到的就是AppOps Command line utility。

所有的OP(Operations),即操作权限列表

appops 命令是Android系统的可执行程序,我们要运行,需要使用电脑USB连接手机并开启开发者调试,使用 adb shell [-e escape] [-n] [-Tt] [-x] [command] 运行远程shell命令(如果没有给定命令则开启交互的shell终端) 在Android系统内执行shell命令。

现在,我们就要拿微信来举个例子,微信中文版在Android 6.0下强制要求读取电话状态信息定位读取写入外置存储权限,否则应用强制无法正常使用。我不知道大家怎么看待,我个人认为这三个权限都是可选的权限,微信就是在耍流氓。而我们就可以使用AppOps将其某项强制要求权限忽略掉,注意这里说的是忽略掉而不是禁用,如果单纯禁用在Android Runtime Permission内即可做到,但是微信可以感知到自己的权限被禁用,就会流氓的提示你应用无法使用。而AppOps可以忽略应用的权限申请,但是这个应用本身是无法感知判断的。在这里我们尝试禁用微信的读取电话状态信息权限、位置定位权限和后台服务运行权限(这个导致无法后台收消息):

通过上面的操作,微信已经无法获取上述权限,而且再退出微信应用后,几分钟后微信后台服务(注意Foreground Service不会被关掉)都会被系统关掉,但是微信应用本身的主进程依然是作为空进程缓存在内存中,而不是被整个杀掉。

作为Android开发者,真心希望大家能够尽可能的克制规范自己的行为,少申请一些非必要权限,少运行一些后台活跃唤醒服务。

 

  1.  AppOpsManager.java

Glide框架高斯模糊图片处理

要素: Glide; TransformationRenderScriptScriptIntrinsicBlur;

对于不需要看废话的请直接Show me the code

对于模糊处理,一般的解决方案有四种:

  1. Java实现的算法处理;
  2. NDK实现的算法处理;
  3. RenderScript处理;
  4. openGL处理;

这四种方案的性能考虑的话,一般来讲应该是: 1 < 3 < 2  < 4 (2、3的性能非常接近),不过当属RenderScript方式最为简便(很显然嘛,平台无关性)。

RenderScript是Android自SDK17提供的一套平台无关计算密集脚本,它使用C99语法脚本,可以实现高性能的计算,而其包含大量内联函数,其中就包括了我们今天用到的:ScriptIntrinsicBlur,这是一个高斯模糊处理内联函数,一般系统用来进行阴影的计算处理。

上面有提到RenderScript是自SDK17引入的,但是Android 团队为我们提供了RenderScript support library,而起在Gradle-base的项目中的引入也极其简单,仅需要在module build.gradle设置以下11、12两行即可:

接下来简单说说 ScriptIntrinsicBlur,使用它虽然很方便,但是也是有弊端的,模糊radius不能超过25.0f,不过我们可以通过缩小原图抽样的方式变相的进行扩大半径。

Glide是一个优秀的图片加载缓存处理等一系列功能的框架,它优雅而且使用渐变,扩展也很容易,Glide就提供了自定义Transformation的方式进行扩展图片的处理

到了这里就是通过自定义Transformation的方式,详细的这里就不赘述了,感兴趣可以查看Glide官方文档:Transformation。需要特别提到的是,每个Transformation都有一个String getId()的回调,该ID用于在对处理后的图片进行缓存时的文件命名,这样当下次相同图片使用相同Transformation时,则无需任何实际处理,直接读取缓存文件,所以我们实现时的ID需要同时关联所有的调整参数,参数改变的ID也应该相应改变。下面就是我自定义的BlurTransformation

使用起来也是非常简单:

 

Gist: https://gist.github.com/ligboy/eee784aa57f40a615179

Android Studio Getter & Setter Template

众所周知Android Studio基于开源版的Intellij IDEA,因而具有极其便利的代码辅助功能,其中Getter & Setter生成就是其中之一,然而在Android开发时,因为Code Style for Android 规定私有的成员变量以“m”,静态私有成员变量以“s”开头的驼峰法命名:

Follow Field Naming Conventions

Non-public, non-static field names start with m.
Static field names start with s.
Other fields start with a lower case letter.
Public static final fields (constants) are ALL_CAPS_WITH_UNDERSCORES.

然而这在使用Android Studio默认的Getter & Setter 生成时会出现类似这样的情况:

插件AndroidAccessors可以处理Android代码规范生成Getter Setter这种情况,然而这个插件并不完美。而且Idea本身的getter setter生成规则是可以通过模板文件设置的,所以我们完全可以通过添加自定义规则的方式来实现Android编码规范的Getter Setter生成。

以下就是Android Studio默认的Getter及Setter模板:

Getter – Intellij Default

Setter – Intellij Default

Setter – Builder

可以看出这是某种模板引擎语言,请教了“撸大神”,被告知应该是Velocity模板引擎,原谅我的无知健忘,竟然一点印象都没有。

然后我们需要做的就很简单了,依葫芦画瓢,在原处理的基础上在进一步将$name做去除s及m前缀处理即可得到想要的结果,我定义了Getter:Android,Setter:Android、AndroidBuilder三个模板。以下附上自定义模板源码:

Getter:Android

Setter:Android

Setter:AndroidBuilder

附上Github Gist 地址: https://gist.github.com/ligboy/0eae9ecffc694595d40e

  1. 关于Velocity https://github.com/putaoshu/jdf/blob/master/doc/core_vm.md

Terminal 更新Android SDK

因为公司持续构建系统的Android SDK升级需要,不能在图形界面进行操作升级,所以搜集了以下资料,学习$ANDROID_HOME/tools/android 的命令行参数。

更新sdk的命令行帮助信息如下:

屏蔽掉images、source、sample等构建无用的模块

android -s update sdk -u -t "extra-android-support,extra-google-m2repository,extra-google-google_play_services,extra-android-m2repository,platform-tools,tool,platform"

 

其实升级的最大问题就是万恶GFW的阻挠问题,也就是设置代理问题。对于android sdk的更新的代理设置有多种方式.

一种是在 ~/.android/.androidtool.cfg 中指定,如果之前没有运行过sdk manager,该文件可能不存在,自己创建即可。文件的内容如下:

另外一种是实在更新命令中指定代理参数:

$ANDROID_HOME/tools/android update sdk --proxy-port proxy.example.com --proxy-port 8080 -s -u -t "1"

Provided Scope in Android Studio

provided scope包引入方式就是,项目编译时只包含对库的classpath引用,但是一并打包库到编译的项目中,一般情况是目标运行环境或容器已经包含了该库。

Android Studio自从0.4.3((Gradle 0.8)版本就引入Provided Scope库编译选项[1],但是我一直都没有试验成功,之前都是使用AS(Android Studio)打开eclipse的项目才可以。来到Android Studio beta 0.8.2版本,在AS的Project Structure Setting的module dependencies里面的scope选项里provided竟然消失了,手工修改项目build.gradle依然不行。 

 

在Android Issues看到很多人反馈的bug请求,其中一篇比较早的Google工程师提到可以使用Android-apt第三方gradle插件来解决provided引入问题[2]。我试验了下,测试通过。

 Android-apt的项目地址:https://bitbucket.org/hvisser/android-apt/overview

在项目公共build.gradle中插入

 

然后在项目build.gradle中插入:

 

如上面代码所示,如果想使用provided方式引入项目,格式为: apt ‘com.google.code.gson:gson:2.2.+’ 

参考资料:

  1. http://tools.android.com/recent/androidstudio043released
  2. https://code.google.com/p/android/issues/detail?id=65898#c7
  3. https://bitbucket.org/hvisser/android-apt/overview

 

Android Studio 使用的琐碎问题

1.在升级Android Studio后,特别是版本升级涉及到了gradle时,常会在打开老项目时遇到这个错误:“Gradle xxxx project refresh failed” 这个错误的原因具体我不太明白,我在这里看到大家的解决办法,我在实际中就是删除了项目根目录下的/gradle/里面的内容,然后 Sync Project with Gradle files.