Android打印机项目 涉及的技术:
APP部分:
系统打印插件API
APP基础:Activity、Broadcast、Service(四大组件中的三个)
UI制作(Activity、Fragment、Dialog、Handler、各种Layout、Button、Listview)
JAVA调用命令行使用Stream
线程池(管理命令的异步执行)
多线程同步(使用了synchronized、wait/notify,等待命令的stdout/stderr通道结束)
AIDL(与通知栏进程通信,发送打印状态)
Parcelable(数据序列化,给AIDL使用)
界面逻辑分离(MVC)
单例模式(线程池)
字符串匹配
移植CUPS部分:
Change Root
Android权限管理(添加自定义USB权限)
Linux程序动态链接程序运行原理
Linux系统调用
Shell脚本
CUPS的运行流程(epoll管理、PPD文件指定渲染流程、前后端过滤器、libusb连接USB打印机)
Android源码编译、添加系统程序
Android打印机项目 遇到的坑
1. AlertDialog如何在非APP界面弹出
alert.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
但是在有的系统上无效。
2. PrintJob只能在主线程操作,否则操作无效
(原因?)
3. APP进程退出,后台运行的CUPS进程也会退出,保活问题
在Android中,APP所在进程被杀死,其启动的子进程也会被杀死。
解决方案一,在APP被杀死时,启动一个定时器,几秒后唤醒一个service。。。(暴力方法)
解决方案二,使用AIDL,启动两个APP/进程。
(原因?)
4. Intent跨进程发送Parcelable数据,双方的类名必须相同
反序列化时类名,包括所在包名,必须完全相同。
5. 记得PrintJob是final类,而且不能Parcelable,使用反射来调用内部方法的。
但是找了半天,找不到在哪用的。。。
6. 在调用类的wait、notify方法时,必须使用synchronized。
防止并发操作,导致出错。
7. 调试网络打印时,发现无法打印,有问题。
使用tcpdump和wireshark抓包,发现无法打印的问题不在传输上。
8. USB打印出现问题,无法打印。
使用starce抓取系统调用,结合CUPS源码,发现问题出现libusb上面,自行编译libusb库解决。
9. 在AIDL中map不能使用泛型等
不使用泛型,可以用强转
10. 使用hpcups过滤器,无法使用以usb开头的地址。
在ubuntu中,系统会自动转换地址为 hp 开头,因此编写地址转换脚本,进行动态转换
Android打印机项目 如何组织项目
借助git,在github平台上通过issue以及fork + Pull 模式协作。
每周开会沟通进展、问题。
Android打印机项目 改进:
发现多线程执行任务有改进空间
public int waitFor() throws InterruptedException {
waitForInterruptibly(handle);
if (Thread.interrupted())
throw new InterruptedException();
return exitValue();
}
java里可以waitFor() 到进程完成,不用开两个输出进程。
调用Runtime.getRuntime().exec()执行Linux脚本导致程序挂住的问题分析
http://flyneil.iteye.com/blog/1601301
优化方案:执行exec()的线程处理标准输入,再开一个线程处理错误输入总共只需要两个线程。因为执行exec()的线程是空闲的,所以可以用来处理标准输入。在处理完标准输入之后,执行process.waitFor(),等待线程结束即可,不用自己创建锁了。
说一说感觉收获最大的项目
只记得清Openthos打印机项目了,所以就说它
0 项目介绍
Openthos打印项目是开源操作系统的一个子项目,我们为Openthos系统提供打印功能。Openthos是清华大学和同方、一铭等公司学校合作开发的基于Android的桌面操作系统。由于Android系统没有打印功能,因此我们考虑移植桌面Linux系统中的打印功能到Android中。桌面Linux都使用CUPS程序,作为打印服务,CUPS是打印管理程序,配合cups-filter和打印驱动就可以实现本地和网络打印。我们将CUP及配套程序全部移植到Android系统中,并且对接Android打印框架,实现打印。
Linux中一个程序要运行需要 动态链接库(如果有)、可执行文件和动态链接器三类文件。
可执行文件在Linux中是ELF格式。动态链接器文件读取可执行文件,根据文件里指向的动态链接库地址,获取动态链接库。用ldd命令可以看到。
可执行程序运行时,动态连接器就会根据函数名,从符号表中定位函数在哪,从而获取函数代码。
所以我们把程序在ArchLinux上编译好后复制可执行文件,动态连接器以及通过脚本复制所需的动态链接库,因为动态链接库是递归调用的。
这样程序就可以在Android中运行了。但是程序里的各种文件位置,包括配置文件,动态链接库文件等是绝对地址,直接复制到Android的相同地址会破坏Android系统的结构,因此我们使用proot实现了一个子系统。
proot类似chroot,它不同于chroot需要root权限调用chroot系统调用,实现重定向根目录。proot使用ptrace,类似于父进程调试子进程,从而能够修改子进程所有系统调用中的文件地址。
然后再编写Android客户端,通过命令行调用cups的命令实现打印。
在这过程中,遇到了很多棘手的问题,通过查看大量的日志、系统调用及源码才解决。比如usb不打印和hp打印机不能用的问题。
1 研究深度
为了解决CUPS的移植问题,必须从大量的日志、系统调用及源码中寻找线索,而不仅仅是使用CUPS而已。
在Android上,通过这个项目接触了Android源码,编译系统应用,修改通知栏等。
通知栏文件
frameworks/base/packages/systemUI/res/layout/status_bar_expanded.xml
frameworks/base/packages/systemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
通过Broadcast发送打印信息。
2 协同开发
使用github托管代码,用git与其他人合作开发。
除了github上的仓库,还要将程序合并进内部的Openthos的源码中。
所以我们要管理两套仓库。github上通过git commit,内部通过使用git patch将更新合并进系统源码中。
在 git patch合并过程中,负责管理源码的工程师将会对代码进行review,只有符合规范,才能合并。合并完成后,将Patch信息发送到Openthos项目组的邮件列表中。
软件开发者:
编写好代码 -> 使用git diff检查代码改动 -> git add ... -> git commit -m "..." -> git format-patch HEAD^ 并适当修改描述信息 -> 把patch发送到管理者邮箱
代码管理者:
从邮箱下载patch -> 查看patch是否可用 -> 适当修改后git am xxx.patch -> 发送邮件通知社区已合并该patch
Bug管理使用禅道,在上面统一管理每个人的任务。
每日写总结,记录当天的工作。每周开会总结。
3 代码规范
合并代码过程中,由于管理源码的工程师要求,我对代码规范有了新的认识。
- 成员变量以m开头,驼峰命名
- 一行代码不超过100行
- 注释简洁,在重要代码上方,勿滥
- 注意有些代码语句块之间有一个空格,比如 if else
- 代码段分割,只需要一行空格
- 代码折叠时,逗号在上一行
搜集HR面试相关的问题
十个HR常问的尖锐问题及回答技巧
https://www.douban.com/group/topic/42025176/
- 你的业余爱好?
倒腾手机、倒腾电脑。
学习摄影,但是这个太难了,还没入门。
弹吉他,这个算入门了,会几首。
- 谈谈你的优缺点?
优点:
善于自学。
独立解决问题的能力较好。
有些幽默感。
善于反思自己的不足。
缺点:
有的时候过于追求某个不重要细节,做了一大堆相关工作,结果把重要的事延后了。比如,一个工具不顺手,然而这个工具的使用次数可能不顺手,我也要找到最好用的工具替换原来的。
不善于表达,很多事情我认为理所当然,但是我没解释,别人不知道。比如:解释一个技术上的事。
但是我正在尝试改善,加强自己的表达能力。
- 介绍你一次最失败的一次经历
考cet6考了4、5次才过,理由都是没时间看。其实都是安慰自己的话。时间是可以挤出来的,虽然我这次考得不高,但是过了。
- 在腾讯有没有亲戚
没有亲戚,但是有师兄算吗。
- 项目中遇到什么困难
在遇到技术难题时,没有人可以给予直接帮助,老师只能从大方向上给予思路,实施还是靠自己。比如:遇到usb打印无响应,网上搜不到,这种细节问题老师没遇到过。我只能思考所有可能的解决方法,一个个试,从问题的边缘一点点向中心靠近。
- 为什么来西安读研
因为当时工作不好找考的研,南邮竞争太大了。现在一想,读研的确是一件非常必要的事情。读研以来,我对专业上的思考更深入了,对生活的理解也更上一个层次。以前觉得读书没用,可能是因为以前我学习的是通信,我对通信不感兴趣。现在觉得,读书很重要。读书无论是对专业知识的提升,还是对自己思维上的提升,都非常明显。我自己感觉我思考事物的维度明显比以前更高了。在工作也应当保持学习的状态,不断学习不断前进。
- 你期望的工作地点
深圳、北京、上海都可以。虽然我家是南京的,但是我不介意去外面,虽然上海离家近,但是我更看重的是工作的前景、发展,离家远也没关系。我希望我能尽可能的追求我喜欢的东西(技术),所以其他的事情可以靠后一点,包括结婚生子。
- 为什么应聘我们公司/看重公司的什么
看中公司的平台,薪水不是最重要的,重要的是能够在这个平台上进步。
自定义控件-仿QQ导航栏-跟手导航条
http://blog.csdn.net/bboxhe/article/details/70145502
见 学习 Android笔记
ZYF师兄说可能会问的:
HXP:
1. 给我介绍下Openthos这个项目吧,以及你在这个项目中承担什么工作职责
2. 给我说说什么是OOP?知道AOP吗? 两者有什么不同
3. 设计模式有了解吗?,你用过哪些设计模式
4. 给我简单说说安卓中的ListView实现原理吧
5. 我问一些数据结构的问题吧,如果快速的逆转一个链表,复杂度是多少(还会问一些经典数据结构的复杂度等等)
6. 对JAVA的并发有了解吗?,给我说说hashmap和concurrenthashmap 的区别
TY:
1. 给我简单说说Hadoop flume, kafka, hive这些大数据平台下的工具(面试官或许会选一个让你说,或者让你自己选)
2. 给我说说flume的工作原理
3. zero-copy的原理是什么
4. TCP/IP中的TIME_WAIT状态的用处是什么?
5. TCP/IP中为什么要三次握手
YM:
1. 你是如何采集性能数据的,给我简单说一下
2. VMware和Vsphere,CloudStack还有openstack这些有什么不同
YM的简历技能那块写的太范,我不知道该问什么了。TCP/IP JAVA相关的问题参考我问之前同学的问题吧
ZHL:
1. 什么是并行测试
2. 你用过哪些测试工具,给我简单说下
3. 什么是黑盒测试,什么是白盒测试
4. 我看你没什么测试相关的经验,你为什么想要做测试
TCR:
1. 给我简单说说jvm中的垃圾回收算法,以及你如何调优
2. linux IO复用中的select和epoll的相同之处,不同之处,各自优缺点
3. 网络设计模式有了解吗?,同步异步,阻塞,非阻塞,这些概念是什么意思?
4. docker目前存在哪些问题?,docker的网络你了解吗?(扩展性问题)
ALLGO -- 基于 Android 的组织活动平台
xUtils的原理
- View模块主要的功能是通过注解绑定UI,资源,事件。
- Db模块是一个数据库orm框架, 简单的语句就能进行数据的操作。
- Http模块主要访问网络,支持同步,异步方式的请求,支持文件的下载。
- Bitmap模块是加载图片以及图片的处理, 支持加载本地,网络图片。而且支持图片的内存和本地缓存。
View模块:注解和反射
Db模块:注解、反射
Http模块:网络数据缓存、Handler、线程池
Bitmap模块:二级缓存(运行缓存、闪存缓存 )、线程池
参考:
http://a.codekk.com/detail/Android/Caij/xUtils%20%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90
服务器:
Servlet
Filter
一个有意思的地方:如何实现单点登录
其他
使用JAVA定时打日志
发现JAVA定时器或者newScheduledThreadPool会有毫秒级的延迟,造成定时打log的时间越来越迟。
解决方法,定时任务执行时,通过手动计算本次延误的时间,减去这部分时间再定时下一个任务。
猜想原因:因为CPU轮转不可能每次都准时轮到该程序。
以前本科面试问过的
如何断点续传
本地数据存储的几种方式
子线程如何更新UI
不同线程如何通信
数据库操作流程
Fragement和activity的区别
两个activity如何相互传递数据
安卓界面构件的发展变化
不同进程间的通信AIDL
web server的和客户端的数据传递
activity的生命周期
fragment的生命周期
json解析的方式
app如何后台运行
app如何自启动
横竖屏切换activity的变化
后台推送如何通知用户有消息
content provider作用
listview 几种优化