(4.0.24.1)Android之桌面组件App Widget案例

本文详细介绍了一个桌面小控件的开发过程,包括XML布局设计、AndroidManifest.xml配置、AppWidgetProvider使用及Service后台更新机制。通过具体代码实现,展示了如何实时更新时间与天气信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


下载地址:http://pan.baidu.com/s/1hqpjrpi

res/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="300dp"
    android:updatePeriodMillis="0" >

</appwidget-provider>

res/layout

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    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" >

    <LinearLayout
        android:id="@+id/time"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:orientation="horizontal" >

        <LinearLayout
            android:id="@+id/linearLayout1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/wd_bg"
            android:orientation="horizontal" >

            <ImageView
                android:id="@+id/h1"
                android:layout_width="wrap_content"
                android:layout_height="fill_parent"
                android:paddingLeft="10dip"
                android:src="@drawable/n0" />

            <ImageView
                android:id="@+id/h2"
                android:layout_width="wrap_content"
                android:layout_height="fill_parent"
                android:src="@drawable/n0" />
        </LinearLayout>

        <TextView
            android:layout_width="30dip"
            android:layout_height="wrap_content" />

        <LinearLayout
            android:id="@+id/linearLayout2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/wd_bg"
            android:orientation="horizontal" >

            <ImageView
                android:id="@+id/m1"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:paddingLeft="10dip"
                android:src="@drawable/n0" />

            <ImageView
                android:id="@+id/m2"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:src="@drawable/n0" />
        </LinearLayout>
    </LinearLayout>

    <LinearLayout
        android:id="@+id/linearLayout3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:gravity="center"
        android:orientation="horizontal" >

        <LinearLayout
            android:layout_width="100dip"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:paddingLeft="10dip" >

            <TextView
                android:id="@+id/city"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textColor="#000000"
                android:textSize="20sp" />

            <TextView
                android:id="@+id/condition"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/neterror"
                android:textColor="#000000"
                android:textSize="18sp" />
        </LinearLayout>

        <ImageView
            android:id="@+id/weather"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal|top"
            android:src="@drawable/sunny" />

        <LinearLayout
            android:layout_width="100dip"
            android:layout_height="wrap_content"
            android:gravity="right"
            android:orientation="vertical"
            android:paddingRight="10dip" >

            <TextView
                android:id="@+id/date"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textColor="#000000"
                android:textSize="18sp" />

            <TextView
                android: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>

AndroidManifest.xml

        <receiver android:name="com.way.apptest.App" >

            <!-- 指定桌面小控件的meta-data -->
            <meta-data
                android: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>

AppWidgetProvider

public class App extends AppWidgetProvider {
	private Intent intent;

	@Override
	public void onUpdate(Context context, AppWidgetManager appWidgetManager,
			int[] appWidgetIds) {
		intent = new Intent(context, UpdateService.class);
		context.startService(intent);
		super.onUpdate(context, appWidgetManager, appWidgetIds);
	}

	@Override
	public void onDeleted(Context context, int[] appWidgetIds) {
		intent = new Intent(context, UpdateService.class);
		context.stopService(intent);
		super.onDeleted(context, appWidgetIds);
	}
}

Service

/**
 * @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() {

		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case UPDATE:
				// 更新天气
				updateTime();
				updateWeather();
				break;
			}
		}
	};
	// 广播接收者去接收系统每分钟的提示广播,来更新时间
	private BroadcastReceiver mTimePickerBroadcast = new BroadcastReceiver() {

		@Override
		public 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);
	}

	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}

	@Override
	public void onCreate() {
		super.onCreate();
		remoteViews = new RemoteViews(getApplication().getPackageName(),
				R.layout.main);// 实例化RemoteViews
		if (isNetworkAvailable()) {
			MyWeather.getWeather();// json解析中国天气网天气
		} else {
			toast();
		}
		updateTime();// 第一次运行时先更新一下时间和天气
		updateWeather();
		// 点击天气图片,进入MainActivity
		Intent 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() {
			@Override
			public 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);
	}

	@Override
	public void onStart(Intent intent, int startId) {
		// 注册系统每分钟提醒广播(注意:这个广播只能在代码中注册)
		IntentFilter updateIntent = new IntentFilter();
		updateIntent.addAction("android.intent.action.TIME_TICK");
		registerReceiver(mTimePickerBroadcast, updateIntent);
		super.onStart(intent, startId);
	}

	@Override
	public 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;
	}

	private void toast() {
		new AlertDialog.Builder(getApplicationContext())
				.setTitle("提示")
				.setMessage("网络连接未打开")
				.setPositiveButton("前往打开",
						new DialogInterface.OnClickListener() {

							public void onClick(DialogInterface dialog,
									int which) {
								Intent intent = new Intent(
										android.provider.Settings.ACTION_WIRELESS_SETTINGS);
								startActivity(intent);
							}
						}).setNegativeButton("取消", null).create().show();
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值