Android开发Widget之提高篇
2016-04-19 22:01
639 查看
在上一篇博客Android开发Widget之入门篇我们已经介绍了创建一个widget的流程。但是像这样的widget没什么实际用途,widget主要是为了显示一些信息,这样很方便,不用我们专门去启动应用查看信息,那么现在教大家做一个显示时间的widget。
效果如下:
这个与之前的widget不同的就是,它是启动了一个后台服务,服务注册了广播监听时间变化,当发生变化时就接受到广播然后更新时间。像之前的流程一样还是分三步。
一.建一个widget的布局。
新建一个TimeApplication继承自Application,调用TimeUpdateService的onReceive方法,在widget一启动就接受时间更新时间,然后启动TimeUpdateService.
这样就完成了时间widget,很简单的。如果你要做一个界面很复杂的widget你就要注意了,widget只支持部分View,像Button,AnalogClock,TextView,ImageView等,那么那些复杂,酷炫的widget是怎么实现的呢,这就要在framework层下去修改了,位置在frameworks/base/core/java/android/widget里面,资源文件存放在frameworks/base/core/res/res
里,感兴趣的朋友可以自己研究下。
最后附上Demo地址:点击打开链接
效果如下:
这个与之前的widget不同的就是,它是启动了一个后台服务,服务注册了广播监听时间变化,当发生变化时就接受到广播然后更新时间。像之前的流程一样还是分三步。
一.建一个widget的布局。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingTop="@dimen/widget_marginTop" android:paddingBottom="@dimen/widget_marginBottom" > <TextView android:id="@+id/appwidget_time" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:gravity="center" android:contentDescription="@string/appwidget_text" android:textColor="@color/appwidget_view_time" android:textSize="@dimen/appwidget_view_time"/> </RelativeLayout>二.在xml目录下新建一个 widget的配置文件。
<?xml version="1.0" encoding="utf-8"?> <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:initialLayout="@layout/time_widget" android:minHeight="72dp" android:minWidth="142dp" android:previewImage="@drawable/example_appwidget_preview" android:resizeMode="horizontal" android:updatePeriodMillis="86400000" > </appwidget-provider>三.编写代码
新建一个TimeApplication继承自Application,调用TimeUpdateService的onReceive方法,在widget一启动就接受时间更新时间,然后启动TimeUpdateService.
public class TimeApplication extends Application { @Override public void onCreate() { TimeUpdateService.mTimeTickReceiver.onReceive(getApplicationContext(), null); getApplicationContext().startService( new Intent(getApplicationContext(), TimeUpdateService.class)); } }TimeUpdateService里注册广播,接受广播就更新时间.
public class TimeUpdateService extends Service { //获取Calendar对象 private static Calendar mCalendar = Calendar.getInstance(TimeZone.getDefault()); //时间广播接收者 public static BroadcastReceiver mTimeTickReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { //时区改变则重新获取Calendar if (intent != null) { if (intent.getAction().equals(Intent.ACTION_TIMEZONE_CHANGED)) { String tz = intent.getStringExtra("time-zone"); mCalendar = Calendar.getInstance(TimeZone.getTimeZone(tz)); } } //设置当前时间 mCalendar.setTimeInMillis(System.currentTimeMillis()); //设置时间格式 boolean is24 = DateFormat.is24HourFormat(context); SimpleDateFormat format = new SimpleDateFormat(is24 ? "H:mm" : "h:mm", Locale.getDefault()); String time = format.format(mCalendar.getTime()); //更新时间 TimeWidget.updateAppWidget(context, time); } }; @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { super.onCreate(); //注册这个广播,当系统时间改变时就会发送广播 IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_TIME_TICK); filter.addAction(Intent.ACTION_TIME_CHANGED); filter.addAction(Intent.ACTION_DATE_CHANGED); filter.addAction(Intent.ACTION_TIMEZONE_CHANGED); getApplicationContext().registerReceiver(mTimeTickReceiver, filter); } @Override public void onDestroy() { super.onDestroy(); //注销广播 if (null != mTimeTickReceiver) { getApplicationContext().unregisterReceiver(mTimeTickReceiver); } } }最后新建TimeWidget继承自AppWidgetProvider.
public class TimeWidget extends AppWidgetProvider { //时间 private static String mTime; @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { super.onUpdate(context, appWidgetManager, appWidgetIds); //如果时间不为空,那么更新时间 if (mTime!=null) { TimeWidget.updateAppWidget(context, mTime); } } @Override public void onEnabled(final Context context) { super.onEnabled(context); //启动后台服务检测时间变化 context.startService(new Intent(context, TimeUpdateService.class)); } @Override public void onDisabled(Context context) { //当最后一个widget被移除时停止服务 context.stopService(new Intent(context, TimeUpdateService.class)); } //更新widget static void updateAppWidget(Context context, String time) { //给mTime赋值 mTime = time; //如果time不为null则更新 if (null != time) { //widget管理者 AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); //远程view视图 RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.time_widget); //设置视图中的显示 views.setTextViewText(R.id.appwidget_time, time); //指定要启动的组件 ComponentName mComponentName = new ComponentName(context, TimeWidget.class); //更新 appWidgetManager.updateAppWidget(mComponentName, views); } } }
这样就完成了时间widget,很简单的。如果你要做一个界面很复杂的widget你就要注意了,widget只支持部分View,像Button,AnalogClock,TextView,ImageView等,那么那些复杂,酷炫的widget是怎么实现的呢,这就要在framework层下去修改了,位置在frameworks/base/core/java/android/widget里面,资源文件存放在frameworks/base/core/res/res
里,感兴趣的朋友可以自己研究下。
最后附上Demo地址:点击打开链接
相关文章推荐
- [android] fragment的生命周期和通讯
- Android 动效系列之一 - AndroidSwipeLayout
- 30 条 Android 开发建议 2016.3.16
- VectorDrawable 怎么玩(Android)
- Android自定义控件之onLayout
- Android studio 2.1 集成第三方短信验证类库
- Android 状态栏工具类(实现沉浸式状态栏 / 变色状态栏)
- 高效Android开发者必须知道的4个工具
- Android 服务两种启动方式的区别
- Android 自定义 View 之高仿 QQ 健康
- Android 5.0以后版本打开“有权查看使用情况的应用”
- Android Service使用拾遗[阿里工程师分享]
- android将对象写入文件和从文件中读取对象数据
- Android源码国内源
- ListView属性及方法android
- 14条Android Studio常用的的配置
- Android Studio 快捷键大全及使用技巧
- [译] 适配 Android N 多窗口特性的 5 个要诀
- Android:ViewGroup事件分发机制详解
- android下的一些调试方法