使用 AlarmManager 更新应用程序小部件

发布于 2024-10-27 16:57:12 字数 4595 浏览 4 评论 0原文

我正在尝试比 1.6docs 规定的 30 分钟限制更频繁地更新 Widget。在阅读了 SO 中的几乎每一篇文章、开发人员文档以及各种其他来源之后,我认为我已经达到了可以实现它的程度。于是,我尝试了,但失败了。从那时起,我又搜索了更多论坛和解决方案,但似乎无法更新。

我有一个设置 AlarmManager 的 Update 类:

public class Update extends Service{

    @Override
    public void onStart(Intent intent, int startId) {
          String currentTemp = Battery.outputTemp;
          String currentLevel = Battery.outputLevel;
          String currentCard = Battery.outputCard;
          String currentInternal = Battery.memory;
          String currentRam = String.valueOf(Battery.outputRam).substring(0, 3) + "MB";

          // Change the text in the widget
          RemoteViews updateViews = new RemoteViews( 
          this.getPackageName(), R.layout.main);
          //update temp
          updateViews.setTextViewText(R.id.batteryTemp, currentTemp); 
          //update %
          updateViews.setTextViewText(R.id.batteryLevel, currentLevel);     
          //update level
          updateViews.setTextViewText(R.id.sdCard, currentCard);
          //update internal memory
          updateViews.setTextViewText(R.id.internal, currentInternal);
          //update ram
          updateViews.setTextViewText(R.id.ram, currentRam);

          ComponentName thisWidget = new ComponentName(this, Widget.class);
          AppWidgetManager manager = AppWidgetManager.getInstance(this);
          manager.updateAppWidget(thisWidget, updateViews);

    }
    @Override
    public IBinder onBind(Intent intent) {
        // no need to bind
        return null;
    }

}

这导致我的小部件类中的 onReceive 频繁触发(我有一个 toast 来查看它何时触发),但它没有任何意图(toast 旨在按原样显示此内容)已收到,但内容为空)。

我无法弄清楚(我是一个相对新手 - 两个月的缓慢 Android 开发),并感谢你们所拥有的任何见解。

这是我的小部件类供参考:

    public class Widget extends AppWidgetProvider {


    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager,
            int[] appWidgetIds) {

        AlarmManager alarmManager;
        Intent intent = new Intent(context, Update.class);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0,
                intent, PendingIntent.FLAG_UPDATE_CURRENT);
        alarmManager = (AlarmManager) context
                .getSystemService(Context.ALARM_SERVICE);
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(System.currentTimeMillis());
        cal.add(Calendar.SECOND, 10);
        alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, cal
                .getTimeInMillis(), 5 * 1000, pendingIntent);

        String currentTemp = Battery.outputTemp;
        String currentLevel = Battery.outputLevel;
        String currentCard = Battery.outputCard;
        String currentInternal = Battery.memory;
        String currentRam = String.valueOf(Battery.outputRam).substring(0, 3)
                + "MB";

        // Change the text in the widget
        RemoteViews updateViews = new RemoteViews(context.getPackageName(),
                R.layout.main);
        // update temp
        updateViews.setTextViewText(R.id.batteryTemp, currentTemp);
        appWidgetManager.updateAppWidget(appWidgetIds, updateViews);
        // update %
        updateViews.setTextViewText(R.id.batteryLevel, currentLevel);
        appWidgetManager.updateAppWidget(appWidgetIds, updateViews);
        // update level
        updateViews.setTextViewText(R.id.sdCard, currentCard);
        appWidgetManager.updateAppWidget(appWidgetIds, updateViews);
        // update internal memory
        updateViews.setTextViewText(R.id.internal, currentInternal);
        appWidgetManager.updateAppWidget(appWidgetIds, updateViews);
        // update ram
        updateViews.setTextViewText(R.id.ram, currentRam);
        appWidgetManager.updateAppWidget(appWidgetIds, updateViews);
        super.onUpdate(context, appWidgetManager, appWidgetIds);

    }

    public void onReceive(Context context, Intent intent) {

        super.onReceive(context, intent);
        Toast
                .makeText(context, intent.getAction() + context,
                        Toast.LENGTH_LONG).show();
        Bundle extras = intent.getExtras();
        if (extras != null) {
            AppWidgetManager appWidgetManager = AppWidgetManager
                    .getInstance(context);
            ComponentName thisAppWidget = new ComponentName(context
                    .getPackageName(), Widget.class.getName());
            int[] appWidgetIds = appWidgetManager
                    .getAppWidgetIds(thisAppWidget);

            onUpdate(context, appWidgetManager, appWidgetIds);
        }

    }
}

