简体   繁体   English

从小部件启动活动

[英]Launching activity from widget

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. 将小部件添加到主屏幕时,Logcat会显示两条调试行,但不会显示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. (任何想法为什么不呢?)然而,更令人烦恼的是,当我点击与PendingIntent相关联的按钮时,根本没有任何事情发生。 I know the "WidgetTest" activity can run because if I set up an Intent from within the main activity, it launches fine. 我知道“WidgetTest”活动可以运行,因为如果我在主要活动中设置了一个Intent,它会正常启动。

In case it matters, here is the Android Manifest file: 如果重要,这里是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" />

Is there a way to test where the fault is? 有没有办法测试故障的位置? Ie 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 史蒂夫

Bringing this way back 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. 把这种方式从死里复活,但是我遇到了类似的问题,我想我终于解决了它......就像你一样,我有一个挂在远程视图上的PendingIntent。 Sometimes it would work, and sometimes it would fail. 有时它会起作用,有时会失败。 It was driving me crazy. 这让我发疯了。

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

I was having the same issue. 我遇到了同样的问题。 I discovered that the fix is to call an update through the appwidget manager. 我发现修复是通过appwidget管理器调用更新。 here is an example of how to do that in onEnabled. 这是一个如何在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. 它似乎需要在onEnabled和onUpdated中完成,这样当设备启动时,你的点击意图也是初始化的 - 在onUpdated中,params已经提供了对经理的引用,幸运的是。

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

This worked for me, based on info here, the word widget sample, and the tutorial here 这对我有用,基于这里的信息,单词widget示例和这里的教程

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

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

Steve, 史蒂夫,

Have you found the problem? 你找到了问题吗? I use widget and it works fine for me without onEnabled trick. 我使用小部件,没有onEnabled技巧它对我很好。 I'm interested why it doesn't for you. 我很感兴趣为什么它不适合你。

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

I know this thread is ancient, but... Other answers describe your burnt Toast problem. 我知道这个线程是古老的,但是...其他答案描述了你烧焦的Toast问题。 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. 至于您的弹出活动无法在触摸时启动的原因,您可能需要启用“更新”操作才能启动并调用onUpdate()方法。 For that I think you need to add the "APPWIDGET_UPDATE" action like this: 为此,我认为您需要添加“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. 它似乎是一个非常不寻常的API,需要您声明要调用的重写方法。 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. 也许这个奇怪的模式有一个很好的理由,但它不是我以前见过的Java模式。 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. 如果没有这种机制,app小部件就不会让人感到困惑。

One additional point: The Activity that is called from the Widget needs to be declared in the Manifest file. 还有一点:需要在Manifest文件中声明从Widget调用的Activity。 No exception is thrown, just looks like nothing happens... 没有异常被抛出,只是看起来没有任何反应......

When adding the widget to the homescreen, Logcat shows the two debugging lines, though not the Toast. 将小部件添加到主屏幕时,Logcat会显示两条调试行,但不会显示Toast。 (Any ideas why not?) (任何想法为什么不?)

Don't try launching Toasts from a BroadcastReceiver . 不要尝试从BroadcastReceiver启动Toasts

Is there a way to test where the fault is? 有没有办法测试故障的位置?

Look at LogCat, via adb logcat , DDMS, or the DDMS perspective in Eclipse. 通过adb logcat ,DDMS或Eclipse中的DDMS透视图查看LogCat。 You may find warnings about not finding an activity to match the given Intent . 您可能会发现有关未找到与给定Intent匹配的活动的警告。

I do not see any obvious problem. 我没有看到任何明显的问题。 You may want to take a peek at one of my book examples and see if that works for you, and if it gives you any idea of what may be afoot. 你可能想看看我的一本书的例子 ,看看它是否适合你,以及它是否让你知道可能正在发生的事情。

you must define your configuration activity in res/xml/volume_changer_info.xml. 您必须在res / xml / volume_changer_info.xml中定义配置活动。 Add this tag and give a fully qualified path to the configuration activity. 添加此标记并为配置活动提供完全限定的路径。

android:configure = "" android:configure =“”


eg 例如

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

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. 在我的Overridden onUpdate()函数的末尾。

Make sure you DO NOT have this call to super as it will clear out all pending intents you've set up! 确保你没有这个超级电话,因为它会清除你设置的所有待定意图!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM