Android桌面小部件AppWidget(2)

简介: Android桌面小部件AppWidget(2)在附录文章1的基础上,我再写一篇关于Android AppWidget的文章,本篇文章实现一个简单功能,此功能亦是对附录文章1所实现功能的增强和改进,本文的代码实现的功能:假设桌面小部件只包含一个Button和一个TextView,当点击Button后,后台启动一个服务(IntentService实现),该服务每个一秒发送一个简单的字符串消息数据data,然后将此消息数据更新到桌面小部件的TextView里面实时显示。


Android桌面小部件AppWidget(2)

在附录文章1的基础上,我再写一篇关于Android AppWidget的文章,本篇文章实现一个简单功能,此功能亦是对附录文章1所实现功能的增强和改进,本文的代码实现的功能:假设桌面小部件只包含一个Button和一个TextView,当点击Button后,后台启动一个服务(IntentService实现),该服务每个一秒发送一个简单的字符串消息数据data,然后将此消息数据更新到桌面小部件的TextView里面实时显示。
这次,在Androidmanifest.xml有关receiver的定义中,与附录文章1相比,将增加一个action:action_update。本例中,Button的按击事件将触发后台启动服务,后台服务Service每隔一秒制造一个简单字符串数据,然后将此数据实时的以广播形式发给AppWidge,AppWidge收到后,就更新到桌面小部件的TextView里面。

(1)定义AppWidget。

先在Androidmanifest.xml里面定义APP widget的,以Android广播形式:

 <receiver android:name="zhangphil.widget.AppWidget" >
           
            <intent-filter>
                <action android:name="action_button" />
            </intent-filter>
            
            <intent-filter>
                <action android:name="action_update" />
            </intent-filter>
            
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            </intent-filter>

            <meta-data
                android:name="android.appwidget.provider"
                android:resource="@xml/appwidget" />
            
        </receiver>

两个用于广播接收的action:action_button和action_update,其中action_button用于在桌面小部件接收用户的点击事件,此action_button将随即启动后台服务,而后台启动的服务将发送广播数据,数据中的广播过滤器即是:action_update。

涉及到的res/xml目录下的appwidget.xml代码文件:

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:initialLayout="@layout/appwidget_layout"
    android:minHeight="20dip"
    android:minWidth="300dip"
    android:previewImage="@drawable/ic_launcher"
    android:resizeMode="horizontal|vertical"
    android:updatePeriodMillis="0"
    android:widgetCategory="home_screen" >

</appwidget-provider>


(2)上次Java代码实现窗口小部件。

核心的AppWidget.java代码:

package zhangphil.widget;

import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.RemoteViews;

public class AppWidget extends AppWidgetProvider {

	@Override
	public void onReceive(Context context, Intent intent) {
		super.onReceive(context, intent);
		Log.d(this.getClass().getName(), "onReceive");

		if (intent == null)
			return;

		String action = intent.getAction();

		if (action.equals(Constants.ACTION_UPDATE)) {
			String data = intent.getStringExtra(Constants.KEY_DATA);
			Log.d(Constants.KEY_DATA, data);

			RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.appwidget_layout);
			remoteViews.setTextViewText(R.id.text, data);

			AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
			ComponentName componentName = new ComponentName(context, AppWidget.class);
			appWidgetManager.updateAppWidget(componentName, remoteViews);
		}

		// 点击了按钮,开始启动一个后台服务
		if (action.equals(Constants.ACTION_BUTTON)) {
			Intent serviceIntent = new Intent(context, MyService.class);
			context.startService(serviceIntent);
		}
	}

	@Override
	public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
		Log.d(this.getClass().getName(), "onUpdate");

		Intent intent = new Intent(Constants.ACTION_BUTTON);
		PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);

		// 小部件在Launcher桌面的布局
		RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.appwidget_layout);

		// 事件
		remoteViews.setOnClickPendingIntent(R.id.btn, pendingIntent);

		// 更新AppWidget
		appWidgetManager.updateAppWidget(appWidgetIds, remoteViews);
	}

	/**
	 * 删除AppWidget
	 */
	@Override
	public void onDeleted(Context context, int[] appWidgetIds) {
		super.onDeleted(context, appWidgetIds);
		Log.d(this.getClass().getName(), "onDeleted");
	}

	@Override
	public void onDisabled(Context context) {
		super.onDisabled(context);
		Log.d(this.getClass().getName(), "onDisabled");
	}

	/**
	 * AppWidget首次创建调用
	 */
	@Override
	public void onEnabled(Context context) {
		super.onEnabled(context);
		Log.d(this.getClass().getName(), "onEnabled");
	}
}

