2014年03月 存档

细说ItemInfo

2014年03月28日,星期五

(系列文章点这里)

要理解ItemInfo,就要先理解桌面有哪几种东西,即有哪几种Item。

  • 小工具:就是AppWidget,时钟小工具,天气小工具,等等。
  • 快捷方式:快速启动应用的图标,一个应用可以有多个重复的快捷方式,workspace和hotseat上的都是快捷方式
  • 文件夹:可以把多个快捷方式放到一块的,用来分类,减少屏幕空间占用。

这些东西都一些共同的,可以抽象出来的东西,有自己的宽度和高度,都有所在的位置和第几等等,而ItemInfo就是抽象出来的东西,打开ItemInfo.java,其中包含的就是这些特征,然而,最关键的是ItemInfo对象和数据库记录是一一对应的。其中有个id的成员,代表的就是数据库中ID。

对于不同的item,ItemInfo也有不同的子类,小工具对应的是LauncherAppWidgetInfo,他增加了小工具的信息(查android文档:AppWidgetProviderInfo);快捷方式对应的是ShortcutInfo,他增加了启动一个Activity所需的Intent信息;文件夹对应的是FolderInfo,他增加了文件夹是否打开的标签,文件夹内图标的信息等等。

ItemInfo的成员有几个值得说说:
(更多…)

Launcher3的启动流程(一)

2014年03月23日,星期日

(系列文章点这里)

Launcher3作为一个用户经常使用,常驻内容的应用,运行时维护着许多信息,而这些信息都需要在开机的时候加载完,今天就来分析下Launcher3是怎样一步一步启动的。

如果你手里还没有源码,请点击这里,编译并让他在你的手机上运行。然后打开Eclipse,一步步跟着走。

在启动Launcher这个Activity之前,先看下桌面的LauncherApplication吧,任何一个组件(Component)启动之前都会启动他的。代码只有寥寥几行。

LauncherAppState我们在上一篇博客里面说过,主要用来初始化对象,注册广播接收器等等,这些都在他的构造方法里面完成了。这里监听的广播有应用的安装、卸载和更新,SD卡上应用的可用或不可用,地区变化和配置变化等等。接收应用安装更新什么的广播,都是为了方便实时更新桌面上的图标,如果用豌豆荚安装了应用会在桌面上马上显示出来,这都是这些个广播接收器在发挥作用。需要注意的是贯穿始终的LauncherModel就是在这个构造方法里初始化的。

准备工作做好了,就开始启动Launcher Activity。Activity的启动从onCreate开始查找。
(更多…)

Launcher3中的常用类

2014年03月21日,星期五

(系列文章点这里)

除了上一篇博客中布局需要用到的几个类,还有一些类是我们在代码中随时可能遇见的。

LauncherModel:从名字我们可以看出他跟数据有关系的,保存了桌面运行时的状态信息,也提供了读写数据库的API,他有一个内部类LoaderTask,桌面启动从数据库中读取数据并把图标和小工具添加上去的时候用的就是他。

BubblTextView:图标都是基于他,不过奇怪的是,他是继承自TextView,我之前一直以为是一个线性布局,上面放图片,下面放文字。

DragController:DragLayer只是一个ViewGroup,具体的拖拽的处理都放到了DragController中。

LauncherAppState:单例模式,主要在启动的时候用,他初始化了一些对象,并且注册了广播监听器和ContentObserver。

DragView:在拖动图标的时候跟随手指移动的View就是他。

DragSource,DropTarget:跟拖拽相关的接口,DragSource表示图标从哪里被拖出来,DropTarget表示图标可以被拖到哪里去。

Folder:文件夹打开时候那个view。

FolderIcon: 文件夹图标。

LauncherProvider:数据库类,Launcher3使用了SQLite,数据库文件保存在/data/data/包名/databases/launcher.db 下,有兴趣的同学可以把这个东西拷贝出来,用SQLite的工具看看里面都是怎么保存的。

ItemInfo:运行时保存了桌面上每个项目的信息,包括图标在第几屏,第几行第几列,高度宽度等信息,每一个ItemInfo对象都对应着数据库中的一条记录。在Launcher3源码路径下,会有很多以Info结尾的类,这些类都是ItemInfo的子类,具体代表了桌面上的某个项目。比如说FolderIcon和FolderInfo是对应的,BubbleTextView和ShortcutInfo是对应的,AppWidgetHostView和LauncherAppWidgetInfo是对应的。有了对应关系,可以这样通过view获取ItemInfo对象:

