gpt4 book ai didi

java - 服务中的广播接收器在服务停止后仍在广播

转载 作者:行者123 更新时间:2023-12-02 11:49:26 24 4
gpt4 key购买 nike

我正在制作一个应用程序,可以跟踪用户的位置并更新他们行驶的距离、总体速度和花​​费的时间。当用户点击 MainActivity.java 中的 StartTracking 按钮时,MapsActivity.java 就会启动。 MapsActivity.java 包含 map fragment 和显示信息的 TextView。位置跟踪是在服务 TrackingService.java 中完成的,因此即使应用程序在后台运行,位置仍然会更新。

为了发送距离、时间和速度,我在服务中使用了广播接收器。当onLocationChanged()被触发时,距离被广播。为了广播时间和速度,我使用了timer.schedule()。当我点击 MapsActivity.java 中的 StopTracking 按钮时,服务应该停止, Activity 被销毁,用户应该返回到 MainActivity.java.

我的问题是,当我点击 StopTracking Button 时,上述所有情况都会发生,除了 timer.schedule() 中的广播仍然保持广播。因此,当我在 MainActivity 中再次点击 StartTracking 时,TextView 的速度和时间会不断在旧值和新值之间切换。相关的类如下,我删除了多余的代码以使其更具可读性。

全面披露:这是一项学校作业。我假设 GPS 条件完美并且连接没有丢失。作业需要使用 BroadCastReciever 和服务。

MapsActivity.java

    public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {

private GoogleMap mMap;
private Intent intent;
private TrackingService trackingService;
private BroadcastReceiver receiver;
private ArrayList<Location> coordinates;
private TextView distanceTV, timeTV, speedTV;
private Button stopTrackingButton;

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

coordinates = new ArrayList<Location>();
distanceTV = (TextView) findViewById(R.id.distanceTextView);
timeTV = (TextView) findViewById(R.id.timeTextView);
speedTV = (TextView) findViewById(R.id.speedTextView);

IntentFilter filter = new IntentFilter();
filter.addAction("locationChanged");
filter.addAction("timeChanged");
filter.addAction("speedChanged");

stopTrackingListener();

SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);

receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {

if(intent.getAction().equals("locationChanged"))
{
Bundle bundle = intent.getExtras();
coordinates = bundle.getParcelableArrayList("COORDINATES");

float distance = bundle.getFloat("DISTANCE");
distanceTV.setText("Distance: " + Float.toString((float) Math.round(distance *100f) / 100f) + "m");
Log.d("test", "onReceive location");
redrawLine();
}
else if (intent.getAction().equals("timeChanged"))
{
Bundle bundle = intent.getExtras();
long time = bundle.getLong("TIME");

float hours = (float) (((time/1000) / 60) / 60);
float mins = (float) (((time/1000) / 60) % 60);
float secs = (float) ((time/1000) %60);

timeTV.setText(String.format("Time: %.0fh: %.0fm: %.0fs", hours, mins, secs));
}
else if (intent.getAction().equals("speedChanged"))
{
Bundle bundle = intent.getExtras();
float speed = bundle.getFloat("SPEED");
speedTV.setText("Avg Speed: " + Float.toString (Math.round(speed *100f) / 100f) + "m/s");
}
}
};
LocalBroadcastManager.getInstance(this).registerReceiver(receiver, filter);
}


private ServiceConnection trackerConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
TrackingService.TrackingBinder binder = (TrackingService.TrackingBinder)iBinder;
trackingService = binder.getService();

Log.d("test", "Service is Connected");
}

@Override
public void onServiceDisconnected(ComponentName componentName) {
Log.d("test", "Service Disconnected");
}
};

//Start the service as soon as activity starts
@Override
protected void onStart()
{
super.onStart();
if(intent == null)
{
intent = new Intent(getBaseContext(), TrackingService.class);
bindService(intent, trackerConnection, Context.BIND_AUTO_CREATE);
startService(intent);
Log.d("test", "Service Started");
}
}

//Unbind and destroy service when app is destroyed
@Override
protected void onDestroy()
{
unbindService(trackerConnection);
getBaseContext().stopService(intent);
Log.d("test", "Service Destroyed");
super.onDestroy();
}

//Listens for user tapping on "Stop tracking..." button.
public void stopTrackingListener()
{
stopTrackingButton = (Button)findViewById(R.id.stopTrackingButton);

stopTrackingButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view)
{

Log.d("test", "Stopped tracking...");
getBaseContext().stopService(intent);
trackingService = null;

Intent i =new Intent (MapsActivity.this, MainActivity.class);
startActivity(i);

finish();
}
});
}

}

TrackingService.java

    public class TrackingService extends Service implements LocationListener{

private final IBinder trackingBind = new TrackingBinder();
private ArrayList<Location> points;
LocationManager locationManager;
StopWatch timer;


public void onCreate()
{
super.onCreate();

points = new ArrayList<Location>();
timer = new StopWatch();

locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
requestLocation();
updateTimeAndSpeed();
}

private void requestLocation() {

if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}

locationManager.requestLocationUpdates(locationManager.GPS_PROVIDER, 1000, 1, this);
timer.start();
}

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

@Override
public boolean onUnbind(Intent intent)
{
timer.stop();
Log.d("test2", "Service onUnbind");
return false;
}

@Override
public void onLocationChanged(Location location) {

points.add(location);
broadcastCurrentLocation();
}


public class TrackingBinder extends Binder
{
TrackingService getService()
{
return TrackingService.this;
}
}

public void updateTimeAndSpeed()
{
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
broadcastElapsedTime();
broadcastAverageSpeed();
Log.d("test2", "Broadcasting...");
}
}, 0, 1000);
}

public void broadcastElapsedTime()
{
Intent intent = new Intent ("timeChanged");
intent.putExtra("TIME", getTime());
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}

public void broadcastCurrentLocation()
{
Intent intent = new Intent ("locationChanged");
intent.putParcelableArrayListExtra("COORDINATES", points);
intent.putExtra("DISTANCE", calculateDistance());
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}

public void broadcastAverageSpeed()
{
Intent intent = new Intent ("speedChanged");
intent.putExtra("SPEED", getSpeed());
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}

public float calculateDistance()
{
float distance = 0;

if(null != points && (!points.isEmpty()))
{
for(int i = 1; i < points.size(); i++)
{
Location currLoc = new Location(points.get(i));
Location lastLoc = new Location(points.get(i-1));

distance += lastLoc.distanceTo(currLoc);
}
}
return distance;
}

public long getTime()
{
return timer.getElapsedTime();
}


public float getSpeed()
{
float distance = calculateDistance();

long time = getTime();
float timeAsSeconds = (float) (time/1000);

return (distance / timeAsSeconds);
}


}

最佳答案

重写 Service 子类中的 onDestroy()。在该方法中,您可以在固定延迟计时器上调用 Timer.cancel() 。 (您需要将该计时器的引用保留为 TrackingService.java 中的字段。)

关于java - 服务中的广播接收器在服务停止后仍在广播,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47988056/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com