38

我正在尝试做一些应该很容易的事情,但这让我发疯。我正在尝试在按下主屏幕小部件时启动活动,例如小部件的配置活动。我想我已经逐字阅读了 Android 开发者网站上的教程,甚至还有一些非官方的教程,但我一定错过了一些重要的东西,因为它不起作用。

这是代码:

public class VolumeChangerWidget extends AppWidgetProvider {

public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds){
    final int N = appWidgetIds.length;

    for (int i=0; i < N; i++) {
        int appWidgetId = appWidgetIds[i];

        Log.d("Steve", "Running for appWidgetId " + appWidgetId);
        Toast.makeText(context, "Hello from onUpdate", Toast.LENGTH_SHORT);
        Log.d("Steve", "After the toast line");

        Intent intent = new Intent(context, WidgetTest.class);

        PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);

        RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget);
        views.setOnClickPendingIntent(R.id.button, pendingIntent);

        appWidgetManager.updateAppWidget(appWidgetId, views);
    }
}

}

将小部件添加到主屏幕时,Logcat 显示两条调试行,但不显示 Toast。(有什么想法为什么不呢?)然而,更令人烦恼的是,当我点击带有 PendingIntent 关联的按钮时,什么也没有发生。我知道“WidgetTest”活动可以运行,因为如果我从主活动中设置一个 Intent,它可以正常启动。

万一这很重要,这里是 Android Manifest 文件:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.steve"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
    <activity android:name=".Volume_Change_Program"
              android:label="@string/app_name">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    <activity android:name=".WidgetTest"
              android:label="@string/hello">
        <intent_filter>
            <action android:name="android.intent.action.MAIN"/>
            <category android:name="android.intent.category.LAUNCHER"/>
        </intent_filter>
    </activity>

    <receiver android:name=".VolumeChangerWidget" >
        <intent-filter>
            <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
        </intent-filter>
        <meta-data  android:name="android.appwidget.provider"
                    android:resource="@xml/volume_changer_info" />
    </receiver>

</application>
<uses-sdk android:minSdkVersion="3" />

有没有办法测试故障在哪里?即按钮没有正确链接到PendingIntent,或者PendingIntent 或Intent 没有找到WidgetTest.class 等故障?

非常感谢您的帮助!

史蒂夫

4

9 回答 9

22

以这种方式起死回生,但我遇到了类似的问题,我想我终于解决了它......像你一样,我有一个附加到 RemoteView 的 PendingIntent。有时它会起作用,有时它会失败。这让我快疯了。

我从 PendingIntent.getActivty() 的工具提示中发现:

请注意,该活动将在现有活动的上下文之外启动,因此您必须在 Intent 中使用 Intent.FLAG_ACTIVITY_NEW_TASK 启动标志。

所以,我补充说:

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

到目前为止,我没有看到任何示例代码可以做到这一点,但它解决了我的问题;现在可以可靠地启动设置活动。

运行良好的完整代码...

Intent intent = new Intent(context, Settings.class);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appId);  // Identifies the particular widget...
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// Make the pending intent unique...
intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
PendingIntent pendIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.wwwidget);
views.setOnClickPendingIntent(R.id.widget, pendIntent);
appWidgetManager.updateAppWidget(appId,views);
于 2011-03-01T17:58:38.630 回答
10

我遇到了同样的问题。我发现解决方法是通过 appwidget 管理器调用更新。这是一个如何在 onEnabled 中执行此操作的示例。看来它需要在 onEnabled 和 onUpdated 中完成,这样当设备启动时,您的点击意图也会被初始化——幸运的是,在 onUpdated 中,参数已经提供了对管理器的引用。

@Override 
    public void onEnabled(Context context) {  
          //Log.v("toggle_widget","Enabled is being called"); 

          AppWidgetManager mgr = AppWidgetManager.getInstance(context); 
          //retrieve a ref to the manager so we can pass a view update 

          Intent i = new Intent(); 
          i.setClassName("yourdoman.yourpackage", "yourdomain.yourpackage.yourclass"); 
          PendingIntent myPI = PendingIntent.getService(context, 0, i, 0); 
          //intent to start service 

        // Get the layout for the App Widget 
        RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.togglelayout); 

        //attach the click listener for the service start command intent 
        views.setOnClickPendingIntent(R.id.toggleButton, myPI); 

        //define the componenet for self 
        ComponentName comp = new ComponentName(context.getPackageName(), ToggleWidget.class.getName()); 

        //tell the manager to update all instances of the toggle widget with the click listener 
        mgr.updateAppWidget(comp, views); 
} 
于 2010-01-09T02:19:03.453 回答
7

