studio programacion herramientas fundamentos con avanzado aplicaciones android android-widget

programacion - manual de android en pdf



Iniciando actividad desde widget (10)

Intento hacer algo que realmente debería ser bastante fácil, pero me está volviendo loco. Intento iniciar una actividad cuando se presiona un widget de pantalla de inicio, como una actividad de configuración para el widget. Creo que he seguido palabra por palabra el tutorial en el sitio web de Desarrolladores de Android, e incluso algunos tutoriales no oficiales, pero me falta algo importante, ya que no funciona.

Aquí está el código:

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

}

Al agregar el widget a la pantalla de inicio, Logcat muestra las dos líneas de depuración, aunque no el Toast. (¿Alguna idea de por qué no?) Sin embargo, es más molesto que cuando hago clic en el botón con el PendingIntent asociado, nada sucede. Sé que la actividad "WidgetTest" se puede ejecutar porque si configuro un Intent desde dentro de la actividad principal, se inicia correctamente.

En caso de que importe, aquí está el archivo de Manifiesto de 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" />

¿Hay alguna manera de probar dónde está la falla? Es decir, ¿es culpa de que el botón no esté vinculado correctamente al PendingIntent, o que el PendingIntent o Intent no encuentre WidgetTest.class, etc.?

¡Muchas gracias por su ayuda!

Steve


Al agregar el widget a la pantalla de inicio, Logcat muestra las dos líneas de depuración, aunque no el Toast. (¿Alguna idea de por qué no?)

No intente iniciar Toasts desde un BroadcastReceiver .

¿Hay alguna manera de probar dónde está la falla?

Mire LogCat, a través de adb logcat , DDMS, o la perspectiva DDMS en Eclipse. Puede encontrar advertencias sobre no encontrar una actividad que coincida con el Intent dado.

No veo ningún problema obvio. Es posible que desee echar un vistazo a uno de mis ejemplos de libros y ver si eso funciona para usted, y si le da alguna idea de lo que puede estar en marcha.


El problema con el Toast que no se muestra es fácil, no llamas a show (), un error que siempre hago también ... do

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

en lugar de

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


Esto funcionó para mí, basado en la información aquí, la muestra del widget de palabras y el tutorial aquí

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


Sé que este hilo es antiguo, pero ... Otras respuestas describen su problema de Toast quemado. En cuanto a por qué su actividad emergente no se inicia al tocar, es posible que necesite habilitar la acción de "actualización" para iniciar y llamar a su método onUpdate (). Para eso, creo que debes agregar la acción "APPWIDGET_UPDATE" de esta manera:

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

Asimismo, agregue las acciones APPWIDGET_ENABLED y APPWIDGET_DISABLED si tiene la intención de anular esos métodos también.

Parece ser una API muy inusual que requiere que declares los métodos reemplazados que deseas llamar. La forma habitual de obtener su versión personalizada de un padre es simplemente anular / implementarlos. Tal vez haya una buena razón para este patrón extraño, pero no es un patrón de Java que haya visto antes. Por lo tanto, creo que es probable que se pierda una gran cantidad de autores de widgets de aplicaciones. Como si los widgets de aplicaciones no fueran lo suficientemente confusos sin este mecanismo.


Solo quería notar esto aquí en alguna parte, ya que he estado (bastante estúpidamente) batallando con esto toda la noche. Básicamente, hice todo el código de intención correctamente, pero no se lanzaría nada.

El problema fue que accidentalmente tuve una llamada como esta

super.onUpdate(context, appWidgetManager, appWidgetIds);

al final de mi función OverUpden onUpdate ().

¡Asegúrate de NO TENER esta llamada a super, ya que borrará todos los intentos pendientes que hayas configurado!


Steve,

¿Has encontrado el problema? Uso widget y funciona bien para mí sin el truco onEnabled. Me interesa por qué no es para ti.

Mi suposición: en tu código original por favor prueba

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

en lugar de

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


Traer de regreso de la muerte, pero tuve un problema similar y creo que finalmente lo resolví ... como tú, tenía un PendingIntent que adjunté a RemoteView. Algunas veces funcionaría, y algunas veces fallaría. Me estaba volviendo loco.

Lo que encontré en una información sobre herramientas en PendingIntent.getActivty () fue:

Tenga en cuenta que la actividad se iniciará fuera del contexto de una actividad existente, por lo que debe usar el indicador de inicio Intent.FLAG_ACTIVITY_NEW_TASK en el Intent.

entonces, agregué:

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

Ningún código de ejemplo que he visto hasta ahora hace esto, pero resolvió mi problema; la actividad de Configuración ahora se inicia de forma confiable.

El código completo funciona 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);


Un punto adicional: la Actividad que se llama desde el Widget debe declararse en el archivo Manifest. No se lanza ninguna excepción, simplemente parece que no pasa nada ...


Yo estaba teniendo el mismo problema. Descubrí que la solución es llamar a una actualización a través del administrador de appwidget. aquí hay un ejemplo de cómo hacer eso en onEnabled. Parece que se debe hacer tanto en onNable como onUpdated para que cuando el dispositivo se encienda tu intento de cliquear también se inicialice. En onUpdated, los params ya proporcionan la referencia al administrador, afortunadamente.

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


debe definir su actividad de configuración en res / xml / volume_changer_info.xml. Agregue esta etiqueta y proporcione una ruta completa a la actividad de configuración.

android: configure = ""

p.ej

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