相信墨迹天气,大家都见过,他在时间显示和天气界面上,很吸引人,今天我就来模仿一下墨迹天气的桌面组件,但是由于谷歌在天朝频频被墙的缘故,所以我在今天测试的时候,解析xml文件的网页打不开,所以天气显示出了点问题,希望大家能理解,谢谢。(今天9月24日修改为解析中国天气网获取天气了,而且修改组件在桌面居中显示)。

老规矩,先分享源代码:Weather.zip(2.38 MB, 下载次数: 229)

好了,废话不多说,先上效果图:

再来看一下整个小项目的主体结构:

首先先声明一个桌面布局的xml文件,即app.xml:

    <?xml version="1.0" encoding="utf-8"?><!--指定该桌面组件的基本配置信息:initialLayout:初始时显示的布局minWidth:桌面小控件的最小高度。minWidth:桌面小控件的最小宽度。updatePeriodMillis:更新频率--><appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"android:initialLayout="@layout/main"android:minHeight="150dp"android:minWidth="200dp"android:updatePeriodMillis="0" ></appwidget-provider>

复制代码

然后要在manifest文件中声明:

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.way.apptest"android:versionCode="1"android:versionName="1.0" ><uses-sdkandroid:minSdkVersion="8"android:targetSdkVersion="15" /><uses-permission android:name="android.permission.INTERNET" /><applicationandroid:icon="@drawable/ic_launcher"android:label="@string/app_name"android:theme="@style/AppTheme" ><activity android:name="com.way.apptest.MainActivity" ></activity><receiver android:name="com.way.apptest.App" ><!-- 指定桌面小控件的meta-data --><meta-dataandroid:name="android.appwidget.provider"android:resource="@xml/app" /><!-- 将该BroadcastReceiver当成桌面小控件 --><intent-filter><action android:name="android.appwidget.action.APPWIDGET_UPDATE" /></intent-filter></receiver><service android:name=".UpdateService" ></service></application></manifest>

复制代码

主要代码:一:定义一个App类继承AppWidgetProvider,然后再onUpdate方法中启动一个服务去更新时间和天气。

    /*** @author way*/public class App extends AppWidgetProvider {private Intent intent;@Overridepublic void onUpdate(Context context, AppWidgetManager appWidgetManager,int[] appWidgetIds) {intent = new Intent(context, UpdateService.class);context.startService(intent);super.onUpdate(context, appWidgetManager, appWidgetIds);}@Overridepublic void onDeleted(Context context, int[] appWidgetIds) {context.stopService(intent);super.onDeleted(context, appWidgetIds);}}