ItemInfo info = (ItemInfo)bubbletextview.getTag();

这样这里的info其实就是ShortcutInfo对象了。

之后我会专门写一篇讲解数据库、ItemInfo相关的博文,敬请期待

Launcher3 的布局和结构

2014年03月21日,星期五

(系列文章点这里)

首先你需要去 这里 下载下Launcher3的源码。这个是我从android源码里面拿出来的,修改删掉了一些东西,方便在eclipse上运行,你可以直接在手机上运行,有了代码和apk再来看说明,心理会很踏实的。

Launcher3其实最主要的是一个Activity,基本上所有的操作都集中在这个Activity上,在Launcher.java 当中,setContentView的参数是R.layout.launcher,我们暂时只研究下桌面竖屏的情况,相关源码在res/layout-port/launcher.xml。

请左手拿着你运行着launcher3的手机,右手打开launcher.xml,布局的最外面是一个FrameLayout,紧紧地包围了一个叫DragLayer的ViewGroup,他继承自FrameLayout,主要功能就是处理拖拽事件,当你在拖拽一个图标的时候,就是一个view放到了DragLayer里面,跟随你的手在移动。

下面在你的手机屏幕上左右滑,有好几屏,这个能滑的东西叫做Workspace,在布局文件里面可以看到的,Workspace能算是Launcher3代码里代码量前三的吧,他的父类的父类是PagedView,一个用来处理左右滑动的ViewGroup。那么Workspace里面可以滑动的单独一屏叫什么呢? 布局文件里面似乎没有写,其实是CellLayout,他负责的是图标和小部件的显示和整齐摆放。

接下来看你在滑动屏幕的时候看见下方有个指示器,告诉你桌面现在有几屏,当前是在哪一屏上。这个东西叫做PageIndicator,从名字就可以看出意义了。还有最下面的4个固定不动的图标,和中间一个Button显示所有应用,这整个叫做Hotseat,用来放置比较常用的应用,比如拨号,短信,相机等等。
(更多…)

如何用Discourse搭建一个论坛

2014年03月21日,星期五

Discourse是基于ruby on rails,Ember.js, PostgreSQL 和Redis的开源论坛,是由StackOverflow的联合创始人Jeff Atwood发起的,目的是成为下一代论坛,改变传统论坛的格局,成为论坛界的wordpress。

先说下我的使用感受吧,在try.discourse.org上可以体验的,首先是界面比较清爽,主体是白色的,很简洁。其次是摒弃了“板块”的概念,所有的帖子集中显示,用滚轮一直往下滑好了。然后是发帖和回复都十分方便,直接在当前页都可以完成,内容的编辑支持Markdown和BBCode,编辑的时候还可以在右侧直接预览,插入图片很方便,在网上看到一张图片之后可以右键复制图片,直接Ctrl+V就可以在编辑器内插入图片了,Discourse会自动完成复制并且上传到服务器上。

之前很早就用过Discuz!,但是这个论坛在国内用的实在是太普遍了,很多论坛的长的都是一个样子的。我感觉他最大的缺点是帖子中的每个回复都占用的很大的空间,在回复内容普遍很短的情况下,我每看一行回复都要滚动半个屏幕,这个最不能忍(哦对,还有坑爹的签名图片  = =)。Discourse做的比较合我胃口,一个回复的高度只有Discuz!的三分之一左右。

来说说安装吧,首先你要有个VPS或者云主机,可以使用阿里云,linode或者digitalocean等等,推荐内存是1G。

我安装的时候参照的是这篇文档 ,这个地方是以digital ocean为例来说明的,其他主机都大同小异。部署的时候需要用到docker,这个是个比较火的容器引擎,目前我还没有完全理解容器引擎到底指的是什么,“他可以打包引用和其依赖到linux上,实现虚拟化”,就当是个虚拟机好了恩。我选的是系统是Ubuntu 12.04.3 x64 LTS,按照文档上的教程升级了内核,我没有验证这一步是否是必要的,但是感觉虚拟化可能需要升级内核的东西,做了也无妨。

