Android应用小部件点击无效。

7
哎呀,关于Android应用程序小部件的教程似乎有成千上万种,甚至在这里还有更多问题,但我就是无法弄清楚为什么我的小部件不起作用。叹气!反问:为什么代码不能和其他对象一样,使用setOnClickListener(new Button.OnClickListener() { // do stuff }... 就可以了呢?
总之,我的小部件出现在屏幕上,标签也正确,但当我点击小部件时,没有任何反应。我在所有认为会执行某些操作的地方设置了断点,但仍然没有执行任何操作。
问题1:小部件被点击后执行哪些代码?
我的小部件在被点击时实际上并不会更新,只会在我的程序的其他部分中执行一些代码。它只是执行一些网络HTTP和/或套接字服务器命令。此外,在将它放置在桌面之前,我的小部件被配置了一个活动。
以下是清单文件:
 <receiver android:name="PhcaAppWidgetProvider" >
     <intent-filter>
         <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
         <action android:name="com.skipmorrow.phca.PhcaAppWidgetProvider.WIDGET_CLICKED" />
     </intent-filter>
     <meta-data android:name="android.appwidget.provider"
                android:resource="@xml/phca_widget_info" />
 </receiver>

这里是小部件配置器活动。
    private Activity act;
    private static ListView listView;
    private static ArrayAdapter<String> adapter;
    private ArrayList<String> actionList;
    private final String widgetPageName = "_widget";
    int mAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
     private static final String PREFS_NAME = "PHCA";
     private static final String PREF_PREFIX_KEY = "prefix_";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setTitle("Choose an action for this widget");
        actionList = GetActionList();
        if (!actionList.isEmpty()) {
            listView = getListView();
            adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, android.R.id.text1, actionList);
            setListAdapter(adapter);
        }
        else {
            // no objects on the widget page
        }

        // 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 they gave us an intent without the widget id, just bail.
         if (mAppWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
             finish();
         }
    }

    private ArrayList<String> GetActionList() {
        ArrayList<String> l = new ArrayList<String>();
        Page p = CommonActivity.GetPageNamed(getApplicationContext(), widgetPageName);
        if (p!=null) {
            if (p.pageObjects.size()==0) DisplayEmptyPageHelpDialog();
            for (int i = 0; i < p.pageObjects.size(); i++) {
                l.add(p.pageObjects.get(i).GetParsedMajorLabel(getApplicationContext()).toString());
            }
        }
        else {
            CreateWidgetPage();
            DisplayEmptyPageHelpDialog();
        }
        return l;
    }

    private void CreateWidgetPage() {
        Page widgetPage = new Page(getApplicationContext());
        widgetPage.setPageName(widgetPageName);
        widgetPage.SetPageType("list");
        widgetPage.setNote("Widget Page");
        widgetPage.setPageTitle("Widget Page");
        widgetPage.setImageFilename("");
        widgetPage.setTransparentImageOverlayFilename("");
        widgetPage.InsertInstanceIntoDatabase(getApplicationContext());
    }

     private void DisplayEmptyPageHelpDialog() {
        Dialog helpDialog = new Dialog(this);
        helpDialog.setContentView(R.layout.phca_help_dialog);
        helpDialog.setTitle("PHCA Widget");
        TextView helpText = (TextView) helpDialog.findViewById(R.id.tvHelpText);
        helpText.setText("Your _widget page is empty. Please add an action to the _widget page so it can be used in a widget.");
        TextView subTitle = (TextView) helpDialog.findViewById(R.id.tvSubject);
        subTitle.setText("PHCA Widget configurator");
        helpDialog.show();
    }

    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        super.onListItemClick(l, v, position, id);
        SharedPreferences.Editor prefs = getSharedPreferences(PREFS_NAME, 0).edit();
         prefs.putInt(PREF_PREFIX_KEY + mAppWidgetId, position);
         prefs.commit();

         // Push widget update to surface with newly set prefix
         String majorLabel = CommonActivity.GetPageObjectAtIndex(getApplicationContext(), widgetPageName, position).GetParsedMajorLabel(getApplicationContext()).toString();
         String minorLabel = CommonActivity.GetPageObjectAtIndex(getApplicationContext(), widgetPageName, position).GetParsedMinorLabel(getApplicationContext()).toString();
         AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(getApplicationContext());
         PhcaAppWidgetProvider.updateAppWidget(getApplicationContext(), appWidgetManager,
                 mAppWidgetId, majorLabel, minorLabel);

         Intent resultValue = new Intent();
         resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
         setResult(RESULT_OK, resultValue);
         finish();
    }

