Запуск активности из виджета - PullRequest
36 голосов
/ 21 декабря 2009

Я пытаюсь сделать что-то, что действительно должно быть довольно легким, но это сводит меня с ума. Я пытаюсь запустить действие при нажатии виджета на главном экране, например, действие по настройке виджета. Я думаю, что дословно следовал учебнику на веб-сайте разработчиков 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 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 и т. д.?

Большое спасибо за вашу помощь!

Steve

Ответы [ 10 ]

22 голосов
/ 01 марта 2011

Возвращение этого пути из мертвых, но у меня была похожая проблема, и я думаю, что наконец-то решил ее ... как и у вас, у меня был PendingIntent, который я прикрепил к RemoteView. Иногда это сработало, а иногда не получилось. Это сводило меня с ума.

То, что я нашел из всплывающей подсказки в PendingIntent.getActivty (), было:

Обратите внимание, что действие будет запущено вне контекста существующего действия, поэтому вы должны использовать флаг запуска Intent.FLAG_ACTIVITY_NEW_TASK в Intent.

Итак, я добавил:

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);
9 голосов
/ 09 января 2010

У меня была такая же проблема. Я обнаружил, что исправить это вызвать обновление через менеджер 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); 
} 
7 голосов
/ 24 декабря 2010

Это сработало для меня, основываясь на информации здесь, образце слова и учебнике здесь

       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); 
4 голосов
/ 21 декабря 2009

Проблема с тостом не показывается легко, вы не вызываете show (), ошибка, которую я всегда делаю тоже ... делать

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

вместо

Toast.makeText(context, "Hello from onUpdate", Toast.LENGTH_SHORT);
1 голос
/ 01 мая 2010

Стив,

Вы нашли проблему? Я использую виджет, и он отлично работает для меня без трюка onEnabled Мне интересно, почему это не для тебя.

Мое предположение: в исходном коде попробуйте

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

вместо

PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
0 голосов
/ 07 февраля 2013

Еще один момент: действие, которое вызывается из виджета, должно быть объявлено в файле манифеста. Не исключение, просто выглядит так, будто ничего не происходит ...

0 голосов
/ 21 января 2013

Я знаю, что эта тема древняя, но ... Другие ответы описывают вашу проблему сгоревшего тоста. Что касается того, почему всплывающая активность не запускается при прикосновении, вам может потребоваться включить действие «обновление», чтобы запустить и вызвать метод 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, который я видел раньше. Поэтому я думаю, что это может сбить с толку многих авторов виджетов приложений. Как будто виджеты приложения не достаточно запутались без этого механизма.

0 голосов
/ 10 ноября 2011

Я просто хотел отметить это где-то здесь, поскольку я (довольно глупо) боролся с этим всю ночь. По сути, я правильно сделал весь код намерения, но ничего не запустилось.

Проблема была в том, что у меня случайно был такой звонок

super.onUpdate(context, appWidgetManager, appWidgetIds);

в конце моей переопределенной функции onUpdate ().

Убедитесь, что у вас НЕ есть этот вызов super, поскольку он очистит все ожидающие намерения, которые вы установили!

0 голосов
/ 13 мая 2010

вы должны определить свою конфигурационную активность в res / xml / volume_changer_info.xml. Добавьте этот тег и укажите полный путь к операции настройки.

android: configure = ""


, например

<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"/>
0 голосов
/ 21 декабря 2009

При добавлении виджета в домашний экран, Logcat показывает два линии отладки, хотя не тост. (Есть идеи почему бы и нет?)

Не пытайтесь запустить Toasts с BroadcastReceiver.

Есть ли способ проверить, где неисправность есть

Посмотрите на LogCat через adb logcat, DDMS или перспективу DDMS в Eclipse. Вы можете найти предупреждения о том, что не можете найти действие, соответствующее указанному Intent.

Я не вижу очевидной проблемы. Возможно, вы захотите взглянуть на один из примеров моей книги и посмотреть, работает ли он для вас, и дает ли он вам представление о том, что может происходить.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...