I am trying to update a Widget more frequently than the 30 minute restriction imposed by the 1.6docs. After reading nearly every post in SO, and the developer docs, and various other sources, I thought I had got to a point where i could implement it. And so, I tried, and failed. Since then, I have trawled yet more forums and solutions, and I cannot seem to get it to update.

I have an Update class that sets the AlarmManager:

public class Update extends Service{

    @Override
    public void onStart(Intent intent, int startId) {
          String currentTemp = Battery.outputTemp;
          String currentLevel = Battery.outputLevel;
          String currentCard = Battery.outputCard;
          String currentInternal = Battery.memory;
          String currentRam = String.valueOf(Battery.outputRam).substring(0, 3) + "MB";

          // Change the text in the widget
          RemoteViews updateViews = new RemoteViews( 
          this.getPackageName(), R.layout.main);
          //update temp
          updateViews.setTextViewText(R.id.batteryTemp, currentTemp); 
          //update %
          updateViews.setTextViewText(R.id.batteryLevel, currentLevel);     
          //update level
          updateViews.setTextViewText(R.id.sdCard, currentCard);
          //update internal memory
          updateViews.setTextViewText(R.id.internal, currentInternal);
          //update ram
          updateViews.setTextViewText(R.id.ram, currentRam);

          ComponentName thisWidget = new ComponentName(this, Widget.class);
          AppWidgetManager manager = AppWidgetManager.getInstance(this);
          manager.updateAppWidget(thisWidget, updateViews);

    }
    @Override
    public IBinder onBind(Intent intent) {
        // no need to bind
        return null;
    }

}

This has caused my onReceive in my widget class to fire frequently (i have a toast to see when it fires), yet it carries no intent (the toast is meant to display this as they are received but it is blank).

