我已经构建了一个应用程序,该应用程序可以跟踪用户的游乐设施,并显示用户的距离,持续时间和速度以及绘制行驶路线的折线的地图。我已使用服务使应用程序在后台运行。作为一个独立的应用程序,它可以平稳运行,距离和持续时间也会在后台不断更新,当从后台重新打开活动时,它将继续正常运行。但是,当我尝试将该应用程序与另一个具有导航视图的应用程序集成在一起,并且从该视图中启动前一个应用程序时,这给问题了。它在首次启动时运行,但是在按下后部后再次从导航启动ride应用程序,然后应用程序重新启动时,它不会加载在后台绘制的折线。
我的地图活动:
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback, LocationListener {
public static GoogleMap mMap;
public static double lat1=0,lng1=0;
private static final String TAG = MapsActivity.class.getSimpleName();
private static final int REQUEST_PERMISSIONS_REQUEST_CODE = 34;
private MyReceiver myReceiver;
private LocationUpdatesService mService = null;
private boolean mBound = false;
public static Button mRequestLocationUpdatesButton;
private double d1,d2;
boolean isClick;
private Location mLastLocation;
SharedPreferences sharedPreferences;
public static LocationManager manager;
LocationRequest mLocationRequest;
Marker mCurrLocationMarker;
FusedLocationProviderClient mFusedLocationClient;
public static TextView km, speed1,aa,bb;
public static Chronometer chronometer;
boolean running;
public static double kms = 0.00d, finspeed = 0.00d;
private long pause;
public static float temp = 0.00f;
public static String jj = "0.00";
public static String durations = null;
public static long durationTime, c = 0, i = 1;
public static int findur = 0, findur1 = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
Log.i("Create", "is working");
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
myReceiver = new MyReceiver();
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
if (Utils.requestingLocationUpdates(this)) {
if (!checkPermissions()) {
requestPermissions();
}
}
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
manager = (LocationManager) getSystemService( Context.LOCATION_SERVICE );
sharedPreferences = getApplicationContext().getSharedPreferences("MyPrefs", MODE_PRIVATE);
SharedPreferences.Editor edit = sharedPreferences.edit();
edit.putString("lat1", null);
edit.putString("lng1", null);
edit.apply();
mRequestLocationUpdatesButton = findViewById(R.id.button);
bindService(new Intent(this, LocationUpdatesService.class), mServiceConnection,
Context.BIND_AUTO_CREATE);
chronometer = findViewById(R.id.duration);
km = findViewById(R.id.km);
speed1 = findViewById(R.id.speed);
aa=findViewById(R.id.textView4);
bb=findViewById(R.id.textView8);
aa.setVisibility(View.INVISIBLE);
bb.setVisibility(View.INVISIBLE);
}
private final ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
LocationUpdatesService.LocalBinder binder = (LocationUpdatesService.LocalBinder) service;
mService = binder.getService();
mBound = true;
}
@Override
public void onServiceDisconnected(ComponentName name) {
mService = null;
mBound = false;
}
};
@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(10000); // 10 sec interval
mLocationRequest.setFastestInterval(5000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
//Location Permission already granted
mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper());
mMap.setMyLocationEnabled(true);
} else {
//Request Location Permission
requestPermissions();
}
}
else {
mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper());
mMap.setMyLocationEnabled(true);
}
}
LocationCallback mLocationCallback = new LocationCallback() {
@Override
public void onLocationResult(LocationResult locationResult) {
if(c!=0)
return;
List<Location> locationList = locationResult.getLocations();
//The last location in the list is the newest
Location location = locationList.get(locationList.size() - 1);
Log.i("MapsActivity", "Location: " + location.getLatitude() + " " + location.getLongitude());
// Toast.makeText(MapsActivity.this, location.getLatitude() + " " + location.getLongitude(), Toast.LENGTH_SHORT).show();
mLastLocation = location;
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
if(c==0)
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 17));
}
};
@Override
public void onLocationChanged(Location location) {
mLastLocation = location;
//Place current location marker
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(latLng);
markerOptions.title("Current Position");
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA));
//move map camera
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 17));
}
@Override
protected void onStart() {
super.onStart();
mRequestLocationUpdatesButton = findViewById(R.id.button);
mRequestLocationUpdatesButton.setOnClickListener(view -> {
if (!checkPermissions()) {
requestPermissions();
} else {
c++;
aa.setVisibility(View.VISIBLE);
bb.setVisibility(View.VISIBLE);
if (c % 2 == 0 && c != 0) {
mRequestLocationUpdatesButton.setText("RESUME");
chronometer.stop();
pause = SystemClock.elapsedRealtime() - chronometer.getBase();
running = false;
durationTime = SystemClock.elapsedRealtime();
}
if (c % 2 != 0 || c == 1){
mRequestLocationUpdatesButton.setText("PAUSE");
chronometer.setBase(SystemClock.elapsedRealtime() - pause);
chronometer.start();
running = true;}
if (c==1) {
chronometer.setBase(SystemClock.elapsedRealtime() - pause);
chronometer.start();
running = true;
} if(c==-1) {
chronometer.stop();
pause = SystemClock.elapsedRealtime() - chronometer.getBase();
running = false;
durationTime = SystemClock.elapsedRealtime();
Toast.makeText(MapsActivity.this, "Your duration is " + chronometer.getText(), Toast.LENGTH_SHORT).show();
}
mService.requestLocationUpdates();
}
});
mRequestLocationUpdatesButton.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
c = -1;
Intent intent = new Intent(MapsActivity.this, Details.class);
intent.putExtra("dist", temp);
intent.putExtra("duration", chronometer.getText());
startActivity(intent);
return false;
}
});
bindService(new Intent(this, LocationUpdatesService.class), mServiceConnection,
Context.BIND_AUTO_CREATE);
}
@Override
protected void onResume() {
super.onResume();
LocalBroadcastManager.getInstance(this).registerReceiver(myReceiver,
new IntentFilter(LocationUpdatesService.ACTION_BROADCAST));
}
@Override
protected void onPause() {
LocalBroadcastManager.getInstance(this).unregisterReceiver(myReceiver);
super.onPause();
}
@Override
protected void onDestroy() {
Log.i("Create", "Destroy");
super.onDestroy();
}
@Override
protected void onStop() {
if (mBound) {
unbindService(mServiceConnection);
mBound = false;
}
super.onStop();
}
private class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Location location = intent.getParcelableExtra(LocationUpdatesService.EXTRA_LOCATION);
if (location != null) {
Toast.makeText(MapsActivity.this, Utils.getLocationText(location),
Toast.LENGTH_SHORT).show();
sharedPreferences = getApplicationContext().getSharedPreferences("MyPrefs", MODE_PRIVATE);
SharedPreferences.Editor edit = sharedPreferences.edit();
edit.putString("loc", String.valueOf(location.getLatitude()));
edit.putString("loc1", String.valueOf(location.getLongitude()));
edit.apply();
}
}
}
}
我的LocationUpdatesService类:
private static final String CHANNEL_ID = "channel_01";
SharedPreferences prefs;
static final String ACTION_BROADCAST = PACKAGE_NAME + ".broadcast";
static final String EXTRA_LOCATION = PACKAGE_NAME + ".location";
private static final String EXTRA_STARTED_FROM_NOTIFICATION = PACKAGE_NAME +
".started_from_notification";
private final IBinder mBinder = new LocalBinder();
private static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS =
UPDATE_INTERVAL_IN_MILLISECONDS /2;
private static final int NOTIFICATION_ID = 12345678;
private List<Double> ll;
private double pp=0.001;
private boolean mChangingConfiguration = false;
private NotificationManager mNotificationManager;
/**
* Contains parameters used by {@link com.google.android.gms.location.FusedLocationProviderApi}.
*/
private LocationRequest mLocationRequest;
/**
* Provides access to the Fused Location Provider API.
*/
private FusedLocationProviderClient mFusedLocationClient;
/**
* Callback for changes in location.
*/
private LocationCallback mLocationCallback;
private Handler mServiceHandler;
/**
* The current location.
*/
private Location mLocation;
private String gg = "0";
private String ggg = "0";
public LocationUpdatesService() {
}
@Override
public void onCreate() {
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
mLocationCallback = new LocationCallback() {
@Override
public void onLocationResult(LocationResult locationResult) {
super.onLocationResult(locationResult);
onNewLocation(locationResult.getLastLocation());
}
};
if (c%2!=0||c==0||c==1) {
createLocationRequest();
getLastLocation();
}
prefs = getApplicationContext().getSharedPreferences("MyPrefs", MODE_PRIVATE);
SharedPreferences.Editor edit = prefs.edit();
edit.putString("lat", "0");
edit.putString("lng", "0");
edit.apply();
HandlerThread handlerThread = new HandlerThread(TAG);
handlerThread.start();
mServiceHandler = new Handler(handlerThread.getLooper());
mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// Android O requires a Notification Channel.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = getString(R.string.app_name);
// Create the channel for the notification
NotificationChannel mChannel =
new NotificationChannel(CHANNEL_ID, name, NotificationManager.IMPORTANCE_DEFAULT);
// Set the Notification Channel for the Notification Manager.
mNotificationManager.createNotificationChannel(mChannel);
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "Service started");
boolean startedFromNotification = intent.getBooleanExtra(EXTRA_STARTED_FROM_NOTIFICATION,
false);
// We got here because the user decided to remove location updates from the notification.
if (startedFromNotification) {
removeLocationUpdates();
stopSelf();
}
// Tells the system to not try to recreate the service after it has been killed.
return START_NOT_STICKY;
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
mChangingConfiguration = true;
}
@Override
public IBinder onBind(Intent intent) {
// Called when a client (MainActivity in case of this sample) comes to the foreground
// and binds with this service. The service should cease to be a foreground service
// when that happens.
Log.i(TAG, "in onBind()");
stopForeground(true);
mChangingConfiguration = false;
return mBinder;
}
@Override
public void onRebind(Intent intent) {
// Called when a client (MainActivity in case of this sample) returns to the foreground
// and binds once again with this service. The service should cease to be a foreground
// service when that happens.
Log.i(TAG, "in onRebind()");
stopForeground(true);
mChangingConfiguration = false;
super.onRebind(intent);
}
@Override
public boolean onUnbind(Intent intent) {
Log.i(TAG, "Last client unbound from service");
// Called when the last client (MainActivity in case of this sample) unbinds from this
// service. If this method is called due to a configuration change in MainActivity, we
// do nothing. Otherwise, we make this service a foreground service.
if (!mChangingConfiguration && Utils.requestingLocationUpdates(this)) {
Log.i(TAG, "Starting foreground service");
startForeground(NOTIFICATION_ID, getNotification());
}
return true; // Ensures onRebind() is called when a client re-binds.
}
@Override
public void onDestroy() {
mServiceHandler.removeCallbacksAndMessages(null);
}
/**
* Makes a request for location updates. Note that in this sample we merely log the
* {@link SecurityException}.
*/
public void requestLocationUpdates() {
if(c%2==0&&c!=1)//for pause/resume. when paused we dont update the location
{
prefs = getApplicationContext().getSharedPreferences("MyPrefs", MODE_PRIVATE);
SharedPreferences.Editor edit = prefs.edit();
edit.putString("lat1", String.valueOf(0));
edit.putString("lng1", String.valueOf(0));
edit.apply();
return;
}
Log.i(TAG, "Requesting location updates");
Utils.setRequestingLocationUpdates(this, true);
startService(new Intent(getApplicationContext(), LocationUpdatesService.class));
try {
mFusedLocationClient.requestLocationUpdates(mLocationRequest,
mLocationCallback, Looper.myLooper());
} catch (SecurityException unlikely) {
Utils.setRequestingLocationUpdates(this, false);
Log.e(TAG, "Lost location permission. Could not request updates. " + unlikely);
}
}
/**
* Removes location updates. Note that in this sample we merely log the
* {@link SecurityException}.
*/
public void removeLocationUpdates() {
Log.i(TAG, "Removing location updates");
try {
mFusedLocationClient.removeLocationUpdates(mLocationCallback);
Utils.setRequestingLocationUpdates(this, false);
stopSelf();
} catch (SecurityException unlikely) {
Utils.setRequestingLocationUpdates(this, true);
Log.e(TAG, "Lost location permission. Could not remove updates. " + unlikely);
}
}
private void getLastLocation() {
try {
mFusedLocationClient.getLastLocation()
.addOnCompleteListener(new OnCompleteListener<Location>() {
@Override
public void onComplete(@NonNull Task<Location> task) {
if (task.isSuccessful() && task.getResult() != null) {
mLocation = task.getResult();
} else {
Log.w(TAG, "Failed to get locatio n.");
}
}
});
} catch (SecurityException unlikely) {
Log.e(TAG, "Lost location permission." + unlikely);
}
}
private void onNewLocation(Location location) {
if(c%2==0&&c!=1) {
prefs = getApplicationContext().getSharedPreferences("MyPrefs", MODE_PRIVATE);
SharedPreferences.Editor edit = prefs.edit();
edit.putString("lat1", String.valueOf(0));
edit.putString("lng1", String.valueOf(0));
edit.apply();
return;
}
Log.i(TAG, "New location: " + location);
mRequestLocationUpdatesButton.setText("PAUSE");
// chronometer.setBase(SystemClock.elapsedRealtime() - pause);
chronometer.start();
if(c==-1)
removeLocationUpdates();
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
mLocation = location;
double lat = 0, lng = 0;
lat=location.getLatitude();
lng=location.getLongitude();
gg = prefs.getString("lat1", null);
ggg = prefs.getString("lng1", null);
if (gg != null)
lat1 = Double.parseDouble(gg);
if (ggg != null)
lng1 = Double.parseDouble(ggg);
if (lat1 != 0 && GetDistanceFromLatLonInKm(lat1, lng1, lat, lng) > 0.001 &&MapsActivity.manager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
Log.i("Each distance", String.valueOf(GetDistanceFromLatLonInKm(lat1, lng1, lat, lng)));
kms += GetDistanceFromLatLonInKm(lat1, lng1, lat, lng);
// Toast.makeText(MapsActivity.this, "Your speed: " +'\n' + GetDistanceFromLatLonInKm(lat1, lng1, lat, lng)*3600+ '\n' +GetDistanceFromLatLonInKm(lat1, lng1, lat, lng), Toast.LENGTH_LONG).show();
durations = (String) chronometer.getText();
char dd3 = durations.charAt(durations.length() - 4);
char d1 = durations.charAt(durations.length() - 2);
char d2 = durations.charAt(durations.length() - 1);
int d3 = (int) d1 - 48;
int d4 = (int) d2 - 48;
int dd33 = (int) dd3 - 48;
//durations = d1+d2;
findur = dd33 * 60 + d3 * 10 + d4;
Log.i("lob", String.valueOf(findur));
double kms1 = abs(temp - kms);
int kmms1 = abs(findur1 - findur);
Log.i("kms = ", String.valueOf(kms1));
Log.i("temp = ", String.valueOf(temp));
Log.i("dur = ", String.valueOf(findur1));
double ff = (kms1 * 3600) / kmms1;
double kk = ff;
kk = (double) Math.round(kk * 100d) / 100d;
speed1.setText(kk + " kmph");
ArrayList<LatLng> points = new ArrayList<LatLng>();
PolylineOptions polyLineOptions = new PolylineOptions();
Log.i("poly1", lat1+" "+lng1+" "+ location.getLatitude()+" "+ location.getLongitude());
points.add(new LatLng(lat1, lng1));
points.add(new LatLng(location.getLatitude(), location.getLongitude()));
polyLineOptions.width(10);
polyLineOptions.geodesic(true);
polyLineOptions.color(R.color.colorPrimaryDark);
polyLineOptions.addAll(points);
Polyline polyline = mMap.addPolyline(polyLineOptions);
polyline.setGeodesic(true);
prefs = getApplicationContext().getSharedPreferences("MyPrefs", MODE_PRIVATE);
SharedPreferences.Editor edit = prefs.edit();
Log.i("save", location.getLatitude() + " "+location.getLongitude());
edit.putString("lat1", String.valueOf(location.getLatitude()));
edit.putString("lng1", String.valueOf(location.getLongitude()));
edit.apply();
} else {
speed1.setText(jj + " kmph");
}
kms = (double) Math.round(kms * 100000d) / 100000d;
km.setText(String.valueOf(kms));
//i = (long) kk;
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 17));
mMap.setMyLocationEnabled(true);
prefs = getApplicationContext().getSharedPreferences("MyPrefs", MODE_PRIVATE);
SharedPreferences.Editor edit = prefs.edit();
Log.i("save", location.getLatitude() + " "+location.getLongitude());
if(lng1==0) {
edit.putString("lat1", String.valueOf(location.getLatitude()));
edit.putString("lng1", String.valueOf(location.getLongitude()));
}edit.putFloat("kmm", (float) kms);
edit.putInt("kmm1", (int) findur);
edit.apply();
temp= prefs.getFloat("kmm", 0);
findur1 = prefs.getInt("kmm1", 0);
// Notify anyone listening for broadcasts about the new location.
Intent intent = new Intent(ACTION_BROADCAST);
intent.putExtra(EXTRA_LOCATION, location);
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);
// Update notification content if running as a foreground service.
if (serviceIsRunningInForeground(this)) {
mNotificationManager.notify(NOTIFICATION_ID, getNotification());
}
}
private void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
/**
* Class used for the client Binder. Since this service runs in the same process as its
* clients, we don't need to deal with IPC.
*/
public class LocalBinder extends Binder {
LocationUpdatesService getService() {
return LocationUpdatesService.this;
}
}
/**
* Returns true if this is a foreground service.
*
* @param context The {@link Context}.
*/
public boolean serviceIsRunningInForeground(Context context) {
ActivityManager manager = (ActivityManager) context.getSystemService(
Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(
Integer.MAX_VALUE)) {
if (getClass().getName().equals(service.service.getClassName())) {
if (service.foreground) {
return true;
}
}
}
return false;
}
并且我已经打算从导航抽屉中启动mapsactvity