Android 从小部件启动活动

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1937236/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 03:50:40  来源:igfitidea点击:

Launching activity from widget

androidandroid-widget

提问by Steve Haley

I'm trying to do something which really ought to be quite easy, but it's driving me crazy. I'm trying to launch an activity when a home screen widget is pressed, such as a configuration activity for the widget. I think I've followed word for word the tutorial on the Android Developers website, and even a few unofficial tutorials as well, but I must be missing something important as it doesn't work.

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

Here is the code:

这是代码:

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);
    }
}

}

}

When adding the widget to the homescreen, Logcat shows the two debugging lines, though not the Toast. (Any ideas why not?) However, more vexing is that when I then click on the button with the PendingIntent associated with it, nothing happens at all. I know the "WidgetTest" activity can run because if I set up an Intent from within the main activity, it launches fine.

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

In case it matters, here is the Android Manifest file:

如果重要,这里是 Android 清单文件:

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

Is there a way to test where the fault is? I.e. is the fault that the button isn't linked properly to the PendingIntent, or that the PendingIntent or Intent isn't finding WidgetTest.class, etc?

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

Thanks very much for your help!

非常感谢您的帮助!

Steve

史蒂夫

采纳答案by mylock

I was having the same issue. I discovered that the fix is to call an update through the appwidget manager. here is an example of how to do that in onEnabled. It appears it needs to be done in both onEnabled and onUpdated so that when device is powering on your click intent is also intialized - in onUpdated the params already provide the reference to the manager, luckily.

我遇到了同样的问题。我发现修复方法是通过 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); 
} 

回答by Brent Chartrand

Bringing this wayback from the dead, but I had a similar problem and I think I finally solved it... like you, I had a PendingIntent that I attached to the RemoteView. Sometimes it would work, and sometimes it would fail. It was driving me crazy.

以这种方式从死里复活,但我遇到了类似的问题,我想我终于解决了……像你一样,我有一个挂在 RemoteView 上的 PendingIntent。有时它会奏效,有时它会失败。它让我发疯。

What I found from a tooltip on the PendingIntent.getActivty() was:

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

Note that the activity will be started outside of the context of an existing activity, so you must use the Intent.FLAG_ACTIVITY_NEW_TASK launch flag in the Intent.

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

so, I added:

所以,我补充说:

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

No example code I've seen so far does this, but it solved my problem; the Settings activity is now launched reliably.

到目前为止,我还没有见过这样的示例代码,但它解决了我的问题;现在可以可靠地启动设置活动。

The full code that's working well...

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

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);

回答by kdahlhaus

This worked for me, based on info here, the word widget sample, and the tutorial here

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

       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); 

回答by JohanS

The problem with the Toast not showing is easy, you don't call show(), a mistake I always do too... do

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

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

instead of

代替

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

回答by Fedor

Steve,

史蒂夫,

Have you found the problem? I use widget and it works fine for me without onEnabled trick. I'm interested why it doesn't for you.

你发现问题了吗?我使用小部件,它在没有 onEnabled 技巧的情况下对我来说很好用。我感兴趣的是为什么它不适合你。

My guess: in your original code please try

我的猜测:在您的原始代码中,请尝试

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

instead of

代替

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

回答by Raza

you must define your configuration activity in res/xml/volume_changer_info.xml. Add this tag and give a fully qualified path to the configuration activity.

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

android:configure = ""

机器人:配置=“”



e.g.

例如

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

回答by CommonsWare

When adding the widget to the homescreen, Logcat shows the two debugging lines, though not the Toast. (Any ideas why not?)

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

Don't try launching Toastsfrom a BroadcastReceiver.

不要尝试ToastsBroadcastReceiver.

Is there a way to test where the fault is?

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

Look at LogCat, via adb logcat, DDMS, or the DDMS perspective in Eclipse. You may find warnings about not finding an activity to match the given Intent.

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

I do not see any obvious problem. You may want to take a peek at one of my book examplesand see if that works for you, and if it gives you any idea of what may be afoot.

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

回答by Melinda Green

I know this thread is ancient, but... Other answers describe your burnt Toast problem. As to why your pop-up activity doesn't launch on touch, you may need to enable the "update" action in order to launch and call your onUpdate() method. For that I think you need to add the "APPWIDGET_UPDATE" action like this:

我知道这个线程很古老,但是......其他答案描述了你烧焦的 Toast 问题。至于为什么您的弹出 Activity 不会在触摸时启动,您可能需要启用“更新”操作才能启动并调用您的 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>

Likewise add the APPWIDGET_ENABLED and APPWIDGET_DISABLED actions if you intend to override those methods too.

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

It seems to be a very unusual API that requires you to declare the overridden methods that you want called. The usual way to get your custom version of a parent is to simply override/implement them. Maybe there's a good reason for this strange pattern, but it is not a Java pattern that I've seen before. I therefore think it is likely to trip up a great deal of app widget authors. As if app widgets were not confusing enough without this mechanism.

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

回答by Stephan

One additional point: The Activity that is called from the Widget needs to be declared in the Manifest file. No exception is thrown, just looks like nothing happens...

补充一点:从Widget调用的Activity需要在Manifest文件中声明。没有抛出异常,只是看起来没有任何反应......

回答by Sverrir Sigmundarson

I just wanted to note this here somewhere as I have been (quite stupidly) battling this all night. Basically I did all the intent code correctly but nothing would be launched.

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

The problem was that I accidentally had a call like this

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

super.onUpdate(context, appWidgetManager, appWidgetIds);

at the end of my Overridden onUpdate() function.

在我覆盖的 onUpdate() 函数结束时。

Make sure you DO NOThave this call to super as it will clear out all pending intents you've set up!

确保你没有这个对 super 的调用,因为它会清除你设置的所有挂起的意图!