Сервис отправки нескольких широковещательных сообщений - PullRequest
0 голосов
/ 15 января 2020

Я реализую StepCounter в Java для Android. Я создал службу, которая запускается как ForegroundService, если еще нет другого экземпляра этой службы.

package com.**.service.services;

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;

import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;

import com.**.R;

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


public class StepCountingService extends Service implements SensorEventListener {
    private SensorManager sensorManager;
    private Sensor steps;
    private int numSteps = 0;
    private Intent intent;
    public static final String BROADCAST_ACTION = "BROADCASTING_STEPS";
    public static final String TAG = "StepCountingService";
    private static final int UPDATE_DELAY = 5000;

    public static StepCountingService instance = null;

    public static boolean isStarted() {
        return instance != null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        intent = new Intent(BROADCAST_ACTION);
        instance = this;
        sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
        steps = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR);
        sensorManager.registerListener(this, steps, SensorManager.SENSOR_DELAY_UI);
        new Timer().scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                broadcastSensorValue();
            }
        }, 1000, 5000);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        instance = null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i(TAG, "onStartCommand called");
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            String NOTIFICATION_CHANNEL_ID = "com.sportify.app";
            String channelName = "Step Counting";
            NotificationChannel chan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName, NotificationManager.IMPORTANCE_NONE);
            chan.setLightColor(Color.BLUE);
            chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
            NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
            manager.createNotificationChannel(chan);

            NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID);
            Notification notification = notificationBuilder.setOngoing(true)
                    .setContentTitle("App is counting steps in background")
                    .setPriority(NotificationManager.IMPORTANCE_MIN)
                    .setCategory(Notification.CATEGORY_SERVICE)
                    .build();
            startForeground(2, notification);
        }
        else {
            startForeground(1, new Notification());
        }
        return START_STICKY;
    }

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


    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        Log.i(TAG, "onSensorChanged called " + numSteps);
        if (event.sensor.getType() == Sensor.TYPE_STEP_DETECTOR) {
            numSteps++;
        }
    }

    private void broadcastSensorValue() {
        if (numSteps > 0) {
            intent.putExtra("step_count", String.valueOf(numSteps));
            sendBroadcast(intent);
            numSteps = 0; //TODO: if broadcast is not received (bcs app is closed), steps are lost! FIX ME!
        }
    }
}

В моей деятельности запуск службы выглядит так:

if (!StepCountingService.isStarted()) {
    Intent service = new Intent(parent.getBaseContext(), StepCountingService.class);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        parent.startForegroundService(service);
    } else {
        parent.startService(service);
    }
    Log.i(StepCountingService.TAG, "setting up service");
}
else {
    Log.i(StepCountingService.TAG, "service already running!");
}
parent.registerReceiver(broadcastReceiverSteps, new IntentFilter(StepCountingService.BROADCAST_ACTION));

и BroadcastReceiver, подобный этому

    private BroadcastReceiver broadcastReceiverSteps = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        homeViewModel.setSteps(context, Integer.valueOf(intent.getStringExtra("step_count")));
    }
};

После четырехкратного переключения на действие, BroadcastReceiver получает каждое сообщение 4 раза, после переключения на действие 10 раз - каждое сообщение 10 раз. Может кто-нибудь сказать мне проблему? Я думал, что у меня есть только 1 услуга, поэтому 1 широковещательное сообщение каждые 5 секунд.

1 Ответ

1 голос
/ 15 января 2020

Благодаря искусству!

Мне просто нужно было правильно отменить регистрацию BroadcastReceivers:

@Override
public void onDestroy() {
    Activity parent = getActivity();
    parent.unregisterReceiver(broadcastReceiverSteps);
    parent.unregisterReceiver(broadcastReceiverLocations);
    super.onDestroy();

}

Теперь работает как шарм!

...