I cannot figure it out (i'm a relative newb-2 months of slow android dev), and appreciate any insight you guys have.

heres my widget class for reference:

    public class Widget extends AppWidgetProvider {


    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager,
            int[] appWidgetIds) {

        AlarmManager alarmManager;
        Intent intent = new Intent(context, Update.class);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0,
                intent, PendingIntent.FLAG_UPDATE_CURRENT);
        alarmManager = (AlarmManager) context
                .getSystemService(Context.ALARM_SERVICE);
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(System.currentTimeMillis());
        cal.add(Calendar.SECOND, 10);
        alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, cal
                .getTimeInMillis(), 5 * 1000, pendingIntent);

        String currentTemp = Battery.outputTemp;
        String currentLevel = Battery.outputLevel;
        String currentCard = Battery.outputCard;
        String currentInternal = Battery.memory;
        String currentRam = String.valueOf(Battery.outputRam).substring(0, 3)
                + "MB";

        // Change the text in the widget
        RemoteViews updateViews = new RemoteViews(context.getPackageName(),
                R.layout.main);
        // update temp
        updateViews.setTextViewText(R.id.batteryTemp, currentTemp);
        appWidgetManager.updateAppWidget(appWidgetIds, updateViews);
        // update %
        updateViews.setTextViewText(R.id.batteryLevel, currentLevel);
        appWidgetManager.updateAppWidget(appWidgetIds, updateViews);
        // update level
        updateViews.setTextViewText(R.id.sdCard, currentCard);
        appWidgetManager.updateAppWidget(appWidgetIds, updateViews);
        // update internal memory
        updateViews.setTextViewText(R.id.internal, currentInternal);
        appWidgetManager.updateAppWidget(appWidgetIds, updateViews);
        // update ram
        updateViews.setTextViewText(R.id.ram, currentRam);
        appWidgetManager.updateAppWidget(appWidgetIds, updateViews);
        super.onUpdate(context, appWidgetManager, appWidgetIds);

    }

    public void onReceive(Context context, Intent intent) {

        super.onReceive(context, intent);
        Toast
                .makeText(context, intent.getAction() + context,
                        Toast.LENGTH_LONG).show();
        Bundle extras = intent.getExtras();
        if (extras != null) {
            AppWidgetManager appWidgetManager = AppWidgetManager
                    .getInstance(context);
            ComponentName thisAppWidget = new ComponentName(context
                    .getPackageName(), Widget.class.getName());
            int[] appWidgetIds = appWidgetManager
                    .getAppWidgetIds(thisAppWidget);

            onUpdate(context, appWidgetManager, appWidgetIds);
        }

    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

原谅过去的我 2024-11-03 16:57:12

这是我的解决方案,如何比 30 分钟更频繁地自动更新小部件。我使用警报管理器。在使用 AlarmManager 刷新应用程序小部件之前,请确保您知道自己在做什么,因为这种技术可能会耗尽设备的电池。

详细了解 Android 文档中的小部件更新 - 尤其是 updatePeriodMillis 参数。

这是我的 Manifest.xml 的一部分。我定义了自定义操作 AUTO_UPDATE。

<receiver android:name=".appwidget.AppWidget" >
    <intent-filter>
        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
    </intent-filter>
    <intent-filter>
        <action android:name="AUTO_UPDATE" />
    </intent-filter>
    <meta-data android:name="android.appwidget.provider" android:resource="@xml/appwidget_info" />
</receiver>

这是我的 AppWidget.java 的一部分。在 onReceive 方法中,我处理自定义操作 AUTO_UPDATE。在 onEnabled 和 onDisabled 方法中,我启动/停止警报。

public class AppWidget extends AppWidgetProvider
{
    public static final String ACTION_AUTO_UPDATE = "AUTO_UPDATE";

    @Override
    public void onReceive(Context context, Intent intent)
    {
        super.onReceive(context, intent);

        if(intent.getAction().equals(ACTION_AUTO_UPDATE))
        {
            // DO SOMETHING
        }

        ...
    }

    @Override
    public void onEnabled(Context context)
    {
        // start alarm
        AppWidgetAlarm appWidgetAlarm = new AppWidgetAlarm(context.getApplicationContext());
        appWidgetAlarm.startAlarm();
    }

    @Override
    public void onDisabled(Context context)
    {
        // stop alarm only if all widgets have been disabled
        AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
        ComponentName thisAppWidgetComponentName = new ComponentName(context.getPackageName(),getClass().getName());
        int[] appWidgetIds = appWidgetManager.getAppWidgetIds(thisAppWidgetComponentName);
        if (appWidgetIds.length == 0) {
            // stop alarm
            AppWidgetAlarm appWidgetAlarm = new AppWidgetAlarm(context.getApplicationContext());
            appWidgetAlarm.stopAlarm();
    }

    }

    ...
}

这是我的 AppWidgetAlarm.java,它启动/停止警报。警报管理器向 AppWidget 发送广播。

public class AppWidgetAlarm
{
    private final int ALARM_ID = 0;
    private final int INTERVAL_MILLIS = 10000;

    private Context mContext;


    public AppWidgetAlarm(Context context)
    {
        mContext = context;
    }


    public void startAlarm()
    {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.MILLISECOND, INTERVAL_MILLIS);

        Intent alarmIntent=new Intent(mContext, AppWidget.class);
        alarmIntent.setAction(AppWidget.ACTION_AUTO_UPDATE);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, ALARM_ID, alarmIntent, PendingIntent.FLAG_CANCEL_CURRENT);

        AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
        // RTC does not wake the device up
        alarmManager.setRepeating(AlarmManager.RTC, calendar.getTimeInMillis(), INTERVAL_MILLIS, pendingIntent);
    }


    public void stopAlarm()
    {
        Intent alarmIntent = new Intent(AppWidget.ACTION_AUTO_UPDATE);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, ALARM_ID, alarmIntent, PendingIntent.FLAG_CANCEL_CURRENT);

        AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
        alarmManager.cancel(pendingIntent);
    }
}

This is my solution, how to automatically update widget more frequently than the 30 minutes. I use AlarmManager. Before you use AlarmManager for refreshing appwidget, make sure you know what you do, because this technique could drain the device's battery.

Read more about widget update in Android doc - especially about updatePeriodMillis parameter.

This is part of my Manifest.xml. I define custom action AUTO_UPDATE.

<receiver android:name=".appwidget.AppWidget" >
    <intent-filter>
        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
    </intent-filter>
    <intent-filter>
        <action android:name="AUTO_UPDATE" />
    </intent-filter>
    <meta-data android:name="android.appwidget.provider" android:resource="@xml/appwidget_info" />
</receiver>

This is part of my AppWidget.java. In onReceive method, I handle my custom action AUTO_UPDATE. In onEnabled and onDisabled methods, I start/stop alarm.

public class AppWidget extends AppWidgetProvider
{
    public static final String ACTION_AUTO_UPDATE = "AUTO_UPDATE";

