Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Android

Khởi động IntentService định kỳ mỗi 10 giây trong Android

Mục tiêu

Chạy IntentService tự động lặp lại mỗi 10 giây để kiểm tra/cập nhật dữ liệu nền, và gửi kết quả về UI qua BroadcastReceiver.

⚠️ Cảnh báo quan trọng

  • IntentService đã deprecated từ Android 11 (API 30)
  • Sử dụng Timer/TimerTask trong Activity dễ bị kill khi app vào background
  • Khuyên dùng: WorkManager (periodic work), AlarmManager + Foreground Service, hoặc JobScheduler

Ví dụ dưới đây chỉ mang tính học tập/minh họa cơ chế.

Các bước thực hiện

Bước 1: Tạo dự án mới

Android Studio → File → New Project → Empty Activity.

Bước 2: Layout (activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:app="https://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/tvStatus"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Service sẽ chạy mỗi 10s"
        android:textSize="20sp"
        android:padding="16dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Bước 3: PeriodicService.java (IntentService)

package com.example.periodicintentservice;

import android.app.IntentService;
import android.content.Intent;
import android.os.IBinder;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;

public class PeriodicService extends IntentService {

    public static final String ACTION_PERIODIC_UPDATE = "com.example.periodicintentservice.PERIODIC_UPDATE";
    public static final String EXTRA_TIMESTAMP = "timestamp";
    public static volatile boolean shouldStop = false;

    public PeriodicService() {
        super("PeriodicService");
    }

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

    @Override
    protected void onHandleIntent(Intent intent) {
        if (shouldStop) {
            stopSelf();
            return;
        }

        // Gửi timestamp hiện tại về UI
        Intent broadcastIntent = new Intent(ACTION_PERIODIC_UPDATE);
        broadcastIntent.putExtra(EXTRA_TIMESTAMP, "⏰ " + java.text.DateFormat.getTimeInstance().format(new java.util.Date()));
        LocalBroadcastManager.getInstance(this).sendBroadcast(broadcastIntent);
    }
}

Bước 4: MainActivity.java với Timer

package com.example.periodicintentservice;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import java.util.Timer;
import java.util.TimerTask;

public class MainActivity extends AppCompatActivity {

    private TextView tvStatus;
    private Timer timer;
    private BroadcastReceiver receiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        tvStatus = findViewById(R.id.tvStatus);

        // Receiver nhận dữ liệu từ Service
        receiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String time = intent.getStringExtra(PeriodicService.EXTRA_TIMESTAMP);
                tvStatus.setText("Cập nhật lần cuối: " + time);
            }
        };

        // Timer lặp lại mỗi 10 giây (10000ms)
        timer = new Timer();
        TimerTask task = new TimerTask() {
            @Override
            public void run() {
                new Handler(getMainLooper()).post(() -> 
                    startService(new Intent(MainActivity.this, PeriodicService.class))
                );
            }
        };
        timer.schedule(task, 0, 10000); // delay=0, period=10000ms
    }

    @Override
    protected void onStart() {
        super.onStart();
        LocalBroadcastManager.getInstance(this)
            .registerReceiver(receiver, new IntentFilter(PeriodicService.ACTION_PERIODIC_UPDATE));
    }

    @Override
    protected void onStop() {
        super.onStop();
        LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (timer != null) {
            timer.cancel();
            timer.purge();
        }
        PeriodicService.shouldStop = true;
    }
}

Bước 5: AndroidManifest.xml

<service android:name=".PeriodicService" />
<uses-permission android:name="android.permission.WAKE_LOCK" />

Kết quả

TextView cập nhật thời gian mỗi 10 giây: "Cập nhật lần cuối: ⏰ 14:30:45", "Cập nhật lần cuối: ⏰ 14:30:55", ...

Khởi động IntentService định kỳ mỗi 10 giây trong Android

Giải pháp hiện đại thay thế (Khuyên dùng)

WorkManager (PeriodicWorkRequest) - Tốt nhất cho tác vụ định kỳ

PeriodicWorkRequest workRequest = new PeriodicWorkRequest.Builder(
    MyWorker.class, 15, TimeUnit.MINUTES) // Tối thiểu 15 phút
    .build();
WorkManager.getInstance(context).enqueue(workRequest);

AlarmManager + Foreground Service - Cho chu kỳ ngắn (< 15 phút)

AlarmManager alarm = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent intent = new Intent(this, MyForegroundService.class);
PendingIntent pending = PendingIntent.getService(this, 0, intent, FLAG_IMMUTABLE);
alarm.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 10000, pending);

Service phải là Foreground Service (hiển thị notification) để không bị kill.