AppWidget实例

1.概念:

桌面工具(Widget)是Android系统的一大特色,通过桌面工具可以快速得到所需的信息,不必打开程序即可了解最新的内容,就好像是一个应用程序的快捷方式。Android系统自带了一些常用的桌面工具,其他一些经过定制的系统也带有具有特色的桌面工具,同时,有很多第三方程序也支持桌面工具。例如新浪微博提供的AppWidget

 AppWidget实例_第1张图片


在了解完AppWidget的概念后,我们就要开发一个类似的应用。首先来看个制作的效果:

AppWidget实例_第2张图片     AppWidget实例_第3张图片    AppWidget实例_第4张图片

2.代码部分:

新建个程序,并添加以下代码:

MainActivity.java

<span style="font-size:18px;">package com.example.lxxcaroline.myappwidget;
import android.app.Activity;
import android.os.Bundle;
/**
 * 主程序入口类
 * @author Linxuanxuan
 */
public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}</span>


 MyAppWidget.java

<span style="font-size:18px;">package com.example.lxxcaroline.myappwidget;

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.widget.RemoteViews;

/**
 * Created by LxxCaroline on 2015/5/2.
 */
public class MyAppWidget extends AppWidgetProvider {

    /**
     * 接收到每个广播时都会被调用,而且在上面的回调函数之前。
     * 你通常不需要实现这个方法,因为缺省的AppWidgetProvider实现过滤所有App Widget广播并恰当的调用上述方法。
     * 注意: 在Android 1.5中,有一个已知问题,onDeleted()方法在调用时不被调用。
     * 为了规避这个问题,你可以像Group post中描述的那样实现onReceive()来接收这个onDeleted()回调。
     */
    @Override
    public void onReceive(Context context, Intent intent) {
        System.out.println("onReceive");
        super.onReceive(context, intent);
    }

    /**
     * 用来间隔的更新App Widget,间隔时间用AppWidgetProviderInfo里的updatePeriodMillis属性定义(单位为毫秒)。
     * 注意:SDK1.5之后此android:updatePeriodMillis就失效了,要自己创建service更新。
     * 这个方法也会在用户添加App Widget时被调用,因此它应该执行基础的设置,比如为视图定义事件处理器并启动一个临时的服务Service,如果需要的话。
     * 但是,如果你已经声明了一个配置活动,这个方法在用户添加App Widget时将不会被调用,
     * 而只在后续更新时被调用。配置活动应该在配置完成时负责执行第一次更新。
     * 到达指定的更新时间或者当用户向桌面添加AppWidget时被调用.
     */
    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        System.out.println("onUpdate");
        /**
         * RemoteViews类描述了一个View对象能够显示在其他进程中,可以融合layout资源文件实现布局。
         *虽然该类在android.widget.RemoteViews而不是appWidget下面,但在Android Widgets开发中会经常用到它,
         *主要是可以跨进程调用(appWidget由一个服务宿主来统一运行的)。
         */
        RemoteViews myRemoteViews = new RemoteViews(context.getPackageName(), R.layout.my_appwidget_layout);
        //为RemoteView上的按钮设置点击事件,点击桌面组件时进入主程序入口
        Intent intent = new Intent(context, MainActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
        myRemoteViews.setOnClickPendingIntent(R.id.contentBtn, pendingIntent);
        //ComponentName和Intent很相似。
        ComponentName myComponentName = new ComponentName(context,MyAppWidget.class);
        //负责管理AppWidget,向AppwidgetProvider发送通知。提供了更新AppWidget状态,获取已经安装的Appwidget提供信息和其他的相关状态
        AppWidgetManager myAppWidgetManager = AppWidgetManager.getInstance(context);
        myAppWidgetManager.updateAppWidget(myComponentName, myRemoteViews);
        super.onUpdate(context, appWidgetManager, appWidgetIds);
    }

    /**
     * 当App Widget从宿主中删除时被调用。 删除一个AppWidget时调用
     */
    @Override
    public void onDeleted(Context context, int[] appWidgetIds) {
        System.out.println("onDeleted");
        super.onDeleted(context, appWidgetIds);
    }

