专栏名称: 鸿洋
你好,欢迎关注鸿洋的公众号,每天为您推送高质量文章,让你每天都能涨知识。点击历史消息,查看所有已推送的文章,喜欢可以置顶本公众号。此外,本公众号支持投稿,如果你有原创的文章,希望通过本公众号发布,欢迎投稿。
目录
相关文章推荐
51好读  ›  专栏  ›  鸿洋

还记得如何将你的程序放到桌面吗?

鸿洋  · 公众号  · android  · 2017-10-19 07:30

正文

请到「今天看啥」查看全文


每日推荐


PopsTabView是个filter容器,他可以快速,构建不同筛选样式,自由组合PopWindow成一组tab.


https://github.com/ccj659/PopsTabView


本文作者


作者: Wing_Li

链接: http://www.jianshu.com/p/1eec51bf74be

本文由作者投稿推送。


1
概述


Android 桌面小部件是我们经常看到的,比如时钟、天气、音乐播放器等等。
它可以让 App 的某些功能直接展示在桌面上,极大的增加了用户的关注度。


首先纠正一个误区:


当 App 的小部件被放到了桌面之后,并不代表你的 App 就可以一直在手机后台运行了。该被杀,它还是会被杀掉的。


所以如果你做小部件的目的是为了让程序常驻后台,那么你可以死心了。


但是!!!

虽然它还是能被杀掉,但是用户能看的见它了啊,用户可以点击就打开我们的 APP,所以

还是很不错的。


Android 桌面小部件可以做什么?


小部件可以做什么呢?也就是我们需要实现什么功能。

  1. 展示。每隔 N 秒/分钟,刷新一次数据;

  2. 交互。点击操作 App 的数据;

  3. 打开App。打开主页或指定页面。


这三个功能,大概就能满足我们绝大部分需求了吧。


实现桌面小部件需要什么?


如果你从来没有做过桌面部件,那肯定总是感觉有点慌,无从下手,毫无逻辑。
所以,实现它到底需要什么呢?


  1. 先声明 Widget 的一些属性。在 res 新建 xml 文件夹,创建 appwidget-provider 标签的 xml 文件。

  2. 创建桌面要显示的布局。 在 layout 创建 app_widget.xml。

  3. 然后来管理 Widget 状态。实现一个继承 AppWidgetProvider 的类。

  4. 最后在 AndroidManifest.xml 里,将 AppWidgetProvider类 和 xml属性 注册到一块。

  5. 通常我们会加一个 Service 来控制 Widget 的更新时间,后面再讲为什么。


做完这些,如果不出错,就完成了桌面部件。

其实挺简单的,下面就让我们来看看具体的实现吧。


2
实现一个桌面计数器


先上效果图:



1. 声明 Widget 的属性


在 res 新建 xml 文件夹,创建一个 app_widget.xml 的文件。
如果 res 下没有 xml 文件,则先创建。


app_widget.xml 内容如下:



属性的注释在上面写的很清楚了,这里需要说两点。


1.关于宽度和高度的数值定义是很有讲究的,在桌面其实是按照“格子”排列的。
看 Google 给的图。上面我们代码定义 110dp 也就是说,它占了2*2的空间。



2.第二点很重要。有个 updatePeriodMillis 属性,更新widget的时间间隔(ms)。
官方给提供了小部件的自动更新时间,但是却给了限制,你更新的时间必须大于30分钟,如果小于30分钟,那默认就是30分钟。


可以我们就是要5分钟更新啊,怎么办呢?

所以就不能使用这个默认更新,我们要自己来通过发送广播控制更新时间,也就是一开始总步骤里面第4步,加一个 Service 来控制 Widget 的更新时间,这个在最后一步添加。


2.创建布局文件


在 layout 创建 app_widget.xml 文件。



这里要注意的就是 桌面部件并不支持 Android 所有的控件。

支持的控件如下:


App Widget支持的布局:
         FrameLayout
         LinearLayout
         RelativeLayout
         GridLayout
App Widget支持的控件:
         AnalogClock
         Button
         Chronometer
         ImageButton
         ImageView
         ProgressBar
         TextView
         ViewFlipper
         ListView
         GridView
         StackView
         AdapterViewFlipper


