2009-12-20 10 views
35

Sto provando a fare qualcosa che dovrebbe essere abbastanza semplice, ma mi sta facendo impazzire. Sto tentando di avviare un'attività quando viene premuto un widget della schermata iniziale, ad esempio un'attività di configurazione per il widget. Penso di aver seguito parola per parola il tutorial sul sito web degli sviluppatori Android e anche qualche tutorial non ufficiale, ma mi manca qualcosa di importante in quanto non funziona.Avvio dell'attività dal widget

Ecco il codice:

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

}

Quando si aggiunge il widget per la homescreen, Logcat mostra le due linee di debug, anche se non la Toast. (Qualche idea, perché no?) Tuttavia, più fastidio è che quando faccio clic sul pulsante con il PendingIntent ad esso associato, non accade nulla. So che l'attività "WidgetTest" può essere eseguita perché se si imposta un Intent dall'attività principale, viene avviato correttamente.

Nel caso in cui le cose, qui è il file manifest di 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" /> 

C'è un modo per testare in cui la colpa è? Cioè è il difetto che il pulsante non è collegato correttamente a PendingIntent o che PendingIntent o Intent non sta trovando WidgetTest.class, ecc.?

Grazie mille per il vostro aiuto!

Steve

risposta

9

Stavo avendo lo stesso problema. Ho scoperto che la soluzione è chiamare un aggiornamento tramite il gestore appwidget. ecco un esempio di come farlo in onEnabled.Sembra che sia necessario farlo sia su onEnabled che su onUpdated in modo che quando il dispositivo è acceso, anche l'intento del clic venga inizializzato - in suAggiornato i parametri forniscono già il riferimento al gestore, per fortuna.

@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

Purtroppo no, non ho ancora capito come farlo. Deve essere qualcosa di oscuro, come te leggi tutti i tutorial che ho trovato, ma non ho mai trovato qualcosa che funzionasse. Ho appena finito di accantonare questo progetto e ho iniziato a lavorare su qualcos'altro fino a quando non sapessi come usare Android un po 'meglio. –

+0

Ehi, Steve. Penso di aver scoperto la soluzione. Sto sviluppando su 2.0.1. La chiave stava spostando questo codice esatto in onUpdated e poi chiamando una cosa aggiuntiva: un riferimento ad AppWidgetManager arriva a onUpdated tramite i parametri. ComponentName comp = new ComponentName (context.getPackageName(), ToggleWidget.class.getName()); appWidgetManager.updateAppWidget (comp, visualizzazioni); Questa versione dice di aggiornare tutte le istanze del widget come questo. Unico problema ora consiste nell'effettuare la chiamata onEnabled suUpUpdate una volta, in modo tale che si trovi quando l'utente aggiunge widget a casa. – mylock

+1

+1 grazie. aggiungendo mgr.updateAppWidget ho potuto finalmente ottenere il mio widget per fare lo stesso. – nategood

0

Quando si aggiunge il widget per la homescreen , Logcat mostra i due linee di debug, anche se non la Toast. (Tutte le idee perché no?)

Non tentare di lanciare Toasts da un BroadcastReceiver.

C'è un modo per verificare dove si trova l'errore ?

Guardate LogCat, via adb logcat, DDMS, o la prospettiva DDMS in Eclipse. Potresti trovare avvertenze sulla mancata ricerca di un'attività corrispondente al dato Intent.

Non vedo alcun problema evidente. Potresti dare un'occhiata a one of my book examples e vedere se questo funziona per te, e se ti dà qualche idea di cosa potrebbe essere in piedi.

+0

LogCat dice che questo quando si aggiunge il pulsante: DEBUG/Steve (772): Funzionando per appWidgetId 33 DEBUG/Steve (772): Dopo la linea brindisi DEBUG/Launcher (622): dumping extras content = Bundle [{appWidgetId = 33}] WARN/InputManagerService (571): Finestra già focalizzata, ignorando il guadagno di focus di: com.android.internal.view.IInputMethodClient $ Stub $ Proxy @ 4388abe0 ma poi nulla quando si preme il pulsante. Grazie per il programma di esempio, guarderò e vedrò se riesco a trovare qualche inidicazione su dove ho sbagliato. –

+0

Hmmm ... sembra quasi che non stia registrando il tuo clic. Sei sicuro che R.id.button si trovi nel layout del tuo widget? – CommonsWare

+0

Penso che lo sia. Ho una vista

4

Il problema con il toast non mostrare è facile, non si chiama show(), un errore faccio sempre troppo ... fare

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

invece di

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

