带有AlarmManager的Android主屏幕小部件

在本教程中,我们将学习使用AlarmManager创建更新间隔少于30分钟的窗口小部件。

新更新:在Android 4.1中,为Homescreen小部件引入了一项新功能,该功能使小部件在调整大小时可以重新组织其视图。 为了支持此功能,AppWidgetProvider类中引入了新方法onAppWidgetOptionsChanged() 。 当此窗口小部件以新尺寸进行布局时,将调用此方法以响应ACTION_APPWIDGET_OPTIONS_CHANGED广播。

项目信息:有关该项目的元信息。

平台版本: Android API级别16。
IDE: Eclipse Helios服务版本2
模拟器: Android 4.1

先决条件:具备Android应用程序框架,Intent Broadcast接收器和AlarmManager的基本知识。

固定更新间隔少于30分钟的示例。

在本教程中,我们将创建显示当前时间的时间小部件。 这个小部件将每秒更新一次,我们将使用AlarmManager。 在此,重复警报设置为一秒间隔。 但是在现实世界中,不建议使用一秒钟的重复警报,因为它会很快耗尽电池电量。 您必须按照上一小部件教程中提到的类似步骤来编写小部件布局文件。 但是这次我们在布局中引入了一个TextView字段,它将显示时间。 下面给出“ time_widget_layout.xml”的内容。

<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/widget_background" >

     <TextView
         android:id="@+id/tvTime"
         style="@android:style/TextAppearance.Medium"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:layout_gravity="center"
         android:layout_margin="4dip"
         android:gravity="center_horizontal|center_vertical"
         android:textColor="#000000" />

</LinearLayout>

遵循相同的过程来创建AppWidgetProvider元数据文件。 元数据文件“ widget_metadata.xml”的内容如下。

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:initialLayout="@layout/time_widget_layout"
    android:minHeight="40dp"
    android:minWidth="130dp"
    android:updatePeriodMillis="1800000" >
</appwidget-provider>

在本教程中,已经定义了onEnabled(),onDsiabled(),onUpdate()和onAppWidgetOptionsChanged(),而之前的窗口小部件教程仅定义了onUpdate()。

  • onEnabled():在此处创建AlarmManager的实例,以启动重复计时器并向AlarmManager注册意图。 由于此方法是在窗口小部件安装的第一个实例中被调用的,因此它仅有助于将重复警报设置一次。
  • onDisabled():在此方法中,警报被取消,因为一旦删除/卸载了窗口小部件的最后一个实例,就会立即调用此方法,即使在不使用它时,我们也不想保留已注册的警报。
  • onUpdate():此方法更新远程TextView上的时间。
  • onAppWidgetOptionsChanged():调整窗口小部件大小时将调用此方法。
package com.rakesh.widgetalarmmanagerexample;

import android.app.AlarmManager;
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.os.Bundle;
import android.widget.RemoteViews;
import android.widget.Toast;

public class TimeWidgetProvider extends AppWidgetProvider {

 @Override
 public void onDeleted(Context context, int[] appWidgetIds) {
  Toast.makeText(context, "TimeWidgetRemoved id(s):"+appWidgetIds, Toast.LENGTH_SHORT).show();
  super.onDeleted(context, appWidgetIds);
 }

