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/TimerTasktrong 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", ...

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.