    /**
     * 当一个App Widget实例第一次创建时被调用。
     * 比如,如果用户添加两个App Widget实例,只在第一次被调用。
     * 如果你需要打开一个新的数据库或者执行其他对于所有的App Widget实例只需要发生一次的设置,那么这里是完成这个工作的好地方。
     */
    @Override
    public void onEnabled(Context context) {
        System.out.println("onEnabled");
        super.onEnabled(context);
    }

    @Override
    public void onDisabled(Context context) {
        System.out.println("onDisabled");
        super.onDisabled(context);
    }
}
</span>

res/layout/activity_main.xml:

<span style="font-size:18px;"><?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="程序入口" />
</LinearLayout></span>

res/layout/my_appwidget_layout.xml:

这里需要注意的是,appwidget的布局文件并不是支持所有的控件,在上述代码中已经看到使用的是RemoteViews,它并不支持所有控件。RemoteViews还用在notification中。

<span style="font-size:18px;"><?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="match_parent"
    android:orientation="vertical"
    android:background="@drawable/background">

    <Button
        android:id="@+id/contentBtn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="点击进入主程序" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="控件其余内容"
        android:textSize="20sp"
        android:layout_gravity="center"
        android:textColor="#000000"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="控件其余内容"
        android:textSize="20sp"
        android:layout_gravity="center"
        android:textColor="#000000"/>
</LinearLayout>
</span>

res/xml/my_appwidget.xml:

<span style="font-size:18px;"><?xml version="1.0" encoding="utf-8"?>
<!-- 
AppWidgetProvderInfo: 描述AppWidget的大小、更新频率和初始界面等信息,以XML文件形式存在于应用的res/xml/目录下。
注意:SDK1.5之后此android:updatePeriodMillis就失效了,要自己创建service更新
 -->
<appwidget-provider
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:minWidth="150dip"
    android:minHeight="150dip"
    android:updatePeriodMillis="1000"
    android:layout_height="wrap_content"
    android:layout_width="wrap_content"
    android:initialLayout="@layout/my_appwidget_layout"/></span>

AndroidManifest.xml:

<span style="font-size:18px;"><?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.lxxcaroline.myappwidget"
    android:versionCode="1"
    android:versionName="1.0">

    <application
        android:icon="@drawable/icon"
        android:label="@string/app_name">
        <activity
            android:name="com.example.lxxcaroline.myappwidget.MainActivity"
            android:label="主程序">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <!-- MyAppWidget类为一个广播接收器,因为MyAppWidget继承自AppWidgetProvider -->
        <receiver
            android:name="com.example.lxxcaroline.myappwidget.MyAppWidget"
            android:label="添加桌面控件">
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            </intent-filter>
            <meta-data
                android:name="android.appwidget.provider"
                android:resource="@xml/my_appwidget" />
        </receiver>
    </application>
    <uses-sdk android:minSdkVersion="7" />
</manifest>
</span>

项目中用到的图片资源不再说明,读者可以随便贴几张png的图片放在drawable下面。

3.代码说明:

程序正常入口是进入到MainActivity里面去,显示的是activity_main.xml的页面内容。

当点击应用程序图标进入时,MyAppWidget中的代码并不会执行。

接下来为该应用程序创建应用桌面图标,即AppWidgetAppWidget的图样显示是由my_appwidget_layout.xml文件决定。而my_appwidget.xml文件只是说明了该AppWidget应该长什么样,指定AppWidget的布局文件等。

当然最重要的是MyAppWidget里面的代码,他继承自AppWidgetProvider。这个父类中有几个函数,分别是onUpdate()onDeleted()onEnabled()onDisabled()onReceive()。接下来分别解释这几个函数会在什么时候被执行到。

具体可以看一下两个博客:

http://www.cnblogs.com/qianlifeng/archive/2011/03/26/1996407.html

http://blog.csdn.net/thl789/article/details/7887968

你可能感兴趣的:(android,appwidget)