 @Override
 public void onDisabled(Context context) {
  Toast.makeText(context, "onDisabled():last widget instance removed", Toast.LENGTH_SHORT).show();
  Intent intent = new Intent(context, AlarmManagerBroadcastReceiver.class);
  PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, 0);
  AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
  alarmManager.cancel(sender);
  super.onDisabled(context);
 }

 @Override
 public void onEnabled(Context context) {
  super.onEnabled(context);
  AlarmManager am=(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
  Intent intent = new Intent(context, AlarmManagerBroadcastReceiver.class);
  PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, 0);
  //After after 3 seconds
  am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+ 100 * 3, 1000 , pi);
 }

 @Override
 public void onUpdate(Context context, AppWidgetManager appWidgetManager,
   int[] appWidgetIds) {
  ComponentName thisWidget = new ComponentName(context,
    TimeWidgetProvider.class);

  for (int widgetId : appWidgetManager.getAppWidgetIds(thisWidget)) {

   //Get the remote views
   RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
     R.layout.time_widget_layout);
   // Set the text with the current time.
   remoteViews.setTextViewText(R.id.tvTime, Utility.getCurrentTime("hh:mm:ss a"));
   appWidgetManager.updateAppWidget(widgetId, remoteViews);
  }
 }

 @Override
 public void onAppWidgetOptionsChanged(Context context,
   AppWidgetManager appWidgetManager, int appWidgetId,
   Bundle newOptions) {
  //Do some operation here, once you see that the widget has change its size or position.
  Toast.makeText(context, "onAppWidgetOptionsChanged() called", Toast.LENGTH_SHORT).show();
 }
}

广播接收器被定义为处理向警报注册的意图。 因为已在AppWidgetProvider类中将重复警报设置为1秒,所以此广播接收器每秒被调用一次。 在这里,已经定义了onReceive()方法,该方法使用当前时间更新窗口小部件,并且使用getCurrentTime()获取当前时间。

package com.rakesh.widgetalarmmanagerexample;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.PowerManager;
import android.widget.RemoteViews;
import android.widget.Toast;

public class AlarmManagerBroadcastReceiver extends BroadcastReceiver {

 @Override
 public void onReceive(Context context, Intent intent) {
  PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
  PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "YOUR TAG");
  //Acquire the lock
  wl.acquire();

  //You can do the processing here update the widget/remote views.
  RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
    R.layout.time_widget_layout);
  remoteViews.setTextViewText(R.id.tvTime, Utility.getCurrentTime("hh:mm:ss a"));
  ComponentName thiswidget = new ComponentName(context, TimeWidgetProvider.class);
  AppWidgetManager manager = AppWidgetManager.getInstance(context);
  manager.updateAppWidget(thiswidget, remoteViews);
  //Release the lock
  wl.release();
 }
}

将实用程序方法保留在可以从其他程序包访问的某些实用程序类中始终是一个好主意。 getCurrentTime()已在Uitility类中定义。 在AppWidgetProvider和BroadcastReciever类中使用此方法。

package com.rakesh.widgetalarmmanagerexample;

import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Utility {
  public static String getCurrentTime(String timeformat){
      Format formatter = new SimpleDateFormat(timeformat);
         return formatter.format(new Date());
     }
}

在Android清单文件中,我们需要包含WAKE_LOCK权限,因为广播接收器中使用了唤醒锁。 AlarmManagerBroadcastReceiver已注册为广播接收器。 其余部分很容易理解。

<manifest android:versioncode="1" android:versionname="1.0"
      package="com.rakesh.widgetalarmmanagerexample"
      xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-sdk android:minsdkversion="16" android:targetsdkversion="16"/>

<uses-permission android:name="android.permission.WAKE_LOCK"/>
    <application android:icon="@drawable/ic_launcher"
          android:label="@string/app_name">
        <activity android:label="@string/title_activity_widget_alarm_manager"
                android:name=".WidgetAlarmManagerActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <receiver android:icon="@drawable/ic_launcher"
             android:label="@string/app_name"
             android:name=".TimeWidgetProvider">
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
            </intent-filter>
            <meta-data android:name="android.appwidget.provider"
                android:resource="@xml/widget_metadata"/>
        </receiver>
        <receiver android:name=".AlarmManagerBroadcastReceiver"/>
    </application>
</manifest>

一旦执行了代码,该小部件就被注册。 在主屏幕上安装小部件时,它如下所示。

您可以从此处下载源代码。

参考: 带有AlarmManager的Android主屏幕小部件上的教程。 从我们的JCG合作伙伴 Rakesh Cusat在Code4Reference博客上获得。


翻译自: https://www.javacodegeeks.com/2012/09/android-homescreen-widget-with.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值