3. 管理 Widget 状态


这里代码看起来可能有点多,先听我讲几个逻辑,再来看代码。


1.Android 的各种东西都有自己的生命周期,Widget 也不例外,它有几个方法来管理自己的生命周期。

2. 同一个小部件是可以添加多次的,所以更新控件的时候,要把所有的都更新。

3. onReceive() 用来接收广播,它并不在生命周期里。但是,其实 onReceive() 是掌控生命周期的。


如下是 onReceive() 父类的源码,右边是每个广播对应的方法。


上面我画的生命周期的图,也比较清楚。



然后我们再来看代码。
新建一个 WidgetProvider 类,继承 AppWidgetProvider。
主要逻辑在 onReceive() 里,其他的都是生命周期切换时,所处理的事情。
我们在下面分析 onReceive()。



onReceive(Context context, Intent intent)

它传了两个值回来,Context 是跳转、发广播用的。
我们用来判断的是 Intent ,这里用到了 Intent 的两种方式。


Intent 作为信息传递者。
它要把信息传给谁,可以有三个匹配依据:一个是action,一个是category,一个是data。


String ACTION_UPDATE_ALL = "com.lyl.widget.UPDATE_ALL";


这个最后会在 AndroidManifest.xml 里面注册时写进去。

当每隔 N 秒/分钟,就发送一次这个广播,更新所有UI。


intent.hasCategory(Intent.CATEGORY_ALTERNATIVE)


是广播事件里携带的 Intent 里设置的,用来匹配。
点击“恢复”按钮,计数器清零。


然后是 updateAllAppWidgets() 这个方法,更新 UI。
更新 UI 用到了一个新东西——RemoteViews。


怎么来理解 RemoteViews 呢?
因为,桌面部件并不像平常布局直接展示,它需要通过某种服务去更新UI。但是我们的App怎么能去控制桌面上的布局呢?
所以就需要有一个中间人,类似传递者。
我告诉传递者,你让他把我的 R.id.widget_txt ,更新成 “hello world”。
你让他把我的 R.id.widget_btn_open 按钮点击之后去响应 PendingIntent 这件事。
RemoteViews 就是承担着一个这样的角色。


然后再去理解代码,是不是稍微好一点了?


4. 最后就是 Service 控制 Widget 的更新时间


说好的 当每隔 N 秒/分钟,就发送一次这个广播。
那到底在哪发呢?也就是我们刚开始说的,用 Service 来控制时间。

新建一个 WidgetService 类,继承 Service。代码如下:




在 onCreate 开启一个计时线程,每1秒发送一个广播,广播就是我们自己定义的类型。


5. 在 AndroidManifest.xml 注册 桌面部件 和 服务


然后就只剩最后一步了,注册相关信息



相应的注释都在上面,如果我们的App进程被杀掉,服务也被关掉,那就没办法更新UI了。


也可以再创建一个 BroadcastReceiver 监听系统的各种动态,来唤醒我们的通知服务,这就属于进程保活了。


至此,以上代码写完,如果不出问题,运行之后直接去桌面看小工具,我们的App就在里面了,可以添加到桌面。


对于需要定时更新的桌面部件,保证自己的服务在后台运行也是一件比较重要的事情。
这个我们还是可以好好做一下,毕竟用户都已经愿意把我们的程序放到桌面上,所以只要友好的引导用户给你一定的权限,存活概率还是很大。


再不济,让用户主动点开App,也不失为一种办法。


好的创意才能造就好的App,代码只是实现。


最后放上项目地址:

https://github.com/Wing-Li/Widget


ZZS

优秀人才不缺工作机会,只缺适合自己的好机会。但是他们往往没有精力从海量机会中找到最适合的那个。

100offer 会对平台上的人才和企业进行严格筛选,让「最好的人才」和「最好的公司」相遇。


扫描下方二维码,注册 100offer ,谈谈你对下一份工作的期待。一周内,收到 5-10 个满足你要求的好机会!


如果你有 想学习的文章 直接留言,我会整理征稿。如果你有好的文章想和大家分享欢迎投稿,直接向我投递 文章链接 即可。







请到「今天看啥」查看全文