在通过位置服务提醒

时间:2016-09-09 08:08:18

标签: java android gps android-location

我遇到问题,如果我的手机的位置服务已关闭,我想设置一个提醒,打开位置服务设置并在那里打开它。这工作正常,但问题是我打开后导航回我的应用程序。好像当我点击回来时,我的活动的onResume被调用,但在onResume完成之前,该位置仍未正确设置。这是我的代码:

Comments.java:

@Override
public void onResume() {
    super.onResume();
    locationManager = (LocationManager) getContext().getSystemService(Context.LOCATION_SERVICE);
    Location location = LocationService.getLastLocation();
    if(location == null) {
        if(getLastKnownLocation() == null) {
            if(checkLocationEnabled()); {
                location = getLastKnownLocation();
            }
        }
    }

    if(location != null) {
        progressOverlay = fragmentView.findViewById(R.id.progress_overlay);
        AndroidUtils.animateView(progressOverlay, View.VISIBLE, 0.9f, 200);
        //Within this function call, the progress overlay is set to View.GONE.
        databaseQuery.getPublicPosts(location, progressOverlay, fragmentView, getContext());
    } else {
        //We need to handle an error saying that location is not enabled for this device and exit them out of the app
    }
}

private Location getLastKnownLocation() {
    locationManager = (LocationManager) getContext().getSystemService(Context.LOCATION_SERVICE);
    List<String> providers = locationManager.getProviders(true);
    Location bestLocation = null;
    for (String provider : providers) {
        if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {

            return null;
        } else {
            Location l = locationManager.getLastKnownLocation(provider);
            if (bestLocation == null || l.getAccuracy() < bestLocation.getAccuracy()) {
                // Found best last known location: %s", l);
                bestLocation = l;
            }
        }
    }

    return bestLocation;
}

public boolean checkLocationEnabled() {
    try {
        gps_enabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
    } catch(Exception ex) {
    }
    try {
        network_enabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
    } catch(Exception ex) {

    }
    if(!gps_enabled && !network_enabled) {
        // notify user
        AlertDialog.Builder dialog = new AlertDialog.Builder(getContext());
        dialog.setMessage(getContext().getResources().getString(R.string.gpsNetworkNotEnabled));
        dialog.setPositiveButton(getContext().getResources().getString(R.string.openLocationSettings), new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface paramDialogInterface, int paramInt) {
                Intent myIntent = new Intent( Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                getContext().startActivity(myIntent);
                //get gps
            }
        });
        dialog.setNegativeButton(getContext().getString(R.string.cancel), new DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface paramDialogInterface, int paramInt) {

            }
        });
        dialog.show();
    }
    return gps_enabled || network_enabled;
}

我所做的是当电话位置服务关闭时,我设置了一个警报,将您带到位置服务屏幕。当用户打开位置服务屏幕时,如果他或她点击他或她的电话上的“后退”,则应将他们带回到初始屏幕,该屏幕显示他们的位置服务处于警戒状态。但是,当导航回该屏幕时,我的progressOverlay变量仍然可见,因为当progressOverlay来电时,View.GONE设置为databaseQuery.getPublicPosts。这似乎不会发生,因为当我们导航回屏幕时if(location != null)语句可能是错误的,但是在电话等待几秒钟并完全获得电话位置后可能设置为true。这很有意思,因为如果我将调试器放在该代码的任何位置,那么位置服务将被正确设置,我的progressOverlay将会消失,因为在调试代码时该位置已设置。在调用databaseQuery.getPublicPosts之前,有没有办法可以“等待”或继续显示加载屏幕,直到位置服务完全打开?任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:1)

首先,if(checkLocationEnabled());中有一个不需要的分号,它作为一个空语句,导致第二次调用getLastKnownLocation()始终执行(这很可能不会影响问题)。

