我的窗口小部件有问题。实际上,它工作得很好,我可以从自定义活动向我的AppWidgetProvider(也是我的BroadcastReceiver)发送和接收广播。
问题在这里:过一会儿(大约1分钟),该小部件不再收到来自自定义活动的广播。
这是onEnabled,onReceiver和onUpdate(您可以在onReceive方法中看到启动已发出活动的代码):
class TodoWidgetProvider() : AppWidgetProvider() {
override fun onEnabled(context: Context?) {
super.onEnabled(context)
Log.i("Debug", "onEnabled has been called")
try {
val filter = IntentFilter(StaticVariables.ACTION_NEWTASK)
context?.applicationContext?.registerReceiver(this, filter)
// Récupère les informations à partir du manager
val manager = AppWidgetManager.getInstance(context)
val ids = manager.getAppWidgetIds(ComponentName(context?.applicationContext?.packageName, javaClass.name))
// Lance la mise à jour
onUpdate(context, manager, ids)
} catch (e: Exception) {
Log.e("Debug", "Erreur pendant onEnabled +" + e.toString())
}
}
override fun onUpdate(context: Context?, appWidgetManager: AppWidgetManager?, appWidgetIds: IntArray?) {
super.onUpdate(context, appWidgetManager, appWidgetIds)
Log.i("Debug", "Updating TodoWidget")
try {
appWidgetIds?.forEach { id ->
// Met en place l'intent qui lance le service. Le service
// Se chargera de fournir les données pour remplir la liste
val intent = Intent(context, TodoWidgetService::class.java)
// Fournit l'id du widget
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, id)
intent.data = Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME))
// Récupère le layout
val layout = RemoteViews(context?.packageName, R.layout.todowidget)
// Applique l'adapter (via l'intent) sur la listview
layout.setRemoteAdapter(R.id.Main_LV_Todotasks, intent)
// Template permettant de gérer les listener sur les ITEMS
// L'intent est créer vers TodoWidgetProvider puisque le Provider est AUSSI un Broadcast receiver
val intentTemplate = Intent(context, TodoWidgetProvider::class.java)
intentTemplate.action = StaticVariables.ACTION_DELETETASK
layout.setPendingIntentTemplate(R.id.Main_LV_Todotasks,
PendingIntent.getBroadcast(context, 0, intentTemplate, PendingIntent.FLAG_UPDATE_CURRENT));
// Ajoute un clickListener sur le bouton le bouton
val intentAddNew = Intent(context, javaClass)
intentAddNew.action = ACTION_STARTACTIVITY_NEWTASK
layout.setOnClickPendingIntent(R.id.Main_IBT_Add,
PendingIntent.getBroadcast(context?.applicationContext, 0, intentAddNew, 0));
// Applique le layout
appWidgetManager?.updateAppWidget(id, layout)
}
} catch (e: Exception) {
e.printStackTrace();
Log.e("Debug", "Error updating widget" + e.toString())
}
}
/**
* Méthode représentant l'implémentation de la classe BroadcastReceiver
*
* Permet de récupérer les intents correspondants aux actions de l'utilisateur
* pour effectuer les traitements en conséquences
*/
override fun onReceive(context: Context?, intent: Intent?) {
super.onReceive(context, intent)
Log.i("Debug", "Provider received an intent")
// Si le bouton d'ajout a été clické
if (ACTION_STARTACTIVITY_NEWTASK.equals(intent?.action)) {
// Démarrage de l'activité nouvelle task (qui simule une popup)
val i = Intent(context, NewTaskActivity::class.java)
i.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
context?.startActivity(i)
}
// Si l'utilisateur à entré une nouvelle tâche
if (ACTION_NEWTASK.equals(intent?.action)) {
// Récupère les données
var todoTitle = intent?.extras?.get(StaticVariables.EXTRA_NEWTODO_TITLE) as String?
var todoContent = intent?.extras?.get(StaticVariables.EXTRA_NEWTODO_CONTENT) as String?
var todoAlert = intent?.extras?.get(StaticVariables.EXTRA_NEWTODO_ALERT) as Long?
// Lance l'ajout
addNewTask(context!!, todoTitle, todoContent, todoAlert)
}
// Si l'utilisateur à supprimé une tâche
if (ACTION_DELETETASK.equals(intent?.action)) {
// Récupère les données
var deletePosition = intent?.extras?.get(StaticVariables.EXTRA_DELETETODO_POSITION) as Int?
if (deletePosition != null) {
// Lance la suppression
deleteTask(context!!, deletePosition)
}
}
// Si le téléphone a été redémaré
if ("android.intent.action.BOOT_COMPLETED".equals(intent?.getAction())) {
// Récupére une liste des tâches enregistrées
var currentTodoList: ArrayList<TodoTask> = ArrayList(Helper_SharedPreferences.GetTodoList(context!!, StaticVariables.SHARED_TODOLIST))
var currentAlarmList = ArrayList<Date>()
// Si il y avait des alarmes enregistrées
if (currentTodoList?.size > 0) {
// Parcours des alarmes
currentTodoList.forEach { task ->
if (task._alert != null) {
// Réajoute l'alarme
Helper_Alarm.createAlarm(context!!, task)
currentAlarmList.add(task._alert!!)
}
}
}
// Réenregistre la liste des alarmes
Helper_SharedPreferences.SaveAlarmList(context, currentAlarmList, StaticVariables.SHARED_ALARMLIST)
}
// Si on reçoit un intent pour envoyer une notification
if (ACTION_ALERT_TASK.equals(intent?.action)) {
Log.i("Debug", "ALARM RECEIVED" + intent?.action)
// Récupération de la Task sérializée
val taskString = intent?.extras?.getString(StaticVariables.EXTRA_ALERT_TASK)
// Désérialization
val notificationManager = NotificationManagerCompat.from(context!!)
val gson = Gson()
val task: TodoTask = gson.fromJson(taskString, TodoTask::class.java)
// Création du channel (API > 26)
createNotificationChannel(context)
// Création de la notification
val mBuilder = NotificationCompat.Builder(context, StaticVariables.NOTIFICATION_CHANNELID)
.setSmallIcon(R.drawable.ic_alert)
.setContentTitle(task?._title)
.setContentText(task?._content)
.setStyle(NotificationCompat.BigTextStyle()
.bigText(task?._content))
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
notificationManager.notify(5258, mBuilder.build());
}
}
这里是已发布的活动(在ok_ClickListener中发送广播的代码:
class NewTaskActivity() : AppCompatActivity() {
// region Fields
// Déclaration des vues
internal lateinit var et_content: EditText
internal lateinit var et_title: EditText
internal lateinit var ll_parent: LinearLayout
internal lateinit var bt_ok: Button
internal lateinit var ibt_alert: ImageButton
internal lateinit var ll_alert: LinearLayout
internal lateinit var tv_alert: TextView
// Déclaration des valeurs demandées à l'utilisateur
internal var alert_date: Date? = null
internal var alert_year: Int = 0
internal var alert_month: Int = 0
internal var alert_day: Int = 0
// endregion
// region constructor
@SuppressLint("ClickableViewAccessibility")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Window.FEATURE_NO_TITLE
setContentView(R.layout.activity_new_task)
// Récupère l'editTexte du contenu
et_content = findViewById(R.id.NewTaskAct_ET_content)
et_title = findViewById(R.id.NewTaskAct_ET_title)
ll_parent = findViewById(R.id.NewTaskAct_LL_parent)
bt_ok = findViewById(R.id.NewTaskAct_BT_Ok)
ibt_alert = findViewById(R.id.NewTaskAct_IBT_alert)
ll_alert = findViewById(R.id.NewTaskAct_LL_alert)
tv_alert = findViewById(R.id.NewTaskAct_TV_alert)
// Ajoute l'évènement au click de ok
bt_ok.setOnClickListener(ok_ClickListener)
// Ajout l'évènement de création de l'alert (ouverture de la popup)
ibt_alert.setOnClickListener(alert_ClickListener)
ll_alert.setOnClickListener(alert_ClickListener)
// Demande le focus pour afficher le clavier
et_title?.requestFocus()
// Ajoute les listeners de saisie
et_title?.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(p0: Editable?) {
}
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
}
override fun onTextChanged(string: CharSequence?, p1: Int, p2: Int, p3: Int) {
if (string?.length!! >= 2) {
bt_ok.isEnabled = true
} else if (et_content?.length() < 2) {
bt_ok.isEnabled = false
}
}
})
et_content?.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(p0: Editable?) {
}
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
}
override fun onTextChanged(string: CharSequence?, p1: Int, p2: Int, p3: Int) {
if (string?.length!! >= 2) {
bt_ok.isEnabled = true
} else if (et_title?.length() < 2) {
bt_ok.isEnabled = false
}
}
})
}
// endregion
// region Listeners
/**
* TouchListener permettant l'ajout de la tâche
*/
val ok_ClickListener: View.OnClickListener = View.OnClickListener { it ->
try {
// Création de l'intent personnalisé pour renvoyer le résultat
val i = Intent(StaticVariables.ACTION_NEWTASK)
// Ajoute les données de la nouvelle tâche en extra
i.putExtra(StaticVariables.EXTRA_NEWTODO_TITLE, et_title?.text?.toString()!!)
i.putExtra(StaticVariables.EXTRA_NEWTODO_CONTENT, et_content?.text?.toString()!!)
i.putExtra(StaticVariables.EXTRA_NEWTODO_ALERT, alert_date?.time)
// Envoie l'intent pour que tous les receivers potentiels les reçoivent
sendBroadcast(i)
Log.i("Debug","Broadcast aparently sent.")
// Ferme l'activité
finish()
} catch (e: Exception) {
Log.e("Debug", "Error during click ok button action.")
}
}
/**
* Cette méthode permet d'ouvrir les popups de sélection de date et heure
*/
val alert_ClickListener: View.OnClickListener = View.OnClickListener { it ->
// Lance la sélection de la date
showDatePicker()
}
/**
* TouchListener permettant de fermer l'activité de nouvelle tâche
*/
val cancel_ClickListener: View.OnClickListener = View.OnClickListener { it ->
// Termine l'activité
finish()
}
// endregion
// region Helpers
/**
* Permet de lancer la popup de sélection de la date (année mois jour)
*/
private fun showDatePicker() {
// Récupère la date du jour
val c = Calendar.getInstance()
val year = c.get(Calendar.YEAR)
val month = c.get(Calendar.MONTH)
val day = c.get(Calendar.DAY_OF_MONTH)
// Déclare la boite de dialog de sélection à partir de la date du jour
val dialog = DatePickerDialog(this,
// Action a éffectuer une fois la date sélectionnée
DatePickerDialog.OnDateSetListener { view, yearSelected, monthOfYear, dayOfMonth ->
// Affecte les
alert_year = yearSelected
alert_month = monthOfYear
alert_day = dayOfMonth
// Lance le picker de time
showTimeicker()
}, year, month, day)
// Ouvre la dialog
dialog.show()
}
/**
* Permet de lancer la popup de sélection de la date (année mois jour)
*/
private fun showTimeicker() {
// Récupère la date du jour
val c = Calendar.getInstance()
val hour = c.get(Calendar.HOUR)
val minute = c.get(Calendar.MINUTE)
// Déclare la boite de dialog de sélection à partir de la date du jour
val dialog = TimePickerDialog(this,
// Action a éffectuer une fois la date sélectionnée
TimePickerDialog.OnTimeSetListener { timePicker, hourSet, minuteSet ->
// Créer une nouvelle date
alert_date = Helper_Date.createDate(alert_year, alert_month, alert_day, hourSet, minuteSet)
if (alert_date != null) {
// Récupère une chaîne pour l'affichage
val stringDate = Helper_Date.getStringDateCurrentCulture(this, alert_date!!)
tv_alert.setText(stringDate)
}
}, hour, minute, true)
// Ouvre la dialog
dialog.show()
}
// endregion
// region overrides
// endregion
}
我尝试了一切...更改包含applicationContext的上下文。我真的不知道该如何解决,我需要您的帮助:D。
根据广播是在小部件的生命周期开始时接收到的,也许问题出在此...
谢谢您的帮助,
Etienne;)
答案 0 :(得分:0)
我终于通过更改这些行来使其工作:
[ {
"id" : "IboECKV "
}, {
"col2" : "2018-09-14 21:05:02.000Z"
}, {
"col3" : 10
}, {
"col4" : 0
}]
通过这些行:
// Création de l'intent personnalisé pour renvoyer le résultat
val i = Intent(StaticVariables.ACTION_NEWTASK)
我真的不明白问题出在哪里...但是如果它可以帮助某人。