这是我的小部件提供程序。
 public class PhcaAppWidgetProvider extends AppWidgetProvider {
    private static final String ACTION_CLICK = "WIDGET_CLICKED";
    private final String widgetPageName = "_widget";
     private static final String PREFS_NAME = "PHCA";
     private static final String PREF_PREFIX_KEY = "prefix_";

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager,
            int[] appWidgetIds) {

        // Get all ids
        ComponentName thisWidget = new ComponentName(context,
                PhcaAppWidgetProvider.class);
        //int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
        final int N = appWidgetIds.length;
         for (int i=0; i<N; i++) {
            int appWidgetId = appWidgetIds[i];

            SharedPreferences myPrefs = context.getSharedPreferences(PREFS_NAME, context.MODE_WORLD_WRITEABLE);
            Integer objNum = myPrefs.getInt(PREF_PREFIX_KEY + appWidgetId, -1);
            if (objNum > -1) {
                PageAction pa = (PageAction) CommonActivity.GetPageObjectAtIndex(context, widgetPageName, objNum);
                String majorLabel = pa.GetUnparsedMajorLabel(context).toString();
                String minorLabel = pa.GetUnparsedMinorLabel(context).toString();
                updateAppWidget(context, appWidgetManager, appWidgetId, majorLabel, minorLabel);
            }
        }
    }

    @Override
    public void onEnabled(Context context) {
        Log.d("Widget", "onEnabled");
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        String intentAction = intent.getAction();
        updateWidgetState(context, intentAction);
        if (intentAction.equals(ACTION_CLICK)) {
            Bundle extras = intent.getExtras();
            Integer appWidgetId = extras.getInt("appwidgetid");
            SharedPreferences myPrefs = context.getSharedPreferences(PREFS_NAME, context.MODE_WORLD_WRITEABLE);
            Integer objNum = myPrefs.getInt(PREF_PREFIX_KEY + appWidgetId, -1);
            if (objNum > -1) {
                PageAction pa = (PageAction) CommonActivity.GetPageObjectAtIndex(context, widgetPageName, objNum);
                pa.ExecuteActionFromWidgetClick(context);
            }
        } else {
            super.onReceive(context, intent);
        }
    }

    public static void updateWidgetState(Context paramContext, String paramString)
     {
        RemoteViews localRemoteViews = buildUpdate(paramContext, paramString);
        ComponentName localComponentName = new ComponentName(paramContext, PhcaAppWidgetProvider.class);
        AppWidgetManager.getInstance(paramContext).updateAppWidget(localComponentName, localRemoteViews);
     }

    private static RemoteViews buildUpdate(Context ctx, String paramString)
     {
        RemoteViews views = new RemoteViews(ctx.getPackageName(), R.layout.phca_appwidget);
        views.setTextViewText(R.id.majorlabel, "majorLabel");
        views.setTextViewText(R.id.minorlabel, "minorLabel");
        Intent intent = new Intent(ctx, PhcaAppWidgetProvider.class);
        intent.setAction(ACTION_CLICK);
        intent.putExtra("appwidgetid", 0);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(ctx, 0, intent , 0);
        views.setOnClickPendingIntent(R.layout.phca_appwidget, pendingIntent);
        if(paramString.equals(ACTION_CLICK))
        {
              Toast.makeText(ctx, "ACTION_CLICK", Toast.LENGTH_LONG).show();

        }            
        return views; 
     }
 }

当我添加并移除小部件时,不同的意图会传递到onReceive中,所以这是有效的,但是当点击事件发生时没有任何反应。
问题2:有人能否友好地指出我做错了什么?我基本上按照这里的教程进行操作:http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/appwidget/ExampleAppWidgetProvider.html 问题3:看起来我可以在小部件的布局xml中放置一个android:onclick="WidgetClicked",但我无法弄清楚在哪里放置WidgetClicked方法。 WidgetProvider似乎是合乎逻辑的,但对我也没有用。是否有一种方法在xml中实现这个功能?
免责声明:以上代码是经过一天半的疑难解答后的当前状态。这只是许多不同尝试的一个迭代。

仍然不起作用。我在onReceive中添加了一个toast行,当更新、添加和删除时,我仍然会得到toast,但是当我点击小部件时,我从未得到任何反应。这一定与我在创建小部件时注册单击侦听器的方式有关。感谢您今天给我的所有帮助,Imram! - MrGibbage
我有一个正在运行的小部件点击测试应用程序,如果您想要,我可以给您链接。 - ρяσѕρєя K
Imram,抱歉我跟不上你了。如果你能提供一些可行的代码,那当然可以!skip@pelorus.org - MrGibbage
在我的PhcaAppWidgetProvider中,我应该将ACTION_CLICK设置为"com.skipmorrow.phca.PhcaAppWidgetProvider.WIDGET_CLICKED"还是"WIDGET_CLICKED"。我的清单中有动作android:name="com.skipmorrow.phca.PhcaAppWidgetProvider.WIDGET_CLICKED"。 - MrGibbage
下一个问题:我需要在OnReceive方法中注册监听器吗?根据http://developer.android.com/guide/topics/appwidgets/index.html#AppWidgetProvider,它必须在该方法中注册。对我来说似乎很奇怪,因为每次更新后都会重新注册,而实际上它只需要注册一次。糟糕了。没关系,它确实是从onReceive方法调用的。 - MrGibbage
1个回答