LocationManager类有一个常量KEY_STATUS_CHANGED,它是广播状态更改时传递的附加包的关键。请参阅与常量相关的文档。要触发此更改,您需要调用[LocationManager.requestLocationUpdates](https://developer.android.com/reference/android/location/LocationManager.html#requestLocationUpdates(long,float,android.location.Criteria,android.app.PendingIntent)),以便位置管理器收到此类状态更新。

从此方法的文档中,您可以使用BroadcastReceiver通过过滤上述常量来接收更新。 Here是执行此操作的相关帖子。或者,您可以使用另一个重载版本的请求更新方法,该方法会LocationListener进行onStatusChanged回调。

使用KEY_PROVIDER_ENABLED启用位置提供程序时,存在类似的更新。如果状态更新不起作用,您可以尝试侦听这两个更新。

请注意,在为提供商请求位置更新时,为了包括所有提供商的更新(包括已禁用),您应该使用LocationManager.getProviders(false)检索它们。

收到相应的更新事件后,您可以致电removeUpdates删除更新请求。

答案 1 :(得分:1)

为什么要尝试使用 getLastKnownLocation 。它会返回您之前的纬度和经度,并且可能需要一些时间来更新上次知道的位置。 很可能它会在您所在位置后退回null。

我只是引用你 google Fused api 获取任何类型的更新或当前位置。它非常准确。

如何在项目中融合api。请参阅我的小例子。

步骤1.将此类设为GoogleLocationService.java

public class GoogleLocationService {
private GoogleServicesCallbacks callbacks = new GoogleServicesCallbacks();
LocationUpdateListener locationUpdateListener;
Context activity;
protected GoogleApiClient mGoogleApiClient;
protected LocationRequest mLocationRequest;

public static final long UPDATE_INTERVAL_IN_MILLISECONDS = 30000;


public GoogleLocationService(Context activity, LocationUpdateListener locationUpdateListener) {
    this.locationUpdateListener = locationUpdateListener;
    this.activity = activity;
    buildGoogleApiClient();
}

protected synchronized void buildGoogleApiClient() {
    //Log.i(TAG, "Building GoogleApiClient");
    mGoogleApiClient = new GoogleApiClient.Builder(activity)
            .addConnectionCallbacks(callbacks)
            .addOnConnectionFailedListener(callbacks)
            .addApi(LocationServices.API)
            .build();
    createLocationRequest();
    mGoogleApiClient.connect();
}

protected void createLocationRequest() {
    mLocationRequest = new LocationRequest();
    mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

}

private class GoogleServicesCallbacks implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {

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

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

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

        if (connectionResult.getErrorCode() == ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED) {
            Toast.makeText(activity, "Google play service not updated", Toast.LENGTH_LONG).show();

        }
        locationUpdateListener.cannotReceiveLocationUpdates();
    }

    @Override
    public void onLocationChanged(Location location) {
        if (location.hasAccuracy()) {
            if (location.getAccuracy() < 30) {
                locationUpdateListener.updateLocation(location);
            }
        }
    }
}

private static boolean locationEnabled(Context context) {
    boolean gps_enabled = false;
    LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
    try {
        gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
    } catch (Exception ex) {
        ex.printStackTrace();
    }
    return gps_enabled;
}

private boolean servicesConnected(Context context) {
    return isPackageInstalled(GooglePlayServicesUtil.GOOGLE_PLAY_STORE_PACKAGE, context);
}

private boolean isPackageInstalled(String packagename, Context context) {
    PackageManager pm = context.getPackageManager();
    try {
        pm.getPackageInfo(packagename, PackageManager.GET_ACTIVITIES);
        return true;
    } catch (PackageManager.NameNotFoundException e) {
        e.printStackTrace();
        return false;
    }
}


public void startUpdates() {
    /*
     * Connect the client. Don't re-start any requests here; instead, wait
     * for onResume()
     */
    if (servicesConnected(activity)) {
        if (locationEnabled(activity)) {
            locationUpdateListener.canReceiveLocationUpdates();
            startLocationUpdates();
        } else {
            locationUpdateListener.cannotReceiveLocationUpdates();
            Toast.makeText(activity, "Unable to get your location.Please turn on your device Gps", Toast.LENGTH_LONG).show();
        }
    } else {
        locationUpdateListener.cannotReceiveLocationUpdates();
        Toast.makeText(activity, "Google play service not available", Toast.LENGTH_LONG).show();
    }
}

//stop location updates
public void stopUpdates() {
    stopLocationUpdates();
}

//start location updates
private void startLocationUpdates() {

    if (checkSelfPermission(activity, ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && checkSelfPermission(activity, ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        return;
    }
    if (mGoogleApiClient.isConnected()) {
        LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, callbacks);
    }
}

public void stopLocationUpdates() {
    if (mGoogleApiClient.isConnected()) {
        LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, callbacks);
    }
}

public void startGoogleApi() {
    mGoogleApiClient.connect();
}

public void closeGoogleApi() {
    mGoogleApiClient.disconnect();
}

 }

