ここでタスク キラーとウィジェットが機能しなくなる( SO の質問) について質問しましたが、現在、タスク キラーを使用しておらず、しばらくするとウィジェットが機能しなかったというユーザーの報告があります。Nexus One を持っていますが、この問題はありません。
これがメモリの問題なのか、それとも何かの問題なのかはわかりません。API に基づく:
PendingIntent 自体は、それを取得するために使用される元のデータを記述する、システムによって維持されるトークンへの単なる参照です。これは、所有しているアプリケーションのプロセスが強制終了された場合でも、PendingIntent 自体は、それを与えられた他のプロセスから引き続き使用できることを意味します。
Android が PendingIntent 自体を強制終了しない場合、ウィジェットが機能しなくなる理由がわかりません。何が問題なのですか?
これは私のマニフェストコードです:
<receiver android:name=".widget.InstantWidget" android:label="@string/app_name">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="@xml/widget_provider" />
</receiver>
そしてウィジェットコード:
public class InstantWidget extends AppWidgetProvider {
public static ArrayList<Integer> alWidgetsId = new ArrayList<Integer>();
private static final String PREFS_NAME = "com.cremagames.instant.InstantWidget";
private static final String PREF_PREFIX_NOM = "nom_";
private static final String PREF_PREFIX_RAW = "raw_";
/**
* Esto se llama cuando se crea el widget. Metemos en las preferencias los valores de nombre y raw para tenerlos en proximos reboot.
* @param context
* @param appWidgetManager
* @param appWidgetId
* @param nombreSound
* @param rawSound
*/
static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
int appWidgetId, String nombreSound, int rawSound){
//Guardamos en las prefs los valores
SharedPreferences.Editor prefs = context.getSharedPreferences(PREFS_NAME, 0).edit();
prefs.putString(PREF_PREFIX_NOM + appWidgetId, nombreSound);
prefs.putInt(PREF_PREFIX_RAW + appWidgetId, rawSound);
prefs.commit();
//Actualizamos la interfaz
updateWidgetGrafico(context, appWidgetManager, appWidgetId, nombreSound, rawSound);
}
/**
* Actualiza la interfaz gráfica del widget (pone el nombre y crea el intent con el raw)
* @param context
* @param appWidgetManager
* @param appWidgetId
* @param nombreSound
* @param rawSound
*/
private static void updateWidgetGrafico(Context context, AppWidgetManager appWidgetManager,
int appWidgetId, String nombreSound, int rawSound){
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget);
//Nombre del Button
remoteViews.setTextViewText(R.id.tvWidget, nombreSound);
//Creamos el PendingIntent para el onclik del boton
Intent active = new Intent(context, InstantWidget.class);
active.setAction(String.valueOf(appWidgetId));
active.putExtra("sonido", rawSound);
PendingIntent actionPendingIntent = PendingIntent.getBroadcast(context, 0, active, 0);
actionPendingIntent.cancel();
actionPendingIntent = PendingIntent.getBroadcast(context, 0, active, 0);
remoteViews.setOnClickPendingIntent(R.id.btWidget, actionPendingIntent);
appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
}
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
//Esto se usa en la 1.5 para que se borre bien el widget
if (AppWidgetManager.ACTION_APPWIDGET_DELETED.equals(action)) {
final int appWidgetId = intent.getExtras().getInt(
AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID);
if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
this.onDeleted(context, new int[] { appWidgetId });
}
} else {
//Listener de los botones
for(int i=0; i<alWidgetsId.size(); i++){
if (intent.getAction().equals(String.valueOf(alWidgetsId.get(i)))) {
int sonidoRaw = 0;
try {
sonidoRaw = intent.getIntExtra("sonido", 0);
} catch (NullPointerException e) {
}
MediaPlayer mp = MediaPlayer.create(context, sonidoRaw);
mp.start();
mp.setOnCompletionListener(completionListener);
}
}
super.onReceive(context, intent);
}
}
/** Al borrar el widget, borramos también las preferencias **/
public void onDeleted(Context context, int[] appWidgetIds) {
for(int i=0; i<appWidgetIds.length; i++){
//Recogemos las preferencias
SharedPreferences.Editor prefs = context.getSharedPreferences(PREFS_NAME, 0).edit();
prefs.remove(PREF_PREFIX_NOM + appWidgetIds[i]);
prefs.remove(PREF_PREFIX_RAW + appWidgetIds[i]);
prefs.commit();
}
super.onDeleted(context, appWidgetIds);
}
/**Este método se llama cada vez que se refresca un widget. En nuestro caso, al crearse y al reboot del telefono.
Al crearse lo único que hace es guardar el id en el arrayList
Al reboot, vienen varios ID así que los recorremos y guardamos todos y también recuperamos de las preferencias el nombre y el sonido*/
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
for(int i=0; i<appWidgetIds.length; i++){
//Metemos en el array los IDs de los widgets
alWidgetsId.add(appWidgetIds[i]);
//Recogemos las preferencias
SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, 0);
String nomSound = prefs.getString(PREF_PREFIX_NOM + appWidgetIds[i], null);
int rawSound = prefs.getInt(PREF_PREFIX_RAW + appWidgetIds[i], 0);
//Si están creadas, actualizamos la interfaz
if(nomSound != null){
updateWidgetGrafico(context, appWidgetManager, appWidgetIds[i], nomSound, rawSound);
}
}
}
MediaPlayer.OnCompletionListener completionListener = new MediaPlayer.OnCompletionListener(){
public void onCompletion(MediaPlayer mp) {
if(mp != null){
mp.stop();
mp.release();
mp = null;
}
}
};
}
スペイン語でのコメントで申し訳ありません。
デスクトップにさまざまなウィジェットを配置する可能性があるため、widgetId を PendingIntent の「一意の ID」として使用します。
アイデアはありますか?私のアプリの機能の 70% はウィジェットですが、一部のユーザーには機能しません :(
よろしくお願いします。私の英語で申し訳ありません。