我为它创建了简单的示例窗口小部件和简单的配置活动。我需要在用户单击widets后为每个窗口小部件实例调用配置活动。每个实例都应该有单独的设置,单击后,配置活动应该填充从用于调用配置对话框的特定实例获取的设置,允许仅更改此特定实例的设置(其他现有的实例化实例应保持不变)。
所以,我的小部件代码:
package com.example.michal.widgettest2;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.content.Intent;
import android.widget.RemoteViews;
/**
* Implementation of App Widget functionality.
* App Widget Configuration implemented in {@link MyWidgetConfigureActivity MyWidgetConfigureActivity}
*/
public class MyWidget extends AppWidgetProvider
{
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
{
// There may be multiple widgets active, so update all of them
final int N = appWidgetIds.length;
for (int i = 0; i < N; i++)
{
int appWidgetId = appWidgetIds[i];
Intent intent = new Intent(context, MyWidgetConfigureActivity.class);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,appWidgetId);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
RemoteViews views = new RemoteViews(context.getPackageName(),R.layout.my_widget);
views.setOnClickPendingIntent(R.id.widget_container, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
}
@Override
public void onDeleted(Context context, int[] appWidgetIds)
{
// When the user deletes the widget, delete the preference associated with it.
final int N = appWidgetIds.length;
for (int i = 0; i < N; i++)
{
MyWidgetConfigureActivity.deleteTitlePref(context, appWidgetIds[i]);
}
}
@Override
public void onEnabled(Context context)
{
// Enter relevant functionality for when the first widget is created
}
@Override
public void onDisabled(Context context)
{
// Enter relevant functionality for when the last widget is disabled
}
static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
int appWidgetId)
{
CharSequence widgetText = MyWidgetConfigureActivity.loadTitlePref(context, appWidgetId);
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.my_widget);
views.setTextViewText(R.id.appwidget_text, widgetText);
Intent intent = new Intent(context, MyWidgetConfigureActivity.class);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,appWidgetId);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
views.setOnClickPendingIntent(R.id.widget_container, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
}
我的配置活动代码:
package com.example.michal.widgettest2;
import android.app.Activity;
import android.appwidget.AppWidgetManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
/**
* The configuration screen for the {@link MyWidget MyWidget} AppWidget.
*/
public class MyWidgetConfigureActivity extends Activity
{
int mAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
EditText mAppWidgetText;
private static final String PREFS_NAME = "com.example.michal.widgettest2.MyWidget";
private static final String PREF_PREFIX_KEY = "appwidget_";
public MyWidgetConfigureActivity()
{
super();
}
@Override
public void onCreate(Bundle icicle)
{
super.onCreate(icicle);
// Set the result to CANCELED. This will cause the widget host to cancel
// out of the widget placement if the user presses the back button.
setResult(RESULT_CANCELED);
setContentView(R.layout.my_widget_configure);
mAppWidgetText = (EditText) findViewById(R.id.appwidget_text);
findViewById(R.id.add_button).setOnClickListener(mOnClickListener);
// Find the widget id from the intent.
Intent intent = getIntent();
Bundle extras = intent.getExtras();
if (extras != null)
{
mAppWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
}
// If this activity was started with an intent without an app widget ID, finish with an error.
if (mAppWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID)
{
finish();
return;
}
mAppWidgetText.setText(loadTitlePref(MyWidgetConfigureActivity.this, mAppWidgetId));
}
View.OnClickListener mOnClickListener = new View.OnClickListener()
{
public void onClick(View v)
{
final Context context = MyWidgetConfigureActivity.this;
// When the button is clicked, store the string locally
String widgetText = mAppWidgetText.getText().toString();
saveTitlePref(context, mAppWidgetId, widgetText);
// It is the responsibility of the configuration activity to update the app widget
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
MyWidget.updateAppWidget(context, appWidgetManager, mAppWidgetId);
// Make sure we pass back the original appWidgetId
Intent resultValue = new Intent();
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
setResult(RESULT_OK, resultValue);
finish();
}
};
// Write the prefix to the SharedPreferences object for this widget
static void saveTitlePref(Context context, int appWidgetId, String text)
{
SharedPreferences.Editor prefs = context.getSharedPreferences(PREFS_NAME, 0).edit();
prefs.putString(PREF_PREFIX_KEY + appWidgetId, text);
prefs.commit();
}
// Read the prefix from the SharedPreferences object for this widget.
// If there is no preference saved, get the default from a resource
static String loadTitlePref(Context context, int appWidgetId)
{
SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, 0);
String titleValue = prefs.getString(PREF_PREFIX_KEY + appWidgetId, null);
if (titleValue != null)
{
return titleValue;
} else
{
return context.getString(R.string.appwidget_text);
}
}
static void deleteTitlePref(Context context, int appWidgetId)
{
SharedPreferences.Editor prefs = context.getSharedPreferences(PREFS_NAME, 0).edit();
prefs.remove(PREF_PREFIX_KEY + appWidgetId);
prefs.commit();
}
}
不幸的是,它不能正常工作。配置活动中显示的设置不是来自用于调用配置活动的小部件,而是更新转到不正确的小部件实例。
可能我已经提出了一些问题,你能提供一些错误的提示吗?
[编辑] 更新的代码:
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
{
// There may be multiple widgets active, so update all of them
final int N = appWidgetIds.length;
for (int i = 0; i < N; i++)
{
int appWidgetId = appWidgetIds[i];
//Intent intent = new Intent(context, MyWidgetConfigureActivity.class);
//intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,appWidgetId);
//PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntent pendingIntent = getUniquePI(context,null,appWidgetId);
RemoteViews views = new RemoteViews(context.getPackageName(),R.layout.my_widget);
views.setOnClickPendingIntent(R.id.widget_container, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
}
static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
int appWidgetId)
{
CharSequence widgetText = MyWidgetConfigureActivity.loadTitlePref(context, appWidgetId);
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.my_widget);
views.setTextViewText(R.id.appwidget_text, widgetText);
//Intent intent = new Intent(context, MyWidgetConfigureActivity.class);
//intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,appWidgetId);
//PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
PendingIntent pendingIntent = getUniquePI(context,null,appWidgetId);
views.setOnClickPendingIntent(R.id.widget_container, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
现在我的窗口小部件不响应点击事件(配置活动未显示)。怎么了?
答案 0 :(得分:1)
逐步使用以下示例。
第1步
创建服务UpdateWidgetService.java
public class UpdateWidgetService extends Service {
public UpdateWidgetService() {
}
public static final String SKIP = "skip";
public static final String OPENAPP = "openapp";
@Override
public int onStartCommand(Intent pIntent, int flags, int startId) {
String command = pIntent.getAction();
int appWidgetId = pIntent.getExtras().getInt(AppWidgetManager.EXTRA_APPWIDGET_ID);
RemoteViews remoteView = new RemoteViews(getApplicationContext().getPackageName(), R.layout.widget);
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(getApplicationContext());
if(command.equals(SKIP)){
/**Do the SKIP click work here*/
return START_NOT_STICKY;
}else if(command.equals(OPENAPP)){
/**Do the OPENAPP click work here*/
Intent mAct=new Intent(this, OPENAPP.class);
mAct.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(mAct);
return START_NOT_STICKY;
}
remoteView.setTextViewText(R.id.widet_ibtn_skip, "MyTextHere");
remoteView.setTextViewText(R.id.widget_tv_title, "Title");
remoteView.setOnClickPendingIntent(R.id.widet_ibtn_skip,WallWidgetProvider.makeControlPendingIntent(getApplicationContext(),SKIP,appWidgetId));
remoteView.setOnClickPendingIntent(R.id.widget_tv_title,WallWidgetProvider.makeControlPendingIntent(getApplicationContext(),OPENAPP,appWidgetId));
appWidgetManager.updateAppWidget(appWidgetId, remoteView);
return super.onStartCommand(pIntent, flags, startId);
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
}
第2步 将WidgetProvider创建为WallWidgetProvider.java
public class WallWidgetProvider extends AppWidgetProvider{
public static final int UPDATE_RATE = 1000;
@Override
public void onDeleted(Context context, int[] appWidgetIds) {
for (int appWidgetId : appWidgetIds) {
setCounterAlarm(context, appWidgetId, -1);
}
super.onDeleted(context, appWidgetIds);
}
@Override
public void onDisabled(Context context) {
context.stopService(new Intent(context,UpdateWidgetService.class));
super.onDisabled(context);
}
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
PrefrenceSettings ps=new PrefrenceSettings(context);
for (int appWidgetId : appWidgetIds) {
setCounterAlarm(context, appWidgetId, UPDATE_RATE);
}
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
public static void setCounterAlarm(Context context, int appWidgetId, int updateRate) {
PendingIntent newPending = makeControlPendingIntent(context,UpdateWidgetService.UPDATE,appWidgetId);
AlarmManager alarms = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
if (updateRate >= 0) {
alarms.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime(), updateRate, newPending);
} else {
// on a negative updateRate stop the refreshing
alarms.cancel(newPending);
}
}
public static PendingIntent makeControlPendingIntent(Context context, String command, int appWidgetId) {
Intent active = new Intent(context,UpdateWidgetService.class);
active.setAction(command);
active.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
//this Uri data is to make the PendingIntent unique, so it wont be updated by FLAG_UPDATE_CURRENT
//so if there are multiple widget instances they wont override each other
Uri data = Uri.withAppendedPath(Uri.parse("widget://widget/id/#"+command+appWidgetId), String.valueOf(appWidgetId));
active.setData(data);
return(PendingIntent.getService(context, 0, active, PendingIntent.FLAG_UPDATE_CURRENT));
}
}
希望你应该知道如何在你的项目中使用这两个类,这些类生成每个Widget的唯一标识。