在实时应用程序的后台运行重复任务

发布于 2024-11-03 07:22:54 字数 333 浏览 4 评论 0原文

我正在编写一个应用程序,它不断监听和检查传感器(几乎所有可用的)并将该数据保存到设备的数据库中。

我需要每隔 X 秒使用该数据进行一些计算,如果计算检查是这样,则抛出一个新事件。 我正在考虑请求在使用应用程序时插入设备(关于电池消耗)。

对于需要进行计算并引发事件的任务,最佳方法是什么?计时器?线程?异步任务?报警管理器?另一种方法?

我想继续获取传感器数据并将它们保存到数据库中,尽管应用程序不在前台......只要用户不停止应用程序,它就应该保存这些值。 一种选择是唤醒锁(PARTIAL_WAKE_LOCK,它保持 CPU 运行)。

我想听听不同的意见。 提前致谢!吉列尔莫.

I'm writing an application which is continuously listening and checking the sensors (almost all available) and saving that data into the database in the device.

I need to make some calculations every X second with that data and throw a new event if the calculations check says so.
I'm thinking about requesting to have the device plugged in while using the application (regarding battery drain).

What's the best approach for the task that needs to make the calculations and throw the event? Timer? Threads? AsynkTask? AlarmManager? Another approach?

I want to keep getting sensors data and saving them to the database despite if the application is not on foreground...it should save the values as long as the application is not stopped by the user.
One option for that is wake locks (PARTIAL_WAKE_LOCK, which keeps CPU running).

I'd like to hear different opinions.
Thanks in advance! Guillermo.

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

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

发布评论

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

评论(2

一刻暧昧 2024-11-10 07:22:54

您可以使用 AlarmManager 设置重复任务(这是 Android 设置未来/重复任务的首选方法)。要进行计算,请使用Service(如果您认为计算会很昂贵,请考虑将它们移动到单独的工作线程或使用IntentService)。

关于唤醒锁(来自 AlarmManager 参考):

警报管理器保持 CPU 唤醒
只要警报接收器的锁定
onReceive() 方法正在执行。这
保证手机不会
睡觉直到处理完毕
广播。一旦 onReceive()
返回,警报管理器释放
这个唤醒锁。这意味着
在某些情况下,手机会尽快进入睡眠状态
当你的 onReceive() 方法完成时。
如果您的报警接收器打来电话
Context.startService(),是可以的
手机会在
请求的服务已启动。到
防止这种情况发生,你的广播接收器
和服务将需要实施
单独的唤醒锁策略以确保
电话继续运行直到
该服务可用。

You can use AlarmManager to setup the repeating tasks (this is the Android prefered way of setting future/repeating tasks). To make the calculations use a Service (if you think calculations are going to be expensive, then think about moving them to a separate worker thread or use IntentService).

Regarding the wake lock (from the AlarmManager reference):

The Alarm Manager holds a CPU wake
lock as long as the alarm receiver's
onReceive() method is executing. This
guarantees that the phone will not
sleep until you have finished handling
the broadcast. Once onReceive()
returns, the Alarm Manager releases
this wake lock. This means that the
phone will in some cases sleep as soon
as your onReceive() method completes.
If your alarm receiver called
Context.startService(), it is possible
that the phone will sleep before the
requested service is launched. To
prevent this, your BroadcastReceiver
and Service will need to implement a
separate wake lock policy to ensure
that the phone continues running until
the service becomes available.

嗼ふ静 2024-11-10 07:22:54

这是我不久前编写的用于记录 CPU 频率的服务的修改片段。它缺少 ApplicationActivity 部分,但说明了我如何编写 Service 以保持每十秒记录一次。当手机进入深度睡眠时它不会记录,因此如果您想不间断地记录,那么您将需要获取 PARTIAL_WAKE_LOCK ,但请考虑电池寿命将因此严重缩短。

public class YOURCLASS_Service extends Service {
    private long mStartTime = 0L;
    private final Handler mHandler = new Handler();
    private Runnable mUpdateTimeTask;
    private YOURAPP app;

    @Override
    public void onCreate() {
        super.onCreate();
        app = (YOURAPP) getApplicationContext();
    }

    @Override
    public void onDestroy() {
        Toast.makeText(this, "Service finished.", Toast.LENGTH_SHORT).show();
        stopLog ();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (app.isRunning())
            return START_STICKY;
        try {
            File file = new File(Environment.getExternalStorageDirectory(), "yourlog.csv");
            OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(file, false));
            out.write("Log title");
            out.close();
        } catch (java.io.IOException e) {
              stopLog ();
              Toast.makeText(this, "Error creating log file. Aborting.", Toast.LENGTH_SHORT).show();
        }

        mUpdateTimeTask = new Runnable() {
            public void run() {
                long millis = SystemClock.uptimeMillis() - mStartTime;
                int seconds = (int) (millis / 1000);
                int minutes = seconds / 60;
                seconds     = seconds % 60;

                readYourSensors ();
                   if (!writeLog (str)) stopLog();
                   mHandler.postAtTime(this, mStartTime + (((minutes * 60) + seconds + 10) * 1000));
                   mHandler.postDelayed (mUpdateTimeTask, 10000);
        }};
        mStartTime = SystemClock.uptimeMillis();
        mHandler.removeCallbacks(mUpdateTimeTask);
        mHandler.postDelayed(mUpdateTimeTask, 100);

        Notification notification = new Notification(R.drawable.notification_icon, "App title", System.currentTimeMillis());
        Intent notificationIntent = new Intent(this, YOURCLASS.class);
        PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
        notification.setLatestEventInfo(getApplicationContext(), "App title", "Please see /sdcard/yourlog.csv", contentIntent);
        startForeground(startId, notification);

        app.isRunning(true);
        return START_STICKY;
    }

    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }

    public void stopLog () {
            mHandler.removeCallbacks(mUpdateTimeTask);
    }
}    