二:本项目中最重要的部分,在这个服务中,我们注册一个广播接收者去接受系统每分钟时间时间变化的广播,从而来更新桌面时间,这样更省电哦,需要注意的是:这个广播接收者必须在代码中注册,在Manifest文件中注册是没有效果的。更新天气,我是通过定义一个定时器,由用户设置时间间隔来更新天气信息。

    package com.way.apptest;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Timer;import java.util.TimerTask;import android.app.AlertDialog;import android.app.PendingIntent;import android.app.Service;import android.appwidget.AppWidgetManager;import android.content.BroadcastReceiver;import android.content.ComponentName;import android.content.Context;import android.content.DialogInterface;import android.content.Intent;import android.content.IntentFilter;import android.net.ConnectivityManager;import android.net.NetworkInfo;import android.os.Handler;import android.os.IBinder;import android.os.Message;import android.widget.RemoteViews;import com.way.getWeather.MyWeather;/*** @author way*/public class UpdateService extends Service {private static final int UPDATE = 0x123;private RemoteViews remoteViews;// 数字时间图片资源数组private int[] imgs = { R.drawable.n0, R.drawable.n1, R.drawable.n2,R.drawable.n3, R.drawable.n4, R.drawable.n5, R.drawable.n6,R.drawable.n7, R.drawable.n8, R.drawable.n9, };// 将显示小时、分钟的ImageView定义成数组private int[] dateViews = { R.id.h1, R.id.h2, R.id.m1, R.id.m2 };// 按照中国天气网的天气图片顺序排列好本地资源图片,我这里是随意的~嘿嘿private int[] weatherImg = { R.drawable.sunny, R.drawable.cloudy,R.drawable.chance_of_rain, R.drawable.chance_of_sleet,R.drawable.chance_of_snow, R.drawable.chance_of_storm,R.drawable.clock1, R.drawable.fog, R.drawable.haze,R.drawable.mist, R.drawable.mostly_sunny, R.drawable.mostly_cloudy,R.drawable.lower, R.drawable.middle };private Handler handler = new Handler() {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case UPDATE:// 更新天气updateTime();updateWeather();break;}}};// 广播接收者去接收系统每分钟的提示广播,来更新时间private BroadcastReceiver mTimePickerBroadcast = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {updateTime();}};private void updateWeather() {// Weather w = new GetWeather().googleWeather();// if (w != null) {// System.out.println("当前天气:" + w.getWeather() + ":" + w.getTemp_c()// + ":" + w.getIcon());remoteViews.setTextViewText(R.id.condition, MyWeather.weather1);remoteViews.setTextViewText(R.id.tem, (MyWeather.temp1));// 根据图片名,获取天气图片资源// remoteViews.setImageViewResource(// R.id.weather,// getApplicationContext().getResources().getIdentifier(// w.getIcon(), "drawable", "com.way.apptest"));if (MyWeather.img1 != null || !"".equals(MyWeather.img1))remoteViews.setImageViewResource(R.id.weather,weatherImg[Integer.parseInt(MyWeather.img1)]);// 执行更新ComponentName componentName = new ComponentName(getApplicationContext(), App.class);AppWidgetManager.getInstance(getApplicationContext()).updateAppWidget(componentName, remoteViews);}@Overridepublic IBinder onBind(Intent intent) {return null;}@Overridepublic void onCreate() {super.onCreate();remoteViews = new RemoteViews(getApplication().getPackageName(),R.layout.main);// 实例化RemoteViewsif (isNetworkAvailable()) {MyWeather.getWeather();// json解析中国天气网天气} else {toast();}updateTime();// 第一次运行时先更新一下时间和天气updateWeather();// 点击天气图片,进入MainActivityIntent intent = new Intent(getApplicationContext(), MainActivity.class);PendingIntent pi = PendingIntent.getActivity(getApplicationContext(),0, intent, 0);remoteViews.setOnClickPendingIntent(R.id.weather, pi);// 定义一个定时器去更新天气。实际开发中更新时间间隔可以由用户设置,new Timer().scheduleAtFixedRate(new TimerTask() {@Overridepublic void run() {Message msg = handler.obtainMessage();msg.what = UPDATE;handler.sendMessage(msg);}}, 1, 3600 * 1000);// 每小时更新一次天气}private void updateTime() {Date date = new Date();// 定义SimpleDateFormat对象SimpleDateFormat df = new SimpleDateFormat("HHmm");// 将当前时间格式化成HHmm的形式String timeStr = df.format(date);for (int i = 0; i < timeStr.length(); i++) {// 将第i个数字字符转换为对应的数字int num2 = Integer.parseInt(timeStr.substring(i, i + 1));// 将第i个图片的设为对应的数字图片remoteViews.setImageViewResource(dateViews[i], imgs[num2]);}remoteViews.setTextViewText(R.id.city, MyWeather.city);remoteViews.setTextViewText(R.id.date, "0" + (date.getMonth() + 1)+ "-" + date.getDate() + " 周" + date.getDay());ComponentName componentName = new ComponentName(getApplication(),App.class);AppWidgetManager.getInstance(getApplication()).updateAppWidget(componentName, remoteViews);}@Overridepublic void onStart(Intent intent, int startId) {// 注册系统每分钟提醒广播(注意:这个广播只能在代码中注册)IntentFilter updateIntent = new IntentFilter();updateIntent.addAction("android.intent.action.TIME_TICK");registerReceiver(mTimePickerBroadcast, updateIntent);super.onStart(intent, startId);}@Overridepublic void onDestroy() {// 注销系统的这个广播unregisterReceiver(mTimePickerBroadcast);//被系统干掉后,服务重启,做一次流氓软件,哈哈Intent intent = new Intent(getApplicationContext(), UpdateService.class);getApplication().startService(intent);super.onDestroy();}/*** 判断手机网络是否可用** @param context* @return*/private boolean isNetworkAvailable() {ConnectivityManager mgr = (ConnectivityManager) getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);NetworkInfo[] info = mgr.getAllNetworkInfo();if (info != null) {for (int i = 0; i < info.length; i++) {if (info[i].getState() == NetworkInfo.State.CONNECTED) {return true;}}}return false;}<p>/*** 在非Activity中弹出对话框** @param context*/private void showDialog(final Context context) {// TODO Auto-generated method stub/* create ui */final AlertDialog dialog;AlertDialog.Builder builder = new AlertDialog.Builder(context);builder.setTitle("提示").setMessage("WiFi连接不可用");builder.setPositiveButton("前往打开", new OnClickListener() {</p><p>   public void onClick(DialogInterface dialog, int which) {Intent go2wifi = new Intent(android.provider.Settings.ACTION_WIRELESS_SETTINGS);go2wifi.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);context.startActivity(go2wifi);</p><p>   }}).setNegativeButton("下次再说", null);dialog = builder.create();dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);// d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY);dialog.show();</p><p>  /* set size & pos */WindowManager.LayoutParams lp = dialog.getWindow().getAttributes();WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);Display display = wm.getDefaultDisplay();if (display.getHeight() > display.getWidth()) {// lp.height = (int) (display.getHeight() * 0.5);lp.width = (int) (display.getWidth() * 1.0);} else {// lp.height = (int) (display.getHeight() * 0.75);lp.width = (int) (display.getWidth() * 0.5);}dialog.getWindow().setAttributes(lp);}</p>//记得加上权限         <!-- 系统对话框权限 -->//   <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>}

三:这是桌面组件主要布局文件,如果大家有什么好的建议,欢迎提,本人对布局不是特别擅长。

    <?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/bg"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:background="@drawable/ww_bg"android:orientation="vertical" ><LinearLayoutandroid:id="@+id/time"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:orientation="horizontal" ><LinearLayoutandroid:id="@+id/linearLayout1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/wd_bg"android:orientation="horizontal" ><ImageViewandroid:id="@+id/h1"android:layout_width="wrap_content"android:layout_height="fill_parent"android:paddingLeft="10dip"android:src="@drawable/n0" /><ImageViewandroid:id="@+id/h2"android:layout_width="wrap_content"android:layout_height="fill_parent"android:src="@drawable/n0" /></LinearLayout><TextViewandroid:layout_width="30dip"android:layout_height="wrap_content" /><LinearLayoutandroid:id="@+id/linearLayout2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/wd_bg"android:orientation="horizontal" ><ImageViewandroid:id="@+id/m1"android:layout_width="wrap_content"android:layout_height="match_parent"android:paddingLeft="10dip"android:src="@drawable/n0" /><ImageViewandroid:id="@+id/m2"android:layout_width="wrap_content"android:layout_height="match_parent"android:src="@drawable/n0" /></LinearLayout></LinearLayout><LinearLayoutandroid:id="@+id/linearLayout3"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_horizontal"android:gravity="center"android:orientation="horizontal" ><LinearLayoutandroid:layout_width="100dip"android:layout_height="wrap_content"android:orientation="vertical"android:paddingLeft="10dip" ><TextViewandroid:id="@+id/city"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textColor="#000000"android:textSize="20sp" /><TextViewandroid:id="@+id/condition"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/neterror"android:textColor="#000000"android:textSize="18sp" /></LinearLayout><ImageViewandroid:id="@+id/weather"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_horizontal|top"android:src="@drawable/sunny" /><LinearLayoutandroid:layout_width="100dip"android:layout_height="wrap_content"android:gravity="right"android:orientation="vertical"android:paddingRight="10dip" ><TextViewandroid:id="@+id/date"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textColor="#000000"android:textSize="18sp" /><TextViewandroid:id="@+id/tem"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/neterror"android:textColor="#000000"android:textSize="18sp" /></LinearLayout></LinearLayout></LinearLayout>

四:谷歌天气不给力,所以我就简单的给出获取天气的核心代码。这里简单的做了一下乱码处理。

     * @author way**/public class GetWeather {/**** @return 天气对象*/public Weather googleWeather() {String str = "http://www.google.com/ig/api?hl=zh_cn&weather=shenzhen";try {URL url = new URL(str);InputStream in = url.openStream();ByteArrayOutputStream bos = new ByteArrayOutputStream();int len = -1;while ((len = in.read()) != -1) {bos.write(len);}InputStream is = new ByteArrayInputStream(bos.toString("GBK").getBytes("utf-8"));// 从流中获取文档到本地内存Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(is);// 从文档中得到名字为current_conditions的第一个节点下的所有子节点(一个集合)NodeList nodeList = doc.getElementsByTagName("current_conditions").item(0).getChildNodes();// 得到nodeList下第一个节点的第一个元素内容(即当前天气)String condition = nodeList.item(0).getAttributes().item(0).getNodeValue();// 当前温度String temp_c = nodeList.item(2).getAttributes().item(0).getNodeValue();// 当前湿度//                        String humidity = nodeList.item(3).getAttributes().item(0)//                                        .getNodeValue();// 当前图片路径String iconPath = nodeList.item(4).getAttributes().item(0).getNodeValue();// 当前风向//                        String wind_condition = nodeList.item(5).getAttributes().item(0)//                                        .getNodeValue();Weather w = new Weather();w.setWeather(condition);w.setTemp_c(temp_c);// 从图片路径中获取图片的名字String icon = iconPath.substring(iconPath.lastIndexOf("/") + 1,iconPath.indexOf("."));w.setIcon(icon);return w;} catch (MalformedURLException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} catch (SAXException e) {e.printStackTrace();} catch (ParserConfigurationException e) {e.printStackTrace();}return null;}}

今天再修改解析中国天气网的json代码:

    public class MyWeather {public static String city;public static String temp1;public static String weather1;public static String img1;public static void getWeather() {try {URL url = new URL("http://m.weather.com.cn/data/101250101.html");InputStream is = url.openStream();ByteArrayOutputStream bos = new ByteArrayOutputStream();int len = -1;byte[] buffer = new byte[1024];while ((len = is.read(buffer)) != -1) {bos.write(buffer, 0, len);}String info = bos.toString("utf-8");JSONObject dataJson = new JSONObject(info);JSONObject json = dataJson.getJSONObject("weatherinfo");city = json.getString("city");temp1 = json.getString("temp1");weather1 = json.getString("weather1");img1 = json.getString("img1");System.out.println(city);is.close();bos.close();} catch (MalformedURLException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} catch (JSONException e) {e.printStackTrace();}}}

转载: http://www.apkbus.com/android-130431-1-1.html

Android之高仿墨迹天气桌面组件(AppWidgetProvider)相关推荐

  1. Android之高仿墨迹天气桌面组件(AppWidgetProvider) .

    Android之高仿墨迹天气桌面组件(AppWidgetProvider) . 点击:382 发布时间:2012-10-03 更多0 相信墨迹天气,大家都见过,他在时间显示和天气界面上,很吸引人,今天 ...

  2. (4.0.24.2)Android之桌面组件App Widget案例之高仿墨迹天气桌面组件

    相信墨迹天气,大家都见过,他在时间显示和天气界面上,很吸引人,今天我就来模仿一下墨迹天气的桌面组件,但是由于谷歌在天朝频频被墙的缘故,所以我在今天测试的时候,解析xml文件的网页打不开,所以天气显示出 ...

  3. 高仿墨迹天气 白天晴天

    简介 一直对墨迹天气的绚丽的场景蛮感兴趣的,趁有时间,自己就高仿了其中的一个场景,其他场景呢,也是类似的,主要是写对象的AI也就是逻辑了. 先看看效果吧,动态效果比较坑,太模糊 高清图 代码分析 来看 ...

  4. android 自定义皮肤,仿墨迹天气在Android App中实现自定义zip皮肤更换

    在这里谈一下墨迹天气的换肤实现方式,不过首先声明我只是通过反编译以及参考了一些网上其他资料的方式推测出的换肤原理, 在这里只供参考. 若大家有更好的方式, 欢迎交流. 墨迹天气下载的皮肤就是一个zip ...

  5. 高仿墨迹天气“我”页面

    看到墨迹天气的"我"页面比较炫酷,处于好奇,就写了一个demo模仿一下. 1,实现效果 实现的效果分三个部分来说明,首先是下拉到最大高度,个人信息界面会产生一个回弹的效果,然后是滚 ...

  6. Android 高仿墨迹天气“我”页面

    1,实现效果  转自:http://blog.csdn.net/huweigoodboy/article/details/47301197 实现的效果分三个部分来说明,首先是下拉到最大高度,个人信息界 ...

  7. 高仿墨迹天气-天鹰气象

            本项目主要设计了一个Android天气气象软件,从网络上获取相关天气信息后展示给用户,主要进行解析json.界面设计.动画优化等工作.所开发软件能够达到如下预期效果: (1)能够根据用 ...

  8. Android之高仿雅虎天气(一)

    引言: 记得去年下半年有上传一份代码(超逼真仿雅虎天气界面):http://download.csdn.net/detail/weidi1989/6312271 但那仅仅只是一个界面,而且还有一些比较 ...

  9. Android之高仿雅虎天气

    首先感谢作者:weidi1989 的无私分享 转来自:http://blog.csdn.net/way_ping_li/article/details/38963807点击打开链接 引言: 记得去年下 ...

  10. Android之高仿雅虎天气(二)---代码结构解析

    版本已升级至1.0.1 源码地址: GitHub:https://github.com/way1989/WayHoo OsChina:http://git.oschina.net/way/WayHoo ...

最新文章

  1. 智能手机相机测试中的功能测试和性能测试
  2. #查找文件中是否有eee如果没有在最后加入
  3. php 中set是什么_php中set
  4. 在Nutz中如何配置多个数据库源,并且带事务控制
  5. 【JavaScript 笔记 】— 基础语法(数据类型、字符串、数组、对象、Map、Set、iterable、函数基础)
  6. Archlinux 简明安装指南
  7. 在Ruby中,如何跳过.each循环中的循环,类似于‘continue‘[duplicate]
  8. 社交礼仪与口才艺术 艾跃进
  9. HDU-2819-Swap [二分匹配][输出路径]
  10. Vivado IP核fifo使用指南
  11. 你要的技术干货我都总结好了
  12. Apache日志分割及分析
  13. 服务器防火墙关闭开机自启解决方案
  14. 如何快速删除CSV、Excel、Markdown表格的重复行?
  15. android高德轨迹纠偏,轨迹纠偏-服务-教程-地图 JS API | 高德地图API
  16. Arcgis js api 点聚合
  17. xcode 工程常见问题
  18. 2021年安全员-C证(江西省)考试报名及安全员-C证(江西省)证考试
  19. 基于博弈思想的攻击图漏洞修复策略
  20. 【实战篇】执行计划3种看法,2种操作,4个误区

热门文章

  1. 机器学习实战(第1章)
  2. c语言给字母加密,C语言文字简单加密程序的实现
  3. 企业服务的定义、分类与特点
  4. 基于CNN-LSTM的手写数字识别与应用实现(附tensorflow代码讲解)
  5. 商务统计_3 概率论基础 2
  6. 查看电脑ip地址的命令Linux,怎么用ipconfig命令查看自己电脑的IP地址
  7. 基层干部计算机培训方案,基层管理干部培训方案
  8. 【学习笔记】《网络安全态势感知》第三章:网络安全数据采集与融合
  9. 【图像分割】最大类间方差法(otsu)图像分割
  10. C#调用PB生成dll详解