我在這裏問了一個關於任務殺手和窗口小部件停止工作的問題(SO Question),但現在我有報告說用戶他們沒有使用任何殺手,窗口小部件沒有工作一段時間後。我有一個Nexus One,我沒有這個問題。我需要關於窗口小部件和PendingIntents的幫助
我不知道這是內存問題還是其他問題。基於API:
甲的PendingIntent本身是一個簡單的 參照由描述原始數據 用於檢索它的 系統所維護的令牌。這意味着,即使其擁有的應用程序的 進程被終止, PendingIntent 本身仍然可以從其他 進程獲得它。
所以,我不知道爲什麼widget停止工作,如果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%是小部件,它是不工作的一些用戶:(提前對不起我的英語
感謝。
感謝您的評論。該小部件只是停止重現聲音,不顯示任何錯誤或fc。 各種設備是巨大的和Android版本(從1.5到2.1)。 我猜是Android操作系統本身... – YaW 2010-04-26 10:21:16
也許,雖然其他應用程序已經能夠可靠地在Android上產生聲音 - 例如,股票音樂播放器和Last.fm.我已經通過一些進一步的建議修改了我的解 – seanhodges 2010-04-27 08:25:59