2009-12-20 30 views
35

Ich versuche etwas zu tun, das wirklich ziemlich einfach sein sollte, aber es macht mich verrückt. Ich versuche, eine Aktivität zu starten, wenn ein Startbildschirm-Widget gedrückt wird, z. B. eine Konfigurationsaktivität für das Widget. Ich denke, ich habe Wort für Wort das Tutorial auf der Android-Entwickler-Website und sogar ein paar inoffizielle Tutorials gefolgt, aber ich muss etwas wichtiges verpassen, wie es nicht funktioniert. HierStarten von Aktivität von Widget

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

}

Wenn das Widget auf dem Homescreen hinzufügen, Logcat zeigt die beiden Debug-Linien, wenn auch nicht der Toast. (Irgendwelche Ideen, warum nicht?) Aber ärgerlicher ist, dass, wenn ich dann auf den Button mit dem PendingIntent damit verbunden bin, nichts passiert. Ich weiß, dass die "WidgetTest" -Aktivität ausgeführt werden kann, denn wenn ich einen Intent innerhalb der Hauptaktivität einrichte, startet er gut.

Bei zählt es, hier ist die Android-Manifest-Datei:

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

Gibt es eine Möglichkeit zu testen, wo der Fehler ist? I.e. ist der Fehler, dass die Schaltfläche nicht ordnungsgemäß mit dem PendingIntent verknüpft ist oder dass der PendingIntent oder Intent WidgetTest.class usw. nicht findet?

Vielen Dank für Ihre Hilfe!

Steve

Antwort

9

Ich hatte das gleiche Problem. Ich habe festgestellt, dass das Problem darin besteht, über den Appwidget-Manager ein Update aufzurufen. Hier ist ein Beispiel dafür, wie man das in onEnabled macht.Es scheint, dass es sowohl in OnEnabled als auch OnUpdated durchgeführt werden muss, damit beim Einschalten des Geräts auch die Klickabsicht initialisiert wird - in onUpdated stellen die Params zum Glück bereits den Verweis auf den Manager bereit.

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

Leider nein, ich habe noch nicht herausgefunden, wie das geht. Es muss etwas unklares sein, so wie du, ich habe alle Tutorials gelesen, die ich finden konnte, aber nie etwas gefunden, das funktioniert hat. Ich habe gerade dieses Projekt eingestellt und angefangen, an etwas anderem zu arbeiten, bis ich weiß, wie ich Android besser gebrauchen kann. –

+0

Hey Steve. Ich denke, ich habe die Lösung gefunden. Ich entwickle auf 2.0.1. Der Schlüssel war, diesen genauen Code in onUpdated zu verschieben und dann eine weitere Sache aufzurufen - ein Verweis auf AppWidgetManager kommt über die Parameter in den OnUpdated. Komponentenname comp = new Komponentenname (context.getPackageName(), ToggleWidget.class.getName()); appWidgetManager.updateAppWidget (comp, Ansichten); Diese Version sagt es, alle Instanzen des Widgets wie folgt zu aktualisieren. Das einzige Problem ist jetzt, onEnabled onUpdate einmal aufrufen zu lassen, so dass es eintritt, wenn der Benutzer ein Widget zu Hause hinzufügt. – mylock

+1

+1 danke. Durch Hinzufügen des mgr.updateAppWidget konnte ich endlich mein Widget dazu bringen, dasselbe zu tun. – nategood

0

Wenn das Widget auf dem Homescreen Zugabe zeigt Logcat die beiden Debug-Linien, wenn auch nicht der Toast. (Irgendwelche Ideen, warum nicht?)

Versuchen Sie nicht, Toasts von einem BroadcastReceiver starten.

Gibt es eine Möglichkeit zu testen, wo der Fehler ist?

Betrachten Sie LogCat, über adb logcat, DDMS oder die Perspektive DDMS in Eclipse. Möglicherweise finden Sie Warnungen, dass keine Aktivität gefunden wird, die der angegebenen Intent entspricht.

Ich sehe kein offensichtliches Problem. Vielleicht möchten Sie einen Blick auf one of my book examples werfen und sehen, ob das für Sie funktioniert, und ob es Ihnen eine Ahnung davon gibt, was im Gange sein könnte.

+0

LogCat dies sagt, wenn die Schaltfläche hinzugefügt: DEBUG/Steve (772): Laufen für appWidgetId 33 DEBUG/Steve (772): Nach dem Toast Linie DEBUG/Launcher (622): dump Extras: content = Bundle [{appWidgetId = 33}] WARN/InputManagerService (571): Fenster bereits fokussiert, Fokusverstärkung ignoriert von: com.android.internal.view.IInputMethodClient $ Stub $ Proxy @ 4388abe0 aber dann gar nichts wenn die Taste gedrückt wird. Danke für das Beispielprogramm, ich werde durchsehen und sehen, ob ich ein paar Hinweise finde, wo ich falsch gelaufen bin. –

+0

Hmmm ... es fühlt sich fast so an, als würde es deinen Klick nicht registrieren. Sind Sie sicher, dass sich R.id.button in Ihrem Widget-Layout befindet? – CommonsWare

+0

Ich denke es ist. Ich habe eine

4

Das Problem mit der Toast nicht einfach ist, zeigt, Sie rufen Sie nicht show(), ein Fehler, den ich auch immer tun ... tun

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

statt

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

Lol, danke dafür. Das war die Art einfacher Reparatur, von der ich hoffte, dass sie benötigt wurde: P –

+0