Lol, grazie per quello. Questo è il tipo di semplice correzione che speravo fosse necessaria: P –

+0

Questa era davvero la soluzione al problema con il Toast. Ora, se solo riesco a capire perché l'attività non si avvia ... –

1

Steve,

Avete trovato il problema? Io uso widget e funziona bene per me senza trucco abilitato. Sono interessato perché non fa per te.

mia ipotesi: nel codice originale riprova

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

invece di

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

Ciao, questa domanda non è stata attiva da secoli! Tuttavia, il cambiamento che hai suggerito non fa la differenza. Sono stato in grado di risolvere il problema riavviando il progetto da capo. Per quanto posso dire i due progetti sono identici, ma questo non funziona. Non capisco perché questo non funzioni, ma non è un problema poiché l'altro lo fa. –

+0

Questo codice è perfetto –

0

è necessario definire la vostra attività di configurazione in res/xml/volume_changer_info.xml. Aggiungi questo tag e fornisci un percorso completo per l'attività di configurazione.

android: configure = ""


esempio

<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

Ciao, penso che stiamo parlando di cose diverse quando abbiamo fatto riferimento a una "attività di configurazione". Intendevo qualcosa che poteva essere lanciato in qualsiasi momento dopo aver aggiunto il widget piuttosto che qualcosa che sarebbe stato lanciato non appena aggiunto il widget. Questo problema è stato risolto qualche tempo fa, ma grazie per aver cercato di aiutare! –

7

Questo ha funzionato per me, sulla base di informazioni qui, il widget del campione di parola, e 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

Portando questo modo indietro dalla morte, ma ho avuto un problema simile e penso Ho finalmente risolto ... come te, ho avuto un PendingIntent che ho allegato a RemoteView. A volte funzionava, e qualche volta falliva. Mi stava facendo impazzire.

Quello che ho trovato da un tooltip sul PendingIntent.getActivty() è stato:

Nota che l'attività verrà avviata al di fuori del contesto di un'attività già esistente, quindi è necessario utilizzare il lancio Intent.FLAG_ACTIVITY_NEW_TASK bandiera nell'intento.

così, ho aggiunto:

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 

No codice di esempio che ho visto fino ad ora fa questo, ma risolto il mio problema; l'attività Impostazioni è ora avviata in modo affidabile.

Il codice completo che sta lavorando bene ...

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

Grazie amico! funziona perfettamente con – Jakob

+0

per me, era la linea 'setData (...)' che ha funzionato. prima di quello, non ho potuto ricevere alcun extra. lo so, difficile da credere. –

0

Volevo solo notare che questo qui da qualche parte come mi è stato (abbastanza stupidamente) combattere questo per tutta la notte. Fondamentalmente ho fatto tutto il codice intent correttamente ma non sarebbe stato lanciato nulla.

Il problema era che per sbaglio ho ricevuto una telefonata del genere

super.onUpdate(context, appWidgetManager, appWidgetIds); 

alla fine della mia funzione override onUpdate().

Assicurati di avere DO avere questa chiamata a super in quanto eliminerà tutti gli intenti in sospeso che hai impostato!

+1

Questo è strano almeno [nelle ultime versioni di Android AppWidgetProvider.onUpdate() non fa nulla] (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

Sì, mi ha anche sconcertato, ma rimuovere quella linea era quello che faceva per me :) –

0

So che questo thread è antico, ma ... Altre risposte descrivono il tuo problema di toast bruciato. Per quanto riguarda il motivo per cui l'attività popup non viene avviata al tocco, potrebbe essere necessario attivare l'azione di "aggiornamento" per avviare e chiamare il metodo onUpdate(). Per questo penso che è necessario aggiungere l'azione "APPWIDGET_UPDATE" come questo:

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

Allo stesso modo aggiungere le azioni APPWIDGET_ENABLED e APPWIDGET_DISABLED se avete intenzione di ignorare quei metodi troppo.

Sembra un'API molto inusuale che richiede di dichiarare i metodi sottoposti a override che si desidera chiamare. Il modo usuale per ottenere la versione personalizzata di un genitore è semplicemente di sovrascriverli/implementarli. Forse c'è una buona ragione per questo strano pattern, ma non è un pattern Java che ho visto prima. Pertanto penso che rischiano di far scattare una grande quantità di autori di widget di app. Come se i widget delle app non fossero abbastanza confusi senza questo meccanismo.

0

Un ulteriore punto: l'attività chiamata dal widget deve essere dichiarata nel file manifest. Non viene generata un'eccezione, sembra proprio non succede nulla ...

Problemi correlati