本章涉及知识点
1、前言
2、案例流程
3、遍历SD卡相册目录
4、OKHttp3批量上传
5、Loading动画的启动和关闭
6、BroadcastReceiver广播组件
7、唤醒第三方App
8、AccessibilityService服务组件
9、案例结果演示
10、心得体会
一、前言
笔者7年没开发Android了,今天突然有兴致想写写原生Android代码,顺便回忆一下Android开发的配置,四大组件通信逻辑,和服务器交互逻辑等,为此写了个小案例将上述的知识点串联起来,当做一个知识回顾吧
二、案例流程
我们写一个案例demo,分两个场景来串联知识点
(1)主动上传:这个非常简单,用Activity实现即可,用户点击上传按钮,带动画的一键上传相册到服务器
(2)隐式上传:为了同时串联BroadcastReceiver和AccessibilityService,我们创建一个场景,监听手机网络状态,当网络改变时,唤醒第三方应用App,并在打开App后上传相册到服务器
三、遍历SD卡相册目录
首先获得SD卡的根路径,数码相机拍摄到照片一般位于/DCIM/Camera文件夹中,得到所有图片路径后返回列表
从SD卡获取所有的图片资源封装出提取相册照片路径的方法
遍历出SD卡相册所有照片的路径四、OKHttp3批量上传
得到相册列表路径后,我们需要批量上传到服务器持久化,这里我们使用OKHttp3来做httpClient请求网络,而请求的方法分为同步请求和异步请求
(1)同步请求:需要显示的开启子线程,请求成功后需要跳转到UI线程修改UI
(2)异步请求:不用显示的开启子线程,但是回调方法是执行在子线程中,所以请求成功后也需要跳转到UI线程修改UI
这里我们选择异步的post请求来做图片批量上传
批量上传照片我们以formdata的形式来提交表单数据,并在回调函数里接收服务器返回的结果,由于在得到服务器结果后可能需要更新UI(如关闭loading动画等),而回调函数是执行在子线程中,所以我们如果需要在此时更新UI,需要跳转到UI线程,这里我们使用Android的handler来传递/监听消息来在UI线程里更新UI
贴上后端批量上传接口,这里我们用NodeJS来实现
后端批量上传接口五、Loading动画的启动和关闭
主要运用在主动上传相册的场景中,需要用户点击上传按钮后,伴随着批量上传数据和显示loading动画,而在接收到服务器结果后(如上传成功)需要关闭loading动画
关于遮罩层,我们单独封装出一个类LoadingDialog来继承原生AlertDialog类,并在该类中引入动画
遮罩层+loading动画关于loading动画,这里我们选择所用第三方AVLoadingIndicatorView来做加载动画,并在配置文件里完成注册
LoadingDialog的配置文件我们简单编写一个继承AppCompatActivity类的photoUploadActivity来做主动上传相册的前端界面
主动上传相册Activity我们在点击按钮的时候,启动遮罩层动画,在做完一系列逻辑提交后,用handler来接收消息(字线程中异步函数传递消息)关闭遮罩层动画,其配置文件为
photoUploadActivity的配置文件以上知识部分我们就完成了主动提交相册的场景,接下来我们来做隐式提交的场景
六、BroadcastReceiver广播组件
根据案例流程,我们首先需要监听网络状态,为此我们引入BroadcastReceiver来做广播
首先在AndroidMainifest里注册广播接收器
广播接收器注册在action里我们注册监听了网络状态变化的行为,然后我们编写MyReceiver类继承BroadcastReceiver
MyReceiver类在这个类里,我们在注册好的广播里,接收网络状态变化并唤醒第三方App,这里我随便选择了阿里钉钉
七、唤醒第三方App
我们单独封装出该方法,通过packageManager来打开包名对应的第三方App
唤醒第三方App八、AccessibilityService服务组件
接下来为了串联AccessibilityService知识,我们简单在打开的第三方App里,进行一些自动化操作(和python的Selenium相似),这里演示在进入钉钉主页后,点击工作按钮进入工作页面
AccessibilityService获取界面组件有两种方法
(1)findAccessibilityNodeInfosByViewId:根据Android组件的ID来获取组件,如果是动态ID,需要在Hierarchy View查看对应view的ID,这里就不展开了
(2)findAccessibilityNodeInfosByText:根据Android组件的value来获取组件,注意是模糊搜索,得到的组件是一个列表
尤其注意一点,AccessibilityService只能过去原生Android组件,所以如果界面使用webview开发的,那么我们只能获取到webview组件,对于webview中html或者Javascript写的dom,AccessibilityService是无法获取到的!比如钉钉的工作界面里的九宫格布局(包含签到按钮),就是用webview来load网页的
首先在AndroidMainifest里注册AccessibilityService服务
注册AccessibilityService在项目的res/xml下新建关于AccessibilityService的配置文件
AccessibilityService的配置文件这里响应的事件是全局事件typeAllMask,使用通用的反馈feedbackGeneric,注意要设置canRetrieveWindowContent=true,这样才可以获取到界面的根节点
接下来我们编写MyAccessibility类继承AccessibilityService,通过实现onAccessibilityEvent方法来接收监听到的事件执行业务代码,业务代码很简单,通过index来switch到相应的逻辑处理,如index=1执行模拟点击app的按钮进入相应的页面,index=2执行隐式上传相册图片到服务器
MyAccessibility类 通过文字执行点击操作 遍历可点击按钮九、案例结果演示
主动上传相册结果
主动上传相册结果当网络状态改变时,自动打开第三方App
网络状态改变打开第三方模拟自动化点击App中的工作按钮,进入工作界面
自动化点击App中的工作按钮隐式上传相册
隐式上传相册十、心得体会
写这个案例的目的就是回顾一下Android编程的风格和各个组件的注册、监听和通信,把OKHttp3、BroadcastReceiver、AccessibilityService等知识串联起来运用
最后从开发者的角度来说,原生Android的功能确实很强大,在实际项目里原生Android做功能强交互,webview做信息展示UI可以得到很好的开发体验,当然root后结合比如Xposed框架更能可以产生更多的黑魔法
案例代码见:Android知识串联—主动/隐式上传相册
网友评论