    @Override
    public void onReceive(Context context, Intent intent)
    {
        super.onReceive(context, intent);

        if(intent.getAction().equals(ACTION_AUTO_UPDATE))
        {
            // DO SOMETHING
        }

        ...
    }

    @Override
    public void onEnabled(Context context)
    {
        // start alarm
        AppWidgetAlarm appWidgetAlarm = new AppWidgetAlarm(context.getApplicationContext());
        appWidgetAlarm.startAlarm();
    }

    @Override
    public void onDisabled(Context context)
    {
        // stop alarm only if all widgets have been disabled
        AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
        ComponentName thisAppWidgetComponentName = new ComponentName(context.getPackageName(),getClass().getName());
        int[] appWidgetIds = appWidgetManager.getAppWidgetIds(thisAppWidgetComponentName);
        if (appWidgetIds.length == 0) {
            // stop alarm
            AppWidgetAlarm appWidgetAlarm = new AppWidgetAlarm(context.getApplicationContext());
            appWidgetAlarm.stopAlarm();
    }

    }

    ...
}

This is my AppWidgetAlarm.java, which starts/stops alarm. Alarm manager sends broadcast to AppWidget.

public class AppWidgetAlarm
{
    private final int ALARM_ID = 0;
    private final int INTERVAL_MILLIS = 10000;

    private Context mContext;


    public AppWidgetAlarm(Context context)
    {
        mContext = context;
    }


    public void startAlarm()
    {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.MILLISECOND, INTERVAL_MILLIS);

        Intent alarmIntent=new Intent(mContext, AppWidget.class);
        alarmIntent.setAction(AppWidget.ACTION_AUTO_UPDATE);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, ALARM_ID, alarmIntent, PendingIntent.FLAG_CANCEL_CURRENT);

        AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
        // RTC does not wake the device up
        alarmManager.setRepeating(AlarmManager.RTC, calendar.getTimeInMillis(), INTERVAL_MILLIS, pendingIntent);
    }


    public void stopAlarm()
    {
        Intent alarmIntent = new Intent(AppWidget.ACTION_AUTO_UPDATE);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, ALARM_ID, alarmIntent, PendingIntent.FLAG_CANCEL_CURRENT);

        AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
        alarmManager.cancel(pendingIntent);
    }
}
星星的轨迹 2024-11-03 16:57:12

我有一个设置 AlarmManager 的 Update 类:

不,你没有。 AlarmManager 出现在代码片段中的任何地方。

确实在第二个代码片段中引用了AlarmManager。那里的问题包括:

  • 每次应用程序小部件更新时,您都设置一个新的重复闹钟

  • 您在闹钟上设置 5 秒的频率,这太疯狂了

  • 您在 _WAKEUP 闹钟上设置了 5 秒频率,我认为这是在某些司法管辖区逮捕您的理由

  • 您的说法毫无意义onReceive() 方法,甚至忽略临时 Toast

  • 您假设您的 Toast 中的 Intent 上会有一个操作字符串,但在创建该操作字符串时没有指定操作字符串。您在警报的 PendingIntent 中放入的 Intent

  • 您的代码指的是我认为是电池类上的静态数据成员,但很可能这些都是空/空的......或者至少它们会是,如果你有一个合理的频率Alarm

I have an Update class that sets the AlarmManager:

No, you don't. AlarmManager appears nowhere in the code snippet.

You do have a reference to AlarmManager in the second code snippet. Problems there include:

  • You are setting a new repeating alarm every time the app widget updates

  • You are setting a 5 second frequency on the alarm, which is utter insanity

  • You are setting a 5 second frequency on a _WAKEUP alarm, which I think is grounds for your arrest in some jurisdictions

  • You have a pointless onReceive() method, even ignoring the temporary Toast

  • You are assuming that there will be an action string on the Intent in your Toast, but you do not specify an action string when you create the Intent that you put in the PendingIntent for the alarm

  • Your code refers to what I presume are static data members on a Battery class, but it is rather likely those are all empty/null... or at least they would be, if you had a sane frequency on the alarm

演多会厌 2024-11-03 16:57:12

感谢这个例子 - 我在使用更高版本的 Android 时也遇到了问题。

这篇文章让它对我有用:
小部件案例不起作用(请参阅 Larry Schiefer 的回答)。

因此,用上面的代码替换它:

Intent alarmIntent = new Intent(AppWidget.ACTION_AUTO_UPDATE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, ALARM_ID, alarmIntent, PendingIntent.FLAG_CANCEL_CURRENT);

