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

Gửi thông báo khi ứng dụng Android bị đóng

Giới thiệu

Ví dụ này minh họa cách gửi thông báo khi người dùng đóng hoàn toàn ứng dụng (không chỉ ẩn vào background). Sử dụng Service kết hợp với Timer để tiếp tục chạy nền và hiển thị thông báo định kỳ.

Kiến trúc giải pháp

  • MainActivity: Giao diện chính, khởi động Service khi onStop() được gọi
  • NotificationService: Service chạy nền, dùng Timer để tạo thông báo định kỳ

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

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

Tạo project Android Studio mới.

Bước 2: Layout chính (res/layout/activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp"
    tools:context=".MainActivity">

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:onClick="closeApp"
        android:text="Đóng ứng dụng để nhận thông báo" />

</RelativeLayout>

Bước 3: MainActivity (src/MainActivity.java)

package app.tutorialspoint.com.notifyme;

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;

public class MainActivity extends AppCompatActivity {

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

    @Override
    protected void onStop() {
        super.onStop();
        // QUAN TRỌNG: Khởi động Service khi app đóng
        startService(new Intent(this, NotificationService.class));
    }

    public void closeApp(View view) {
        finish(); // Kết thúc Activity hoàn toàn
    }
}

Bước 4: NotificationService (src/NotificationService.java)

package app.tutorialspoint.com.notifyme;

import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import java.util.Timer;
import java.util.TimerTask;

public class NotificationService extends Service {
    public static final String NOTIFICATION_CHANNEL_ID = "10001";
    private final static String default_notification_channel_id = "default";

    Timer timer;
    TimerTask timerTask;
    String TAG = "Timers";
    int YOUR_X_SECS = 5; // Demo: 5 giây. Thực tế: 300 (5 phút)

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

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e(TAG, "onStartCommand");
        super.onStartCommand(intent, flags, startId);
        startTimer();
        return START_STICKY; // Restart service nếu bị kill
    }

    @Override
    public void onCreate() {
        Log.e(TAG, "onCreate");
    }

    @Override
    public void onDestroy() {
        Log.e(TAG, "onDestroy");
        stopTimerTask();
        super.onDestroy();
    }

    final Handler handler = new Handler();

    public void startTimer() {
        timer = new Timer();
        initializeTimerTask();
        // Chạy lần đầu sau 5 giây, sau đó mỗi 5 giây
        timer.schedule(timerTask, 5000, YOUR_X_SECS * 1000);
    }

    public void stopTimerTask() {
        if (timer != null) {
            timer.cancel();
            timer = null;
        }
    }

    public void initializeTimerTask() {
        timerTask = new TimerTask() {
            public void run() {
                handler.post(new Runnable() {
                    public void run() {
                        createNotification();
                    }
                });
            }
        };
    }

    private void createNotification() {
        NotificationManager mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getApplicationContext(), default_notification_channel_id);

        mBuilder.setContentTitle("App đã đóng");
        mBuilder.setContentText("Thông báo từ Service chạy nền");
        mBuilder.setTicker("Thông báo background");
        mBuilder.setSmallIcon(R.drawable.ic_launcher_foreground);
        mBuilder.setAutoCancel(true);

        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            int importance = NotificationManager.IMPORTANCE_HIGH;
            NotificationChannel notificationChannel = new NotificationChannel(
                NOTIFICATION_CHANNEL_ID, "NOTIFICATION_CHANNEL_NAME", importance);
            mBuilder.setChannelId(NOTIFICATION_CHANNEL_ID);
            assert mNotificationManager != null;
            mNotificationManager.createNotificationChannel(notificationChannel);
        }

        assert mNotificationManager != null;
        mNotificationManager.notify((int) System.currentTimeMillis(), mBuilder.build());
    }
}

Bước 5: AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
    package="app.tutorialspoint.com.notifyme">

    <uses-permission android:name="android.permission.VIBRATE" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service
            android:name=".NotificationService"
            android:label="@string/app_name">
            <intent-filter>
                <action android:name="app.tutorialspoint.com.notifyme.NotificationService" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </service>

    </application>
</manifest>

Lưu ý quan trọng cho Production

⚠️ Hạn chế trên Android 8.0+ (API 26+)

  • Background Service bị giới hạn thời gian chạy
  • Nên dùng WorkManager cho tác vụ định kỳ tin cậy
  • Hoặc Foreground Service với notification luôn hiển thị
  • Cần quyền FOREGROUND_SERVICE trong Manifest

Chạy thử nghiệm

Cài đặt app, mở lên, nhấn nút "Đóng ứng dụng để nhận thông báo". Đợi vài giây để thấy thông báo xuất hiện trên màn hình khóa hoặc thanh thông báo.