接下来是clone官方的docker镜像,修改配置文件app.yml,配置文件里面有几个需要注意的事情。ssh-key要设置,就是你从~/.ssh/id_rsa.pub拷贝到github上的那个东西,否则你没办法通过./launcher ssh app进入你的“虚拟机”。还有需要填写的是email地址和网站的host。邮箱相关的内容可能需要稍微折腾一点,我直接用的是mailgun的服务,maildraill貌似不让天朝的同学用,囧。。app.xml中邮箱配置的内容怎么填,mailgun里面都写的很清楚了,而且也说明了怎么在域名服务商那里添加邮件相关的记录。如果你嫌邮箱配置麻烦的话,就先略过吧。

最后执行./launcher bootstrap app和./launcher start app就可以让网站运行了。后续的折腾就是测试邮件是否配置成功,添加github,facebook,twitter的第三方登录功能了。如果你访问的时候出现了502错误,请检查你的内存是否只有512MB,内存小的话很容易出现这样的问题,出现这个问题的时候我一直搞不清楚哪里有问题,一直怀疑是配置错误,后来升级了内存之后就完全正常了。

还有一些缺点,由于网站很依赖javascript,SEO会比较差。其次中文本地化还不够完全,给官方提交什么的貌似比较麻烦。刚开始用,缺点应该还有很多没发现,不过看提交记录貌似挺频繁的,希望能越来越好。

我搭建了个论坛,域名是  http://android.hacking.today , 不过目前还不知道怎么搞。。当你搭建论坛的时候一定要想清楚到底该怎么搞,毕竟内容才是重点,用什么样的论坛不是最重要的。。

android触摸事件处理流程

2014年03月15日,星期六

(系列文章点这里)

最近在工作中,经常需要处理触摸事件,但是有时候会出现一些奇怪的bug,比如有时候会检测不到ACTION_MOVE和ACTION_UP,我决定下决心写个测试的小程序,来研究一个触摸事件从上往下是怎么传递和处理的。

先说下大概的流程吧,这个应该在很多博客中都有讲解:当一个事件来临的时候,会先传递给最外层的ViewGroup(比如LinearLayout,FrameLayout),如果这个ViewGroup没有去拦截这个事件的话,才会给传递给下层的ViewGroup或者View。如果被拦截掉的话,它会自己去处理这个事件,这个ViewGroup内的View将无法得知上层发生了什么。

ViewGroup的拦截事件的函数为

public boolean onInterceptTouchEvent(MotionEvent ev)

onInterceptTouchEvent的参数ev就是一个触摸事件,可以从ev获取到事件的坐标,类型,当前屏幕上点的个数等等。通常我们在继承ViewGroup的时候都会重写这个方法,判断目前需不需要拦截,即返回true还是false。返回true的时候表明事件不再往下传了,否则就往下传。那返回true的时候怎么处理呢?
(更多…)

在技术方面,我真是什么都想学

2014年03月3日,星期一

我发现我现在对各种技术都非常感兴趣,记得之前在学校的时候,大部分时间实在搞算法,用的c、c++等,对于java有着很强烈的抵触情绪,工作了之后,我的工作内容是android开发,用的是java语言,后来感觉还行,用的时间长了就发现他没有我当初想象的那么恶心。

下班或者周末的时候我有时候会逛逛coursera,业余时间完成了Andrew Ng的机器学习课程,前两天又完成了一门android课程。年初的时候,我又迷上了codeschool,上面的课程质量非常不错,看了很多javascript的课程(尤其讲解jQuery的course),一下子让我对前端开发又有了兴趣,大二时候搞这些时候真是头疼死了。最近又看了ruby on rails的视频,大概清楚了rails开发到底是什么样子的,跃跃欲试想搞点东西出来。无聊之中在kindle下了objective-c的书,看完发现iOS开发也挺有意思的。哎,,不知道我下一个喜欢的是什么东西。

到这里肯定有人要说,搞东西要专一,学这么多东西肯定都是附在表面的。我也知道,不过工作的内容真的是让我整天提不起兴趣,每天回去之后要敲一两个小时非工作代码心情才能舒缓过来。加之互联网的世界这么精彩,只蜷缩于一个小的舒适区里真的不方便拓宽眼界。

其实我设想我将来一定会成为一个独立开发者,这样必定需要很强的全栈技能,现在多学一点万一以后用上呢。目前我的困惑是,如何用我所学的技能做出一个产品出来,脑子里现在有些小点子,不过需要很长的时间来实现。

如果按照现在这样一直996的节奏,我会被云OS操得不轻的,好累。