如何制作服务(即LocationService)并获取设备的当前位置?

时间:2019-06-08 14:42:36

标签: android location

我想提供一项服务,该服务将提供用户的当前位置和位置更新,并且这些位置更新还应该更新mapFragment。

我尝试了所有这些方法: https://developer.android.com/training/location/receive-location-updates

Best way to get user GPS location in background in Android也是

Get GPS location via a service in Android

我知道如何使用融合位置API获取位置更新,但是我对使用服务有些困惑。我是android新手,不知道如何在android中提供用户服务。任何帮助将不胜感激。

MapsActivity.java

public class MapsActivity extends AppCompatActivity implements OnMapReadyCallback,
    GoogleApiClient.ConnectionCallbacks,
    GoogleApiClient.OnConnectionFailedListener,
    LocationListener{

/** Variables declared here .............. */

 @Override
 protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_maps);
    // Obtain the SupportMapFragment and get notified when the map is ready to be used.
    SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
            .findFragmentById(R.id.map);
    mapFragment.getMapAsync(this);

 //First method called for setting up location
    setUpLocation();

}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

    switch (requestCode) {

        case PERMISSION_REQUEST_CODE:
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                if (checkPlayServices()) {

                    buildGoogleApiClient();
                    createLocationRequest();
                    displayLocation();

                }
            }
            break;
    }
}

private void setUpLocation() {
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
            ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        requestRuntimePermission();
    } else {
        if (checkPlayServices()) {
            buildGoogleApiClient();
            createLocationRequest();
            displayLocation();
        }
    }
}

public void displayLocation() {

    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
            ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        return;
    }
    mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);

    if (mLastLocation != null) {
        lattitude = mLastLocation.getLatitude();
        longitude = mLastLocation.getLongitude();


        mMap.clear();
        mCurrentMarker= mMap.addMarker(new MarkerOptions()
                .position(new LatLng(lattitude, longitude))
                .title("You"));
        mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(lattitude, longitude), 12.02f));
    }

}

private void createLocationRequest() {

    if (mGoogleApiClient == null) {
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addApi(LocationServices.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this).build();
        mGoogleApiClient.connect();
    }

    mLocationRequest = new LocationRequest();
    mLocationRequest.setInterval(UPDATE_INTERVAL);
    mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    mLocationRequest.setSmallestDisplacement(DISPLACEMENT);

    // Prompt to set location enabled in settings is described here

    LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
            .addLocationRequest(mLocationRequest);

    builder.setAlwaysShow(true); //this is the key ingredient **Very important**

    PendingResult<LocationSettingsResult> result =
            LocationServices.SettingsApi.checkLocationSettings(mGoogleApiClient, builder.build());
    result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
        @Override
        public void onResult(LocationSettingsResult result) {
            final Status status = result.getStatus();
            final LocationSettingsStates state = result.getLocationSettingsStates();
            switch (status.getStatusCode()) {
                case LocationSettingsStatusCodes.SUCCESS:
                    // All location settings are satisfied. The client can initialize location
                    // requests here.
                    break;
                case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                    // Location settings are not satisfied. But could be fixed by showing the user
                    // a dialog.
                    try {
                        // Show the dialog by calling startResolutionForResult(),
                        // and check the result in onActivityResult().
                        status.startResolutionForResult(MapsActivity.this, REQUEST_CHECK_SETTINGS);
                    } catch (IntentSender.SendIntentException e) {
                        // Ignore the error.
                    }
                    break;
                case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
                    // Location settings are not satisfied. However, we have no way to fix the
                    // settings so we won't show the dialog.
                    break;
            }
        }
    });
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
        // Check for the integer request code originally supplied to startResolutionForResult().
        case REQUEST_CHECK_SETTINGS:
            switch (resultCode) {
                case Activity.RESULT_OK:
                    startLocationUpdates();
                    break;
                case Activity.RESULT_CANCELED:
                    createLocationRequest();//keep asking if imp or do whatever
                    break;
            }
            break;
    }
}

protected synchronized void buildGoogleApiClient() {

    mGoogleApiClient = new GoogleApiClient.Builder(this)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .addApi(LocationServices.API)
            .build();
    mGoogleApiClient.connect();

}

private boolean checkPlayServices() {

    int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
    if (resultCode != ConnectionResult.SUCCESS) {
        if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {

            GooglePlayServicesUtil.getErrorDialog(resultCode, this, PLAY_SERVICES_REQUEST_CODE).show();

        } else {

            Toast.makeText(this, "This device is not supported", Toast.LENGTH_SHORT).show();
            finish();

        }
        return false;
    }
    return true;

}

private void requestRuntimePermission() {

    ActivityCompat.requestPermissions(this, new String[]{
            Manifest.permission.ACCESS_COARSE_LOCATION,
            Manifest.permission.ACCESS_FINE_LOCATION
    }, PERMISSION_REQUEST_CODE);

}

private void startLocationUpdates() {

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

    LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}

@Override
public void onMapReady(GoogleMap googleMap) {
    mMap = googleMap;

    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        // here to request the missing permissions, and then overriding
        //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
        //                                          int[] grantResults)
        // to handle the case where the user grants the permission.
        return;
    }
    mMap.setMyLocationEnabled(true);
    mMap.getUiSettings().setMyLocationButtonEnabled(true);
    mMap.getUiSettings().setMapToolbarEnabled(false);

}

@Override
public void onConnected(@Nullable Bundle bundle) {
    displayLocation();
    startLocationUpdates();
}

@Override
public void onConnectionSuspended(int i) {
    mGoogleApiClient.connect();
}

@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
}

@Override
public void onLocationChanged(Location location) {

    mLastLocation = location;
    displayLocation();
}

MapsActivity.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">

    <android.support.v4.widget.DrawerLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/drawerLayout"
        android:layout_below="@+id/appBarLayout">

        <fragment xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools"
            android:id="@+id/map"
            android:name="com.google.android.gms.maps.SupportMapFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            tools:context=".MapsActivity"
            tools:ignore="NotSibling" >

        </fragment>

    </android.support.v4.widget.DrawerLayout>

</RelativeLayout>

1 个答案:

答案 0 :(得分:0)

您可以像这样实现LocationService:

1)。首先,您必须创建一个Java类(例如locationService.java)并扩展Service。

public class LocationService extends Service implements LocationListener,
    GoogleApiClient.ConnectionCallbacks,
    GoogleApiClient.OnConnectionFailedListener

2)。然后它将给您错误的实现方法,只需按alt + enter并实现这些方法即可。

3)。有一种方法onStartCommand在创建服务时首先被调用。您必须在setUplocation中调用onStartCommand方法。

4)。现在,在onLocationChanged方法中,您可以像这样使用最广泛的接收方发送纬度和经度:

@Override
public void onLocationChanged(Location location) {
...
sendMessageToUI(String.valueOf(location.getLatitude()), String.valueOf(location.getLongitude()));
...
}

 private void sendMessageToUI(String lat, String lng) {


    Intent intent = new Intent(ACTION_LOCATION_BROADCAST);
    intent.putExtra(EXTRA_LATITUDE, lat);
    intent.putExtra(EXTRA_LONGITUDE, lng);
    LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}

5)。现在,您必须像这样在onCreate中注册此服务:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    LocalBroadcastManager.getInstance(this).registerReceiver(
        new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {

            }
    }, new IntentFilter(LocationServicesForLocationUpdates.ACTION_LOCATION_BROADCAST));

}

onRecieve方法中,您可以从intent.getStringExtras中获取latlng值

希望,这将帮助您解决问题。祝你好运!