Hiểu về START_STICKY
START_STICKY là flag trả về trong onStartCommand() chỉ định hành vi khi Service bị hệ thống kill do thiếu bộ nhớ:
- START_STICKY: Hệ thống sẽ restart Service sau khi có đủ bộ nhớ, gọi
onStartCommand()với intent = null - START_NOT_STICKY: Không restart tự động
- START_REDELIVER_INTENT: Restart và redeliver intent cuối cùng
Ví dụ triển khai
Bước 1-2: Dự án và Layout
Giống các bài trước: Empty Activity + TextView làm nút Start/Stop.
Bước 3: MainActivity.java
package com.example.andy.myapplication;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView text = findViewById(R.id.text);
text.setOnClickListener(v -> {
if (isMyServiceRunning(StickyService.class)) {
text.setText("Stopped");
stopService(new Intent(this, StickyService.class));
} else {
text.setText("Started");
startService(new Intent(this, StickyService.class));
}
});
}
private boolean isMyServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
}
Bước 4: StickyService.java
package com.example.andy.myapplication;
import android.app.Service;
import android.content.Intent;
import android.os.Build;
import android.os.IBinder;
import android.util.Log;
import androidx.annotation.RequiresApi;
import android.widget.Toast;
public class StickyService extends Service {
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
Log.d("StickyService", "onCreate called");
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "Sticky Service started", Toast.LENGTH_LONG).show();
Log.d("StickyService", "onStartCommand - START_STICKY");
// Giả lập công việc nền
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
Log.d("StickyService", "Working... " + i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
return START_STICKY; // Quan trọng: yêu cầu restart nếu bị kill
}
@Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "Sticky Service destroyed", Toast.LENGTH_LONG).show();
Log.d("StickyService", "onDestroy called");
}
}
Bước 5: Manifest
<service android:name=".StickyService" />
Kiểm tra START_STICKY hoạt động
- Chạy app, bật Service
- Mở Settings → Apps → Your App → Force Stop (hoặc kill process từ Developer Options)
- Quan sát logcat: Service sẽ tự restart sau vài giây,
onCreate()vàonStartCommand(null, ...)được gọi lại
Lưu ý thực tế: Từ Android 8.0, Background Service bị giới hạn. START_STICKY chỉ hoạt động tốt cho Foreground Service. Để đảm bảo service chạy liên tục, hãy kết hợp với startForeground() (xem bài trước).