gpt4 book ai didi

android - 我需要有关 Widget 和 PendingIntents 的帮助

转载 作者:行者123 更新时间:2023-11-29 02:17:11 25 4
gpt4 key购买 nike

我在这里问了一个关于 Task Killers 和小部件停止工作的问题 (SO Question) 但现在,我收到用户的报告说他们没有使用任何 Task Killer 并且小部件在一段时间后不起作用。我有 Nexus One,但没有遇到这个问题。

不知道是内存的问题还是什么的。基于 API:

A PendingIntent itself is simply a reference to a token maintained by the system describing the original data used to retrieve it. This means that, even if its owning application's process is killed, the PendingIntent itself will remain usable from other processes that have been given it.

所以,我不知道为什么小部件停止工作,如果 Android 不自行终止 PendingIntent,问题是什么?

这是我的 list 代码:

    <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% 的功能是小部件,它对某些用户不起作用:(

提前致谢,抱歉我的英语不好。

最佳答案

我认为您需要准确确定用户所说的“停止工作”是什么意思。它是强制关闭(崩溃)还是只是变得无响应?尽可能收集有关他们手机的任何信息,例如他们有什么手机,他们运行的是什么版本的 Android(如果他们不知道,请查找)等等。另外,请确保您明确询问他们是否使用自定义固件,如 CyanogenMod。

让您的应用将一些日志记录信息写入 SD 卡,这样您就可以要求用户在再次发生日志时通过电子邮件向您发送日志,并希望能够阐明应用开始出现异常之前的最后一个任务是什么。


更新

看起来您实际上是在应用小部件中播放音乐,这将迫使您遵守屏幕上小部件的生命周期。特别是一旦主屏幕不再处于焦点状态,小部件就不再是优先进程,fail-fast behaviour of a BroadcastReceiver :

Note: Because the AppWidgetProvider is a BroadcastReceiver, your process is not guaranteed to keep running after the callback methods return (see Application Fundamentals > Broadcast Receiver Lifecycle for more information). If your App Widget setup process can take several seconds (perhaps while performing web requests) and you require that your process continues, consider starting a Service in the onUpdated() method.

我的建议是将音乐播放代码从 ​​appwidget 移到 Service 中。 ,只需要在播放开始的时候启动服务,播放结束的时候就把它拆掉。这将为您提供播放音乐的后台进程,而不受您的应用程序小部件生命周期的影响。这种模式的一个例子是 Last.FM 应用程序小部件(随应用程序一起提供)。

关于android - 我需要有关 Widget 和 PendingIntents 的帮助,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2711516/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com