Das war tatsächlich die Lösung für das Problem mit dem Toast. Jetzt, wenn ich nur herausfinden kann, warum die Aktivität nicht startet ... –

1

Steve,

Haben auch Sie das Problem? Ich benutze Widget und es funktioniert gut für mich ohne OnEnabled Trick. Ich bin interessiert, warum es nicht für dich ist.

Meine Vermutung: in Ihrem ursprünglichen Code bitte versuchen Sie es

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

statt

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

Hallo, diese Frage war schon lange nicht mehr aktiv! Die von Ihnen vorgeschlagene Änderung macht jedoch keinen Unterschied. Ich konnte das Problem lösen, indem ich das Projekt von vorne anfing. Soweit ich das beurteilen kann, sind die beiden Projekte identisch, aber dieses funktioniert nicht. Ich verstehe nicht, warum das nicht funktioniert, aber es ist kein Problem, da der andere es tut. –

+0

Dieser Code ist der perfekte –

0

Sie müssen in res/xml/volume_changer_info.xml Ihre Konfiguration Aktivität definieren. Fügen Sie dieses Tag hinzu und geben Sie einen vollständig qualifizierten Pfad für die Konfigurationsaktivität an.

android: configure = ""


z.B.

<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

Hallo, ich denke, wir reden über verschiedene Dinge, wenn wir auf eine "Konfigurationsaktivität" verwiesen. Ich meinte etwas, das jederzeit nach dem Hinzufügen des Widgets gestartet werden könnte, anstatt etwas, das beim Hinzufügen des Widgets gestartet wird. Dieses Problem wurde vor einiger Zeit gelöst, aber danke, dass du versucht hast zu helfen! –

7

Dieser arbeitete für mich, basierend auf Informationen hier das Wort Widget Probe und 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); 
21

bringen diese Weg von den Toten zurück, aber ich hatte ein ähnliches Problem und ich denke, Ich habe es endlich gelöst ... wie du, ich hatte einen PendingIntent, den ich an den RemoteView angehängt habe. Manchmal würde es funktionieren, und manchmal würde es scheitern. Es hat mich verrückt gemacht.

Was ich von einem Tooltip auf dem PendingIntent.getActivty gefunden() war:

Beachten Sie, dass die Aktivität außerhalb des Kontexts einer bestehenden Aktivität gestartet wird, so dass Sie die Intent.FLAG_ACTIVITY_NEW_TASK Start verwenden müssen Flagge in der Absicht.

so fügte ich hinzu:

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 

Kein Beispiel Code, den ich bisher gesehen habe tut dies, aber es mein Problem gelöst; Die Aktivität Einstellungen wird nun zuverlässig gestartet.

Der vollständige Code, der gut funktioniert hat ...

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

Danke Mann! funktioniert perfekt – Jakob

+0

für mich war es die 'setData (...)' Linie, die es funktioniert hat. davor konnte ich keine Extras erhalten. Ich weiß, schwer zu glauben. –

0

Ich wollte nur das hier irgendwo beachten, wie ich (recht dümmlich) kämpft die ganze Nacht gewesen sein. Im Grunde genommen habe ich den ganzen Intellekt-Code richtig gemacht, aber nichts würde gestartet werden.

Das Problem war, dass ich aus Versehen einen Anruf wie diese

super.onUpdate(context, appWidgetManager, appWidgetIds); 

am Ende meiner Überschrieben onUpdate() Funktion hatte.

Stellen Sie sicher, dass Sie NICHT haben diesen Anruf zu super, da es alle ausstehenden Absichten löschen Sie eingerichtet haben!

+1

Das ist seltsam, zumindest [in den letzten Android-Versionen AppWidgetProvider.onUpdate() tut nichts] (http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.1. 1_r1/android/appwidget/AppWidgetProvider.java # AppWidgetProvider.onUpdate% 28android.content.Context% 2Candroid.appwidget.AppWidgetManager% 2Cint []% 29). – sschuberth

+0

Ja, es verwirrte mich auch, aber diese Zeile zu entfernen war was für mich :) –

0

Ich weiß, dass dieser Thread alt ist, aber ... Andere Antworten beschreiben Ihr verbranntes Toast-Problem. Warum Ihre Popup-Aktivität bei Berührung nicht gestartet wird, müssen Sie möglicherweise die Aktion "update" aktivieren, um die onUpdate() -Methode zu starten und aufzurufen. Dafür habe ich glaube, Sie brauchen die „APPWIDGET_UPDATE“ Aktion wie folgt hinzuzufügen:

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

Ebenso fügen Sie die APPWIDGET_ENABLED und APPWIDGET_DISABLED Aktionen, wenn Sie beabsichtigen, auch die Methoden zu überschreiben.

Es scheint eine sehr ungewöhnliche API zu sein, die es erfordert, dass Sie die überschriebenen Methoden deklarieren, die Sie aufgerufen haben. Der übliche Weg, um Ihre benutzerdefinierte Version eines Elternteils zu erhalten, besteht darin, sie einfach zu überschreiben/zu implementieren. Vielleicht gibt es einen guten Grund für dieses seltsame Muster, aber es ist kein Java-Muster, das ich zuvor gesehen habe. Ich denke daher, dass es wahrscheinlich viele App-Widget-Autoren stolpern wird. Als ob App-Widgets ohne diesen Mechanismus nicht verwirrend genug wären.

0

Ein weiterer Punkt: Die Aktivität, die vom Widget aufgerufen wird, muss in der Manifest-Datei deklariert werden. Es wird keine Ausnahme geworfen, sieht genauso aus wie nichts passiert ...

Verwandte Themen