Служба с START_STICKY

Я хочу создать сервис, который будет проверять новые уведомления каждый раз, даже если основное приложение закрыто.

Добавить в манифест

    <service
        android:name=".service.NotificationService"
        android:enabled="true"
        android:exported="true"
        android:stopWithTask="false"
        android:process=":notification"/>

    <!-- Declaring broadcast receiver for BOOT_COMPLETED event. -->
    <receiver android:name=".BootReceiver"
        android:enabled="true"
        android:permission="android.permission.RECEIVE_BOOT_COMPLETED"
        >
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED"/>
            <category android:name="android.intent.category.DEFAULT" />

        </intent-filter>
    </receiver>

Второй - загрузочный приемник, он также запустит сервис после перезагрузки.

NotificationService.class

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.os.IBinder;
import android.util.Log;

import com.tagwishes.fc.Notification;
import com.tagwishes.fc.app.AppConfig;
import com.tagwishes.fc.helper.SessionManager;

import java.util.Timer;
import java.util.TimerTask;

public class NotificationService extends Service {


    static int WIFI_NETWORK_ID = 1;
    static int MOBILE_NETWORK_ID = 2;
    static int NO_NETWORK_ID = 3;
    private SessionManager sm;


    final String LOG_TAG = "fc";

    public void onCreate() {
        super.onCreate();
        Log.d(LOG_TAG, "MyService onCreate");
    }

    public void onDestroy() {
        super.onDestroy();
        Log.d(LOG_TAG, "MyService onDestroy");
    }

    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(LOG_TAG, "MyService onStartCommand");


        readFlags(flags);
        MyRun mr = new MyRun(startId);
        new Thread(mr).start();


        Log.d("fc", "START_STICKY");

        return START_STICKY;
    }

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

    int chkStatus() {
        final ConnectivityManager connMgr = (ConnectivityManager)
                this.getSystemService(Context.CONNECTIVITY_SERVICE);
        final android.net.NetworkInfo wifi = connMgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
        final android.net.NetworkInfo mobile = connMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
        if (wifi.isConnectedOrConnecting()) {
            return WIFI_NETWORK_ID;
        } else if (mobile.isConnectedOrConnecting()) {
            return MOBILE_NETWORK_ID;
        } else {
            return NO_NETWORK_ID;
        }
    }

    void readFlags(int flags) {
        if ((flags&START_FLAG_REDELIVERY) == START_FLAG_REDELIVERY)
            Log.d(LOG_TAG, "START_FLAG_REDELIVERY");
        if ((flags&START_FLAG_RETRY) == START_FLAG_RETRY)
            Log.d(LOG_TAG, "START_FLAG_RETRY");
    }

    class MyRun implements Runnable {

        int startId;

        public MyRun(int startId) {
            this.startId = startId;
            Log.d(LOG_TAG, "MyRun#" + startId + " create");
        }

        public void run() {
            Log.d(LOG_TAG, "MyRun#" + startId + " start");

            final int networkID = chkStatus();

            Log.d("fc", "networkID " + networkID);

            if (sm == null) {
                sm = new SessionManager(getApplication());
            }

            int reCheckTime = AppConfig.NOTIFICATION_RECHECK_DEFAULT;

            if (networkID == WIFI_NETWORK_ID) {
                reCheckTime = AppConfig.NOTIFICATION_RECHECK_WIFI;
            } else if (networkID == MOBILE_NETWORK_ID) {
                reCheckTime = AppConfig.NOTIFICATION_RECHECK_MOBILE;
            }


            final Notification nt = new Notification(getApplicationContext());//Its my own class


            Log.d("fc", "Timer check noti started " + reCheckTime);
            new Timer().scheduleAtFixedRate(new TimerTask(){
                @Override
                public void run(){

                    if (networkID != NO_NETWORK_ID || !sm.isLoggedIn()) {//IF HAVE NETWORK CONNECTION
                        Log.d("fc", "checkNotifications ");

                        nt.checkNotifications();
                    }

                }
            }, 0, reCheckTime*1000);


        }

    }

}

Boot Receiver

public class BootReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {

    Log.d("fc", "BootReceiver BroadcastReceiver");

    Intent myIntent = new Intent(context, NotificationService.class);
    context.startService(myIntent);
}

}

И это, как я называю службу на MainActivity

        Intent bindIntent = new Intent(getBaseContext(), NotificationService.class);
        startService(bindIntent);

Когда я закрываю приложение из истории приложений, оно также закрывает процесс уведомления: служба не запускается снова. Я использую START_STICKY для этого.

1 ответ

Для nadroid O+ необходимо вызвать сервис startForground. так что это будет ваш приемник:

 public void onReceive(Context context, Intent intent) {

   
    Intent service = new Intent(context, NotificationService.class);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        context.startForegroundService(service);
    } else {
        context.startService(service);
    }

и, конечно, объявите службу переднего плана в своем манифесте.

Начать свой сервис внутри onDestroy функция

@Override
protected void onDestroy() {
super.onDestroy();
//startService()
}
Другие вопросы по тегам