This is a modified snippet of a service I wrote to log CPU frequency some time ago. It lacks the Application and the Activity part, but illustrates how I wrote the Service to keep logging every ten seconds. It does not log when the phone goes into deep sleep, so if you want to log without interruptions, then you will need to acquire PARTIAL_WAKE_LOCKs, but consider that battery life will be severely reduced by that.

public class YOURCLASS_Service extends Service {
    private long mStartTime = 0L;
    private final Handler mHandler = new Handler();
    private Runnable mUpdateTimeTask;
    private YOURAPP app;

    @Override
    public void onCreate() {
        super.onCreate();
        app = (YOURAPP) getApplicationContext();
    }

    @Override
    public void onDestroy() {
        Toast.makeText(this, "Service finished.", Toast.LENGTH_SHORT).show();
        stopLog ();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (app.isRunning())
            return START_STICKY;
        try {
            File file = new File(Environment.getExternalStorageDirectory(), "yourlog.csv");
            OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(file, false));
            out.write("Log title");
            out.close();
        } catch (java.io.IOException e) {
              stopLog ();
              Toast.makeText(this, "Error creating log file. Aborting.", Toast.LENGTH_SHORT).show();
        }

        mUpdateTimeTask = new Runnable() {
            public void run() {
                long millis = SystemClock.uptimeMillis() - mStartTime;
                int seconds = (int) (millis / 1000);
                int minutes = seconds / 60;
                seconds     = seconds % 60;

                readYourSensors ();
                   if (!writeLog (str)) stopLog();
                   mHandler.postAtTime(this, mStartTime + (((minutes * 60) + seconds + 10) * 1000));
                   mHandler.postDelayed (mUpdateTimeTask, 10000);
        }};
        mStartTime = SystemClock.uptimeMillis();
        mHandler.removeCallbacks(mUpdateTimeTask);
        mHandler.postDelayed(mUpdateTimeTask, 100);

        Notification notification = new Notification(R.drawable.notification_icon, "App title", System.currentTimeMillis());
        Intent notificationIntent = new Intent(this, YOURCLASS.class);
        PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
        notification.setLatestEventInfo(getApplicationContext(), "App title", "Please see /sdcard/yourlog.csv", contentIntent);
        startForeground(startId, notification);

        app.isRunning(true);
        return START_STICKY;
    }

    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }

    public void stopLog () {
            mHandler.removeCallbacks(mUpdateTimeTask);
    }
}    
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文