0

我正在为 Android 实现 Java 中的 StepCounter。如果还没有此服务的另一个实例,我创建了一个作为 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));

和这样的广播接收器

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

切换到Activity 4次后,BroadcastReceiver每条消息接收4次,切换到Activity 10次后,每条消息接收10次。有人可以告诉我问题吗?我以为我只有 1 个服务,所以每 5 秒有 1 个广播消息。

4

1 回答 1

1

感谢艺术!

我只需要正确注销 BroadcastReceivers:

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

}

现在像魅力一样工作!

于 2020-01-15T17:43:46.483 回答