这对我有用,基于此处的信息、单词小部件示例和此处的教程

       Intent intent = new Intent(Intent.ACTION_MAIN, null);
      intent.addCategory(Intent.CATEGORY_LAUNCHER);
      // first param is app package name, second is package.class of the main activity
      ComponentName cn = new ComponentName("com....","com...MainActivity");
      intent.setComponent(cn);
      intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
      PendingIntent myPI = PendingIntent.getActivity(context, 0, intent, 0); 

    RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_word); 


    views.setOnClickPendingIntent(R.id.widget, myPI); 

    AppWidgetManager mgr = AppWidgetManager.getInstance(context); 
    mgr.updateAppWidget(comp, views); 
于 2010-12-24T06:24:32.823 回答
4

Toast 不显示的问题很简单,你不调用 show(),我也经常犯这个错误......

Toast.makeText(context, "Hello from onUpdate", Toast.LENGTH_SHORT).show();

代替

Toast.makeText(context, "Hello from onUpdate", Toast.LENGTH_SHORT);
于 2009-12-21T13:34:08.500 回答
0

将小部件添加到主屏幕时,Logcat 显示两条调试行,但不显示 Toast。(有什么想法为什么不呢?)

不要尝试ToastsBroadcastReceiver.

有没有办法测试故障在哪里?

查看 LogCat、via adb logcat、DDMS 或 Eclipse 中的 DDMS 透视图。您可能会发现有关未找到与给定Intent.

我没有看到任何明显的问题。你可能想看看我的书中的一个例子,看看它是否适合你,以及它是否能让你对可能发生的事情有所了解。

于 2009-12-20T22:36:25.180 回答
0

您必须在 res/xml/volume_changer_info.xml 中定义您的配置活动。添加此标签并提供配置活动的完全限定路径。

安卓:配置=“”


例如

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:minWidth="200dip"
    android:minHeight="100dip"
    android:updatePeriodMillis="60000"
    android:initialLayout="@layout/widget_loading"
    android:configure = "org.raza.ConfigureWidgetActivity"/>
于 2010-05-13T07:18:56.137 回答
0

我知道这个线程很古老,但是......其他答案描述了你烧焦的吐司问题。至于为什么您的弹出活动没有在触摸时启动,您可能需要启用“更新”操作才能启动并调用您的 onUpdate() 方法。为此,我认为您需要像这样添加“APPWIDGET_UPDATE”操作:

<activity android:name=".WidgetTest" android:label="@string/hello">
    <intent_filter>
        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
        <action android:name="android.intent.action.MAIN"/>
        <category android:name="android.intent.category.LAUNCHER"/>
    </intent_filter>
</activity>

同样,如果您也打算覆盖这些方法,请添加 APPWIDGET_ENABLED 和 APPWIDGET_DISABLED 操作。

这似乎是一个非常不寻常的 API,需要您声明要调用的覆盖方法。获取自定义版本的父级的常用方法是简单地覆盖/实现它们。也许这种奇怪的模式有充分的理由,但它不是我以前见过的 Java 模式。因此,我认为它可能会绊倒大量的应用程序小部件作者。好像没有这种机制,应用程序小部件还不够混乱。

于 2013-01-21T04:56:56.773 回答
0

补充一点:从Widget调用的Activity需要在Manifest文件中声明。没有抛出异常,只是看起来什么都没有发生......

于 2013-02-07T11:11:16.210 回答
-1

我只是想在某个地方注意到这一点,因为我一直(非常愚蠢地)整晚都在与这个作斗争。基本上我正确地完成了所有意图代码,但什么都不会启动。

问题是我不小心接到了这样的电话

super.onUpdate(context, appWidgetManager, appWidgetIds);

在我重写的 onUpdate() 函数的末尾。

确保您没有对 super 进行此调用,因为它会清除您设置的所有未决意图!

于 2011-11-10T02:09:12.073 回答