../img/avatar.png

This Tinggeng

Activity 在横竖屏切换情况下的生命周期变化

概述 Activity 在横竖屏切换的时候,生命周期是不一样的,本地通过打印 log 的方式,看下区别.测试的机器是 Android6.0 . 不做任何配置的情况下 第一次启动 1 2 3 D/LifeCircleActivity: onCreate() called with: savedInstanceState = [null]Activity对象的地址:cn.steve.activitylifecycle.LifeCircleActivity@de950fc D/LifeCircleActivity: onStart() called D/LifeCircleActivity: onResume() called 第一次切换成横屏 1 2 3 4 5 6 7 8 9 D/LifeCircleActivity: onPause() called D/LifeCircleActivity: onSaveInstanceState() called with: outState = [Bundle[{android:viewHierarchyState=Bundle[{android:views={16908290=android.view.AbsSavedState$1@80a47f5, 2131296581=android.view.AbsSavedState$1@80a47f5, 2131296815=android.view.AbsSavedState$1@80a47f5}}], key=x}]] D/LifeCircleActivity: onStop() called D/LifeCircleActivity: onDestroy() called D/LifeCircleActivity: onCreate() called with: savedInstanceState = [Bundle[{android:viewHierarchyState=Bundle[{android:views={16908290=android.view.AbsSavedState$1@80a47f5, 2131296581=android.view.AbsSavedState$1@80a47f5, 2131296815=android.view.AbsSavedState$1@80a47f5}}], key=x}]]Activity对象的地址:cn.steve.activitylifecycle.LifeCircleActivity@266fbfb D/LifeCircleActivity: onStart() called D/LifeCircleActivity: onRestoreInstanceState() called with: savedInstanceState = [Bundle[{android:viewHierarchyState=Bundle[{android:views={16908290=android.

Service 的生命周期

概述 Service 有两种启动方式,一种是 startService ;一种是 bindService.这两种的启动的 Service 的生命周期有些许差异,并且当二者混用的时候,有一些需要注意的地方.这里用打印 log 日志的方式记录下生命周期的差异. 仅 startService 触发 startService 方法 1 2 D/ServiceLifeService: onCreate() called D/ServiceLifeService: onStartCommand() called with: intent = [Intent { cmp=cn.steve.study/cn.steve.servicelifecycle.ServiceLifeService }], flags = [0], startId = [1] 退出APP 无回调 再次进入APP,触发startService 方法 1 D/ServiceLifeService: onStartCommand() called with: intent = [Intent { cmp=cn.steve.study/cn.steve.servicelifecycle.ServiceLifeService }], flags = [0], startId = [2] 杀死 App 进程 没有回调,直接被系统杀死。只有一些AMS系统回调 1 2 W/ActivityManager: Scheduling restart of crashed service cn.steve.study/cn.steve.servicelifecycle.ServiceLifeService in 1000ms I/ActivityManager: Force stopping service ServiceRecord{38ffaacf u0 cn.

Annotation 使用备忘

概述 本文记录使用 javapoet 以及 auto-service 进行编译时注解的过程以及注意点. 最近又使用了一次编译时注解,期间产生了不少问题. 术语的解释 Element 这个代表被注解的元素.这个类有个很重要的方法,getEnclosingElement:这方法的含义是获取 包裹 element 最外围的元素.比如类的最外围的元素是 package. 1 PackageElement pkgElement = (PackageElement) element.getEnclosingElement(); 其他方法都很简单. javapoet 库中一些重要的接口和方法 TypeName: 对应了 java 代码中的一个类型元素,常用于声明一个方法参数,还有一些 collection 范型使用. 1 2 // 用来定一个 ComponentInfo 类的元素类型 TypeName mComponentInfoClassName = ClassName.get(ComponentInfo.class); ParameterizedTypeName 用来声明一个方法的参数.有个 get 方法,这个方法第一个参数是声明原生的类型,后面一个可变参数,声明第一个参数的参数. 1 2 3 4 5 6 7 8 // 声明一个参数的类型是 Map<String,List<ComponentInfo>> ParameterizedTypeName paramListComponent = ParameterizedTypeName.get(ClassName.get(List.class), mComponentInfoClassName); ParameterizedTypeName moduleLoaderParameter = ParameterizedTypeName.get( ClassName.get(Map.class), ClassName.get(String.class), paramListComponent ); ParameterSpec 这个类代表方法的参数 1 2 // 声明一个方法的参数是:final Map<String,List<ComponentInfo>> targetMap.

webview中关于服务端重定向的判断

背景 由于 H5 页面打开都比较慢,为了减少返回时候的刷新,所以有时候需要多开,就是每个 url 都是在一个新的 activity 中打开.一般的处理方式是在 shouldOverrideUrlLoading() 方法中进行处理,这个方法按照 SDK 中的说明是当 url 发生变化时就会回调,当遇到服务端重定向的时候,就会出现一个空白页面的情况,所以我们需要判断是否是重定向,对于重定向进行特殊的处理. 困难 1 2 3 4 public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { return shouldOverrideUrlLoading(view, request.getUrl().toString()); } 在 Android7.0 ,新增了 WebResourceRequest 接口,接口中有个判断是否是重定向的方法,但对于低版本的该如何判断呢? 可以做如下判断. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 WebViewClient webViewClient = new WebViewClient() { private boolean mLoaded = false; @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if (mLoaded){ //not redirect }else { // is redirect } return true; } @Override public void onPageFinished(WebView webView, String url) { mLoaded = true; } }; 因为能回调 onPageFinished 方法,都是有渲染页面的操作,说明页面是有内容的,对于服务端重定向而言,是没有内容的,所以就不会走 onPageFinished 方法,通过这个间接的判断页面是否是重定向的.

IPC_Binder_java_2

概述 本文作为第一篇的补充,补充一下第一篇遗漏的内容,主要谈一下,缺少的概念,技术背景等内容. Why为什么需要Binder Binder 是 Android 系统进程间通信(IPC)方式之一。Android 是基于 Linux 内核的,Linux 已经有很多 IPC 方式,为何还需要一个新的 IPC 方式. Linux已经拥有 管道 system V IPC Socket 等IPC手段。 却还要倚赖Binder来实现进程间通信。 Binder具有无可比拟的优势。 或者可以说,Android系统对进程间有什么特殊的需求是传统其他 IPC 无法完成或者无法很好完成。 基于Client-Server的通信方式广泛应用于从互联网和数据库访问到嵌入式手持设备内部通信等各个领域。 智能手机平台特别是Android系统中,为了向应用开发者提供丰富多样的功能,这种通信方式更是无处不在,诸如媒体播放,视音频频捕获,到各种让手机更智能的传感器(加速度,方位,温度,光亮度等)都由不同的Server负责管理,应用程序只需做为Client与这些Server建立连接便可以使用这些服务,花很少的时间和精力就能开发出令人眩目的功能。 Client-Server 方式的广泛采用对进程间通信(IPC)机制是一个挑战。 只有socket支持Client-Server的通信方式。当然也可以在这些底层机制上架设一套协议来实现Client-Server通信,但这样增加了系统的复杂性,在手机这种条件复杂,资源稀缺的环境下可靠性也难以保证. 传输性能角度: socket作为一款通用接口,其传输效率低,开销大,主要用在跨网络的进程间通信和本机上进程间的低速通信。 消息队列和管道采用存储-转发方式,即数据先从发送方缓存区拷贝到内核开辟的缓存区中,然后再从内核缓存区拷贝到接收方缓存区,至少有两次拷贝过程。 共享内存虽然无需拷贝,但控制复杂,难以使用。 安全性角度: Android作为一个开放式,拥有众多开发者的的平台,应用程序的来源广泛,确保智能终端的安全是非常重要的。终端用户不希望从网上下载的程序在不知情的情况下偷窥隐私数据,连接无线网络,长期操作底层设备导致电池很快耗尽等等。 传统IPC没有任何安全措施,完全依赖上层协议来确保。 传统IPC的接收方无法获得对方进程可靠的UID/PID(用户ID/进程ID),从而无法鉴别对方身份。Android为每个安装好的应用程序分配了自己的UID,故进程的UID是鉴别进程身份的重要标志。使用传统IPC只能由用户在数据包里填入UID/PID,但这样不可靠,容易被恶意程序利用。可靠的身份标记只有由IPC机制本身在内核中添加才能确保安全性。 传统IPC访问接入点是开放的,无法建立私有通道。比如命名管道的名称,system V的键值,socket的ip地址或文件名都是开放的,只要知道这些接入点的程序都可以和对端建立连接,不管怎样都无法阻止恶意程序通过猜测接收方地址获得连接。 效率角度 从对比图可以看出,Binder 在效率上是有优势的. What Binder 是什么 因为 Binder 也是 CS 架构的一种,而 CS 架构最典型的就是 TCP/IP 请求了.下面做个对比,顺带类比以下 Binder 中的几个关键的概念. 背景 在开发中,经常需要通过 getSystemService 的方式获取一个系统服务,那么这些系统服务的 Binder 引用是如何传递给客户端的呢?要知道,系统服务并不是通过 startService() 启动的。 ServiceManager 管理的服务 ServiceManager 是一个独立进程,其作用如名称所示,管理各种系统服务.

记录WebView的file协议的cookie跨域问题

why 在做 hybrid 框架的时候,发现以 file 协议打开的文件,存在 cookie 跨域的问题.以做记录. what 以 file 协议打开的文件,页面内存在新的跳转,跳转数据通过 cookie 传递,发现cookie 不能正常传递. how CookieManager 存在一个静态方法,可以打开 file 协议的 cookie. 1 boolean allowFileSchemeCookies () 这是个静态方法,打开之后,整个 APP 的 webview 就都打开了. 参考文献 [官方文档](https://developer.android.com/reference/android/webkit/CookieManager.html#allowFileSchemeCookies()