3

您需要在清单文件中注册小部件点击的接收器:

  <receiver android:name="MyAppWidgetProvider" >
     <intent-filter>
         <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
         <action android:name="com.myname.myapp.MyAppWidgetProvider.ACTION_CLICK" />
     </intent-filter>
     <meta-data android:name="android.appwidget.provider"
     android:resource="@xml/my_widget_info" />
 </receiver>

AppWidgetProvider.java

public class MyAppWidgetProvider extends AppWidgetProvider {
    private static final String ACTION_CLICK = "ACTION_CLICK_WIDGET";
    private final String widgetPageName = "_widget";
    private static final String PREFS_NAME = "MYAPP";
    private static final String PREF_PREFIX_KEY = "prefix_";
    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager,
            int[] appWidgetIds) {

        ComponentName thisWidget = new ComponentName(context,
                MyAppWidgetProvider.class);
        final int N = appWidgetIds.length;
        for (int i=0; i<N; i++) {
            int appWidgetId = appWidgetIds[i];

            SharedPreferences myPrefs = 
                context.getSharedPreferences(PREFS_NAME, context.MODE_WORLD_WRITEABLE);
            Integer objNum = myPrefs.getInt(PREF_PREFIX_KEY + appWidgetId, -1);
            if (objNum > -1) {
                PageAction pa = (PageAction) CommonActivity
                    .GetPageObjectAtIndex(context, widgetPageName, objNum);
                String majorLabel = pa.GetUnparsedMajorLabel(context).toString();
                String minorLabel = pa.GetUnparsedMinorLabel(context).toString();
                updateAppWidget(context, appWidgetManager, 
                    appWidgetId, majorLabel, minorLabel);
            }
        }
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        String intentAction = intent.getAction();
        if (intentAction.equals(ACTION_CLICK)) {
        updateWidgetState(paramContext, str);
            Bundle extras = intent.getExtras();
            Integer appWidgetId = extras.getInt("appwidgetid");
            SharedPreferences myPrefs = 
            context.getSharedPreferences(PREFS_NAME, context.MODE_WORLD_WRITEABLE);
            Integer objNum = myPrefs.getInt(PREF_PREFIX_KEY + appWidgetId, -1);
            if (objNum > -1) {
                PageAction pa = (PageAction) CommonActivity
                .GetPageObjectAtIndex(context, widgetPageName, objNum);
                pa.ExecuteActionFromWidgetClick(context);
            }
        } else {
            super.onReceive(context, intent);
        }
    } 

public static void updateWidgetState(Context paramContext, String paramString)
          {
            RemoteViews localRemoteViews = buildUpdate(paramContext, paramString);
            ComponentName localComponentName = new ComponentName(paramContext, MyAppWidgetProvider.class);
            AppWidgetManager.getInstance(paramContext).updateAppWidget(localComponentName, localRemoteViews);
          }

    private static RemoteViews buildUpdate(Context ctx, String paramString)
          {
         RemoteViews views = 
         new RemoteViews(ctx.getPackageName(), R.layout.my_appwidget);
        views.setTextViewText(R.id.majorlabel, majorLabel);
        views.setTextViewText(R.id.minorlabel, minorLabel);
        Intent intent = new Intent(ctx, MyAppWidgetProvider.class);
        intent.setAction(ACTION_CLICK);
        intent.putExtra("appwidgetid", mAppWidgetId);
        PendingIntent configPendingIntentprev = PendingIntent.getBroadcast(ctx, 0, intent , 0);
        views.setOnClickPendingIntent(R.layout.my_appwidget, pendingIntent);
            if(parmString.equals(ACTION_CLICK))
            {
             //Toast.maketext("").show();
             //

            }            
             return rview; 
          }
 }

请查看帖子中我的答案,其中包含完整的示例。


如果问题没有解决,你可以在评论中提醒我,因为我有一个可行的例子。 - ρяσѕρєя K
“YOUR_APPWIDGETNAME” 是从哪里来的?我尝试了 com.myname.myapp.MyAppWidgetProvider,但它没有起作用。当我点击后会执行什么代码?我正在观察每个进入 onReceive 的 intent,例如 APPWIDGET_UPDATE 和其他一些,但是在单击后我没有看到任何内容进入。你的例子看起来应该进入 onReceive,但对我来说并没有发生。” - MrGibbage
你在另一篇帖子中看到了我的回答。 - ρяσѕρєя K
我已将其放置在oRecive中,如下所示:if (intentAction.equals(ACTION_CLICK)) {updateWidgetState(paramContext, str);} - ρяσѕρєя K
1
说实话,这个答案只是解决方案的一部分。你必须阅读 ρяσѕρєя K 的其他帖子才能解决这个问题。不过,它对我很有帮助,所以点了一个+1。 - shanabus
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接