web-dev-qa-db-fra.com

Activité de lancement depuis le widget

J'essaie de faire quelque chose qui devrait vraiment être assez facile, mais ça me rend folle. J'essaie de lancer une activité lorsque l'utilisateur appuie sur un widget de l'écran d'accueil, tel qu'une activité de configuration pour le widget. Je pense avoir suivi le didacticiel Word pour Word sur le site Web des développeurs Android, et même quelques tutoriels non officiels, mais il me manque quelque chose d’important car il 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 affiche les deux lignes de débogage, mais pas le Toast. (Toutes les idées pourquoi pas?) Cependant, plus vexant est que quand je clique ensuite sur le bouton avec le PendingIntent associé, rien ne se passe. Je sais que l'activité "WidgetTest" peut s'exécuter, car si j'installe une intention à partir de l'activité principale, elle se lance correctement.

Au cas où cela serait important, voici le fichier Manifest 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" />

Y a-t-il un moyen de tester où la faute est? C'est à dire. est-ce la faute que le bouton ne soit pas lié correctement à PendingIntent ou que PendingIntent ou Intent ne trouve pas WidgetTest.class, etc.?

Merci beaucoup pour votre aide!

Steve

36
Steve Haley

J'avais le même problème. J'ai découvert que le correctif consiste à appeler une mise à jour via le gestionnaire d'appwidget. Voici un exemple de la façon de faire cela dans onEnabled. Il semble que cela doit être fait à la fois sur onEnabled et onUpdated, de sorte que lorsque le périphérique est allumé, l'intention de clic est également intialisé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
mylock

Ramener ceci chemin de retour des morts, mais j'avais un problème similaire et je pense que je l'ai finalement résolu ... comme vous, j'avais un PendingIntent que j'avais attaché à RemoteView. Parfois cela fonctionnerait et parfois cela échouerait. Cela me rendait fou.

Ce que j'ai trouvé dans une info-bulle sur PendingIntent.getActivty () était:

Notez que l'activité sera démarrée en dehors du contexte d'une activité existante. Vous devez donc utiliser l'indicateur de lancement Intent.FLAG_ACTIVITY_NEW_TASK dans l'objectif.

alors j'ai ajouté:

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

Aucun exemple de code que j'ai vu jusqu'à présent ne fait cela, mais cela a résolu mon problème. l'activité 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
Brent Chartrand

Cela a fonctionné pour moi, en fonction des informations ici, de l'exemple de widget Word et du 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
kdahlhaus

Le problème avec le pain grillé qui ne se montre pas est facile, vous n’appelez pas show (), une erreur que je fais toujours aussi.

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

au lieu de

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

Steve,

Avez-vous trouvé le problème? J'utilise un widget et cela fonctionne bien pour moi sans astuce onEnabled. Je suis intéressé pourquoi ce n'est pas pour vous.

À mon avis: 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
Fedor

Un point supplémentaire: l'activité appelée à partir du widget doit être déclarée dans le fichier manifeste. Aucune exception n'est levée, il semblerait que rien ne se passe ...

0
Stephan

Je sais que ce fil est ancien, mais… .. D'autres réponses décrivent votre problème de pain grillé brûlé. Pour savoir pourquoi votre activité contextuelle ne démarre pas au toucher, vous devrez peut-être activer l'action "update" afin de lancer et d'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>

De même, ajoutez les actions APPWIDGET_ENABLED et APPWIDGET_DISABLED si vous souhaitez également remplacer ces méthodes. 

Cela semble être une API très inhabituelle qui vous oblige à déclarer les méthodes remplacées que vous souhaitez appeler. Le moyen habituel d’obtenir votre version personnalisée d’un parent est tout simplement de les remplacer/de les implémenter. Il existe peut-être une bonne raison pour ce modèle étrange, mais ce n'est pas un modèle Java que j'ai déjà vu. Je pense donc que cela risque de faire trébucher beaucoup d'auteurs de widgets d'applications. Comme si les widgets d'applications n'étaient pas assez déroutants sans ce mécanisme.

0
Melinda Green

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

Android: configure = ""


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
Raza

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

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

Y at-il un moyen de tester où la faute est?

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

Je ne vois pas de problème évident. Vous voudrez peut-être jeter un coup d'œil sur un de mes exemples de livre et voir si cela fonctionne pour vous et s'il vous donne une idée de ce qui se prépare.

0
CommonsWare