Lancement de l'activité à partir du widget

J'essaie de faire quelque chose qui devrait vraiment être assez facile, mais ça me rend fou. J'essaie de lancer une activité lorsqu'un widget de l'écran d'accueil est pressé, comme une activité de configuration pour le widget. Je pense que j'ai suivi mot pour mot le tutoriel sur le site Web des Développeurs Android, et même quelques tutoriels non officiels, mais je dois manquer quelque chose d'important car cela ne fonctionne pas.

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

}

Lors de l'ajout du widget à L'écran D'accueil, Logcat montre les deux lignes de débogage, mais pas le Toast. (Des idées pourquoi pas?) Cependant, plus vexant est que lorsque je clique ensuite sur le bouton avec le PendingIntent associé, rien ne se passe du tout. Je sais que L'activité" WidgetTest " peut s'exécuter car si je configure une intention à partir de l'activité principale, elle se lance bien.

Au cas où cela importerait, voici le fichier manifeste 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" />

Existe-t-il un moyen de tester où se trouve la faute? I. e. est le défaut que le bouton N'est pas lié correctement au PendingIntent, ou que le PendingIntent ou L'intention ne trouve pas WidgetTest.classe, etc?

Merci beaucoup pour votre aide!

Steve

36
demandé sur Steve Haley 2009-12-21 01:05:26

10 réponses

J'avais le même problème. J'ai découvert que le correctif consiste à appeler une mise à jour via le gestionnaire appwidget. voici un exemple de la façon de le faire dans onEnabled. Il semble que cela doit être fait à la fois dans onEnabled et onUpdated afin que lorsque le périphérique est sous tension, votre intention de clic soit également initialisée - dans onUpdated, les paramètres fournissent déjà la référence au gestionnaire, heureusement.

@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); 
} 
9
répondu mylock 2010-01-09 21:28:41

Ramener cette Façon d'entre les morts, mais j'ai eu un problème similaire et je pense que je l'ai finalement résolu... comme vous, j'ai eu un PendingIntent que j'ai attaché à la RemoteView. Parfois, cela fonctionnerait, et parfois cela échouerait. Il a été me rend fou.

Ce que j'ai trouvé à partir d'une info-bulle sur le PendingIntent.getActivty() était:

Notez que l'activité sera démarrée en dehors du contexte d'une activité existante, vous devez donc utiliser Intention.Flag_activity_new_task drapeau de lancement dans L'intention.

Donc, j'ai ajouté:

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

Aucun exemple de code que j'ai vu jusqu'à présent ne le fait, mais il a résolu mon problème; L'activité des paramètres est maintenant lancée de manière fiable.

Le code complet qui fonctionne bien...

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);
22
répondu Brent Chartrand 2011-03-01 17:58:38

Cela a fonctionné pour moi, basé sur info ici, l'exemple de widget word, et le tutoriel ici

       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); 
7
répondu kdahlhaus 2010-12-24 06:24:32

Le problème avec le Toast qui ne s'affiche pas est facile, vous n'appelez pas show (), une erreur que je fais toujours aussi... do

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

Au Lieu de

Toast.makeText(context, "Hello from onUpdate", Toast.LENGTH_SHORT);
4
répondu JohanS 2009-12-21 13:34:08

Steve,

Avez-vous trouvé le problème? J'utilise un widget et cela fonctionne très bien pour moi sans astuce onEnabled. Je suis intéressé pourquoi il ne fait pas pour vous.

Ma conjecture: dans votre code d'origine, veuillez essayer

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

Au Lieu de

PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
1
répondu Fedor 2010-05-01 14:47:00

Lors de l'ajout du widget écran d'accueil, Logcat montre les deux lignes de débogage, mais pas le Toast. (Des idées pourquoi pas?)

N'essayez pas de lancer Toasts à partir d'un BroadcastReceiver.

Existe-t-il un moyen de tester où la faute est?

Regardez LogCat, via adb logcat, DDMS ou la perspective DDMS dans Eclipse. Vous pouvez trouver des avertissements sur le fait de ne pas trouver une activité correspondant au Intent donné.

Je ne vois aucun problème évident. Vous voudrez peut-être prendre un regardez un de mes exemples de livres et voyez si cela fonctionne pour vous, et si cela vous donne une idée de ce qui peut être en cours.

0
répondu CommonsWare 2009-12-20 22:36:25

Vous devez définir votre activité de configuration dans res / xml / volume_changer_info.XML. Ajoutez cette balise et donnez un chemin complet à l'activité de configuration.

Android:configurer = ""


Par exemple

<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
répondu Raza 2010-05-13 09:42:12

Je voulais juste noter ceci ici quelque part car j'ai été (assez bêtement) en train de me battre toute la nuit. Fondamentalement, j'ai fait tout le code d'intention correctement mais rien ne serait lancé.

Le problème était que j'ai accidentellement eu un appel comme celui-ci

super.onUpdate(context, appWidgetManager, appWidgetIds);

À la fin de ma fonction onUpdate () remplacée.

Assurez-vous que vous n'avez pas Cet appel à super car il effacera toutes les intentions en attente que vous avez configurées!

0
répondu Sverrir Sigmundarson 2011-11-10 02:09:12

Je sais que ce fil est ancien, mais... D'autres réponses décrivent votre problème de pain grillé brûlé. Quant à la raison pour laquelle votre activité pop-up ne se lance pas au toucher, vous devrez peut-être activer l'action "update" pour lancer et appeler votre méthode onUpdate (). Pour cela, je pense que vous devez ajouter L'action" APPWIDGET_UPDATE " comme ceci:

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

Ajoutez également les actions APPWIDGET_ENABLED et APPWIDGET_DISABLED si vous avez l'intention de remplacer ces méthodes aussi.

Il semble être une API très inhabituelle qui vous oblige à déclarer les méthodes remplacées que vous voulez appeler. La façon habituelle d'obtenir votre version personnalisée d'un parent est de simplement les remplacer/les implémenter. Peut-être y a-t-il une bonne raison pour ce modèle étrange, mais ce n'est pas un modèle Java que j'ai vu auparavant. Je pense donc qu'il est susceptible de trébucher beaucoup d'auteurs de widgets d'applications. Comme si les widgets de l'application n'étaient pas assez confus sans ce mécanisme.

0
répondu Melinda Green 2013-01-21 04:56:56

Un point supplémentaire: L'activité appelée à partir du Widget doit être déclarée dans le fichier manifeste. Aucune exception n'est lancée, On dirait que rien ne se passe...

0
répondu Stephan 2013-02-07 11:11:16