<强>第二步。制作这个界面 LocationUpdateListener.java

 public interface LocationUpdateListener {

/**
 * Called immediately the service starts if the service can obtain location
 */
void canReceiveLocationUpdates();

/**
 * Called immediately the service tries to start if it cannot obtain location - eg the user has disabled wireless and
 */
void cannotReceiveLocationUpdates();

/**
 * Called whenever the location has changed (at least non-trivially)
 * @param location
 */
void updateLocation(Location location);

/**
 * Called when GoogleLocationServices detects that the device has moved to a new location.
 * @param localityName The name of the locality (somewhere below street but above area).
 */
void updateLocationName(String localityName, Location location);
}

步骤3.在想要获取位置的地方使用这段代码

public class MainActivity extends ActionBarActivity {

private GoogleLocationService googleLocationService;

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

    googleLocationService = new GoogleLocationService(context, new LocationUpdateListener() {
    @Override
    public void canReceiveLocationUpdates() {
    }

    @Override
    public void cannotReceiveLocationUpdates() {
    }

    //update location to our servers for tracking purpose
    @Override
    public void updateLocation(Location location) {
        if (location != null ) {
            Timber.e("updated location %1$s %2$s", location.getLatitude(), location.getLongitude());

        }
    }

    @Override
    public void updateLocationName(String localityName, Location location) {

        googleLocationService.stopLocationUpdates();
    }
});
googleLocationService.startUpdates();


}

@Override
public void onDestroy() {
    super.onDestroy();
if (googleLocationService != null) {
    googleLocationService.stopLocationUpdates();
}

}
}

更新回答 如何通过广播发送和接收lat lng

称之为onlocationchanged

Intent sendBroadIntentPND = new Intent("COORD_BROADCAST_FILTER");
                    sendBroadIntentPND.putExtra("LOC_LAT", location.getLatitude());
sendBroadIntentPND.putExtra("LOC_LON", location.getLongitude());
getApplicationContext().sendBroadcast(sendBroadIntentPND);

然后你想以这种方式接收位置调用

// declear global variable
private final String COORD_BROADCAST_FILTER = "COORD_BROADCAST_FILTER";
private Location newLocation;

private BroadcastReceiver coordinateReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
try {
            newLocation.setLatitude(intent.getDoubleExtra("LOC_LAT", 0.0));
            newLocation.setLongitude(intent.getDoubleExtra("LOC_LON", 0.0));
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

 };

注册接收者oncreate,

 getActivity().registerReceiver(coordinateReceiver, new IntentFilter(COORD_BROADCAST_FILTER));

取消注册您的接收器ondestroy

 getActivity().unregisterReceiver(coordinateReceiver);

谢谢希望这对你有所帮助。

答案 2 :(得分:0)

请注意

  

Google Play服务位置API优于Android   框架位置API(android.location)作为添加位置的一种方式   了解您的应用。如果您目前正在使用Android   框架位置API,强烈建议您切换到   Google Play尽快提供服务位置API。