用 ref 中的这个:

Intent alarmIntent=new Intent(mContext, MyWidget.class);
alarmIntent.setAction(AppWidget.ACTION_AUTO_UPDATE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, ALARM_ID, alarmIntent, PendingIntent.FLAG_CANCEL_CURRENT);

完成了这项工作。

Thanks for this example - I also had problems using a later Android version.

This post made it work for me:
widget case that doesn't work (see the answer from Larry Schiefer).

So substituting for this from the code above:

Intent alarmIntent = new Intent(AppWidget.ACTION_AUTO_UPDATE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, ALARM_ID, alarmIntent, PendingIntent.FLAG_CANCEL_CURRENT);

with this from the ref:

Intent alarmIntent=new Intent(mContext, MyWidget.class);
alarmIntent.setAction(AppWidget.ACTION_AUTO_UPDATE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, ALARM_ID, alarmIntent, PendingIntent.FLAG_CANCEL_CURRENT);

did the job.

独行侠 2024-11-03 16:57:12

petrnohejl 解决方案的一点修改版本。这个正在我的项目中工作。 (用 kotlin 编写):

这是 Manifest.xml 的一部分。我添加了以下操作:AUTO_UPDATE、APPWIDGET_UPDATE、APPWIDGET_ENABLED、APWIDGET_DISABLED。

                <receiver android:name=".AppWidget">
                    <intent-filter>
                        <action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
                        <action android:name="android.appwidget.action.APPWIDGET_ENABLED" />
                        <action android:name="android.appwidget.action.APPWIDGET_DISABLED"/>
                    </intent-filter>
                    <intent-filter>
                        <action android:name="ACTION_AUTO_UPDATE" />
                    </intent-filter>

                    <meta-data
                            android:name="android.appwidget.provider"
                            android:resource="@xml/appwidget_info"/>
                </receiver>

这是 AppWidget.kt 的一部分。这里我实现了onUpdate()、onEnabled()、onDisabled()、onReceive()函数。

class AppWidget: AppWidgetProvider() {

    override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) {

        // There may be multiple widgets active, so update all of them
        for (appWidgetId in appWidgetIds) {
            updateAppWidget(context, appWidgetManager, appWidgetId)
        }
    }

    override fun onEnabled(context: Context) { // Enter relevant functionality for when the first widget is created

        // start alarm
        val appWidgetAlarm = AppWidgetAlarm(context.applicationContext)
        appWidgetAlarm.startAlarm()
    }

    override fun onDisabled(context: Context) { // Enter relevant functionality for when the last widget is disabled

        // stop alarm only if all widgets have been disabled
        val appWidgetManager = AppWidgetManager.getInstance(context)

        if (appWidgetIds.isEmpty()) {
            // stop alarm
            val appWidgetAlarm = AppWidgetAlarm(context.getApplicationContext())
            appWidgetAlarm.stopAlarm()
        }
    }

    companion object {

        val ACTION_AUTO_UPDATE = "AUTO_UPDATE"

        fun updateAppWidget(context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int) {

        val widgetText = Random.nextInt(0, 100).toString()

            // Construct the RemoteViews object
            val views = RemoteViews(context.packageName, R.layout.appwidget)
            views.setTextViewText(R.id.widget_text, widgetText)

            // Instruct the widget manager to update the widget
            appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.widget_text)
            appWidgetManager.updateAppWidget(appWidgetId, views)
        }
    }

    override fun onReceive(context: Context?, intent: Intent?) {
        super.onReceive(context, intent)

        // Do something

        /*if (intent!!.action == ACTION_AUTO_UPDATE) {
            // DO SOMETHING
        }*/
    }
}

