新更新:在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