RemoteViews用到的appwidget_layout.xml,appwidget_layout.xml即是桌面小部件的布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:background="#33000000" >

    <Button
        android:id="@+id/btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="启动后台服务" >
    </Button>
   
    <TextView
        android:id="@+id/text"
        android:text="text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

(3)后台服务Service。

MyService.java代码文件,此service是一个Android IntentService,具体实现也可以是Service。此service功能简单,是有桌面小部件的button按钮触发,然后在后台启动,启动后在一个for循环里面循环产生一个简单的字符串数据通过广播形式广播出去,注意打进去的广播过滤器是:action_update。

package zhangphil.widget;

import android.app.IntentService;
import android.content.Intent;

public class MyService extends IntentService {

	private static int ID = 0;

	public MyService() {
		super("ZhangPhilService");
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		return super.onStartCommand(intent, flags, startId);
	}

	@Override
	protected void onHandleIntent(Intent intent) {
		myLongTimeTask(ID++);
	}

	private void myLongTimeTask(int id) {
		for (int i = 0; i < 5; i++) {

			Intent intent = new Intent(Constants.ACTION_UPDATE);
			intent.putExtra(Constants.KEY_DATA, "Zhang Phil @ CSDN " + id + ":" + i);
			sendBroadcast(intent);

			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

记得要将此service注册到Androidmanifest.xml里面:

<service android:name="zhangphil.widget.MyService" >
        </service>

(4)公共变量的定义(次要)。

因为涉及到众多公共变量的写入和读出,所以定义了一个单独的Constants.java代码类,专门定义公共的变量定义:

package zhangphil.widget;

public class Constants {
	public static final String ACTION_BUTTON = "action_button";
	public static final String ACTION_UPDATE = "action_update";
	public static final String KEY_DATA = "data";
}

(5)完整的代码结构。

如图所示:



最终,代码运行结果如图所示:





附录文章:
1,《Android桌面小部件AppWidget(1)》链接地址:http://blog.csdn.net/zhangphil/article/details/50457355

相关文章
|
6月前
|
XML Java Android开发
Android Studio App开发之捕获屏幕的变更事件实战(包括竖屏与横屏切换,回到桌面与切换到任务列表)
Android Studio App开发之捕获屏幕的变更事件实战(包括竖屏与横屏切换,回到桌面与切换到任务列表)
196 0
|
6月前
|
XML 搜索推荐 Java
Android App开发之自定义图形中位图与图形互转、剪裁图形内部区域、给图形添加部件的讲解及实战(附源码 简单易懂)
Android App开发之自定义图形中位图与图形互转、剪裁图形内部区域、给图形添加部件的讲解及实战(附源码 简单易懂)
67 0
|
6月前
|
Java Android开发
Android桌面快捷方式图标生成与删除 使用Intent与launcher交互
Android桌面快捷方式图标生成与删除 使用Intent与launcher交互
110 1
|
6月前
|
Java Android开发
Android 长按桌面显示菜单的代码
Android 长按桌面显示菜单的代码
45 0
|
XML 测试技术 API
【Android开发日常】一文弄懂桌面图标快捷菜单 & 桌面小组件
开发可以定义快捷方式,以便在应用中执行特定操作。 这些快捷方式可在受支持的启动器或助理(如 Google 助理)中显示,方便用户快速启动应用中的常见任务或推荐任务。 通过本文你还将了解一些可提升快捷方式效果的最佳做法。
1018 1
|
双11 Android开发
Android动态来改变App桌面图标
其实对于这样的一个桌面图标更换,Android中为我们提供了AndroidManifest.xml里的<activity-alias>标签实现方式。
330 0
|
XML 缓存 数据库
Android桌面小部件开发,及注意事项
Android桌面小部件开发,及注意事项
471 0
|
XML 定位技术 Android开发
Android 12 小部件详解
Android 12 小部件详解
885 0
Android 12 小部件详解
|
Web App开发 监控 安全
开发者曝 Android 13 “彩蛋”功能!虚拟化支持运行 Windows 11 和桌面版 Linux
开发者曝 Android 13 “彩蛋”功能!虚拟化支持运行 Windows 11 和桌面版 Linux
562 0
开发者曝 Android 13 “彩蛋”功能!虚拟化支持运行 Windows 11 和桌面版 Linux
|
XML Android开发 数据格式
Android之在launcher里面动态加载桌面图标
Android之在launcher里面动态加载桌面图标
222 0