这是 AppWidgetAlarm.kt。这是我的主要修改。答案对我没有帮助,但它正在发挥作用。我在这里设置了一个重复闹钟。 (https://developer.android.com/training/scheduling/alarms)

class AppWidgetAlarm(private val context: Context?) {
        private val ALARM_ID = 0
        private val INTERVAL_MILLIS : Long = 10000

    fun startAlarm() {
        val calendar: Calendar = Calendar.getInstance()
        calendar.add(Calendar.MILLISECOND, INTERVAL_MILLIS.toInt())        

        val alarmIntent = Intent(context, AppWidget::class.java).let { intent ->
            //intent.action = AppWidget.ACTION_AUTO_UPDATE
            PendingIntent.getBroadcast(context, 0, intent, 0)
        }
        with(context!!.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
           setRepeating(AlarmManager.RTC,calendar.timeInMillis, INTERVAL_MILLIS ,alarmIntent)
        }
    }

    fun stopAlarm() {
        val alarmIntent = Intent(AppWidget.ACTION_AUTO_UPDATE)
        val pendingIntent = PendingIntent.getBroadcast(context, ALARM_ID, alarmIntent, PendingIntent.FLAG_CANCEL_CURRENT)
        val alarmManager = context!!.getSystemService(Context.ALARM_SERVICE) as AlarmManager
        alarmManager.cancel(pendingIntent)
    }
}

A little bit modified version of petrnohejl's solution. This one is working in my project. (written in kotlin):

This is part of the Manifest.xml. I added the following actions: AUTO_UPDATE, APPWIDGET_UPDATE, APPWIDGET_ENABLED, APWIDGET_DISABLED.

                <receiver android:name=".AppWidget">
                    <intent-filter>
                        <action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
                        <action android:name="android.appwidget.action.APPWIDGET_ENABLED" />
                        <action android:name="android.appwidget.action.APPWIDGET_DISABLED"/>
                    </intent-filter>
                    <intent-filter>
                        <action android:name="ACTION_AUTO_UPDATE" />
                    </intent-filter>

                    <meta-data
                            android:name="android.appwidget.provider"
                            android:resource="@xml/appwidget_info"/>
                </receiver>

This is part of the AppWidget.kt. Here I implemented the onUpdate(), onEnabled(), onDisabled(), onReceive() functions.

class AppWidget: AppWidgetProvider() {

    override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) {

        // There may be multiple widgets active, so update all of them
        for (appWidgetId in appWidgetIds) {
            updateAppWidget(context, appWidgetManager, appWidgetId)
        }
    }

    override fun onEnabled(context: Context) { // Enter relevant functionality for when the first widget is created

        // start alarm
        val appWidgetAlarm = AppWidgetAlarm(context.applicationContext)
        appWidgetAlarm.startAlarm()
    }

    override fun onDisabled(context: Context) { // Enter relevant functionality for when the last widget is disabled

        // stop alarm only if all widgets have been disabled
        val appWidgetManager = AppWidgetManager.getInstance(context)

        if (appWidgetIds.isEmpty()) {
            // stop alarm
            val appWidgetAlarm = AppWidgetAlarm(context.getApplicationContext())
            appWidgetAlarm.stopAlarm()
        }
    }

    companion object {

        val ACTION_AUTO_UPDATE = "AUTO_UPDATE"

        fun updateAppWidget(context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int) {

        val widgetText = Random.nextInt(0, 100).toString()

            // Construct the RemoteViews object
            val views = RemoteViews(context.packageName, R.layout.appwidget)
            views.setTextViewText(R.id.widget_text, widgetText)

            // Instruct the widget manager to update the widget
            appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.widget_text)
            appWidgetManager.updateAppWidget(appWidgetId, views)
        }
    }

    override fun onReceive(context: Context?, intent: Intent?) {
        super.onReceive(context, intent)

        // Do something

        /*if (intent!!.action == ACTION_AUTO_UPDATE) {
            // DO SOMETHING
        }*/
    }
}

And this is the AppWidgetAlarm.kt. Here it is my main modification. The answers didn't help me, but it is working. I set here a repeating alarm. (https://developer.android.com/training/scheduling/alarms)

class AppWidgetAlarm(private val context: Context?) {
        private val ALARM_ID = 0
        private val INTERVAL_MILLIS : Long = 10000

    fun startAlarm() {
        val calendar: Calendar = Calendar.getInstance()
        calendar.add(Calendar.MILLISECOND, INTERVAL_MILLIS.toInt())        

        val alarmIntent = Intent(context, AppWidget::class.java).let { intent ->
            //intent.action = AppWidget.ACTION_AUTO_UPDATE
            PendingIntent.getBroadcast(context, 0, intent, 0)
        }
        with(context!!.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
           setRepeating(AlarmManager.RTC,calendar.timeInMillis, INTERVAL_MILLIS ,alarmIntent)
        }
    }

    fun stopAlarm() {
        val alarmIntent = Intent(AppWidget.ACTION_AUTO_UPDATE)
        val pendingIntent = PendingIntent.getBroadcast(context, ALARM_ID, alarmIntent, PendingIntent.FLAG_CANCEL_CURRENT)
        val alarmManager = context!!.getSystemService(Context.ALARM_SERVICE) as AlarmManager
        alarmManager.cancel(pendingIntent)
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文