我想在距离最后知道位置10公里处检查我的服务地点。这是否可以不要求所有时间当前位置? (因为现在app每次都试图获取当前位置)。如果是,那怎么样?我的所有位置代码几乎等于Best way to get user GPS location in background in Android应答代码,该代码在主要活动中开始使用
答案 0 :(得分:0)
尝试将Service类更改为IntentService
另外,我使用BroadcastReceiver每隔10秒提供一次演示当前位置更新的演示。 同样在本演示中,我在位置更新时使用了通知显示。
如下面的代码。
public class LocationUpdatesBroadcastReceiver extends BroadcastReceiver {
private static final String TAG = "LUBroadcastReceiver";
public static final String ACTION_PROCESS_UPDATES =
"com.google.android.gms.location.sample.backgroundlocationupdates.action" +
".PROCESS_UPDATES";
@Override
public void onReceive(Context context, Intent intent) {
if (intent != null) {
final String action = intent.getAction();
if (ACTION_PROCESS_UPDATES.equals(action)) {
LocationResult result = LocationResult.extractResult(intent);
if (result != null) {
List<Location> locations = result.getLocations();
LocationResultHelper locationResultHelper = new LocationResultHelper(
context, locations);
// Save the location data to SharedPreferences.
locationResultHelper.saveResults();
// Show notification with the location data.
locationResultHelper.showNotification();
Log.i(TAG, LocationResultHelper.getSavedLocationResult(context));
}
}
}
}
}
然后第二类如下。在此代码中显示通道因为在Android 8.0中运行
/**
*此类用于显示通知并将位置数据存储到共享首选项中。 * /
公共类LocationResultHelper {
final public static String KEY_LOCATION_UPDATES_RESULT = "location- update-result";
final private static String PRIMARY_CHANNEL = "default";
private Context mContext;
private List<Location> mLocations;
private NotificationManager mNotificationManager;
/**
* this constructor used to initialised this class.
* @param context
* @param locations
*/
public LocationResultHelper(Context context, List<Location> locations) {
mContext = context;
mLocations = locations;
NotificationChannel channel = new NotificationChannel(PRIMARY_CHANNEL,
context.getString(R.string.default_channel), NotificationManager.IMPORTANCE_DEFAULT);
channel.setLightColor(Color.GREEN);
channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
getNotificationManager().createNotificationChannel(channel);
}
/**
* this method used to report location with date and time.
*/
private String getLocationResultTitle() {
String numLocationsReported = mContext.getResources().getQuantityString(
R.plurals.num_locations_reported, mLocations.size(), mLocations.size());
return numLocationsReported + ": " + DateFormat.getDateTimeInstance().format(new Date());
}
/**
* this method used to give location data.
* @return
*/
private String getLocationResultText() {
if (mLocations.isEmpty()) {
return mContext.getString(R.string.unknown_location);
}
StringBuilder sb = new StringBuilder();
for (Location location : mLocations) {
sb.append("(");
sb.append(location.getLatitude());
sb.append(", ");
sb.append(location.getLongitude());
sb.append(")");
sb.append("\n");
}
return sb.toString();
}
/**
* this method save data into shared preferences.
*/
public void saveResults() {
PreferenceManager.getDefaultSharedPreferences(mContext)
.edit()
.putString(KEY_LOCATION_UPDATES_RESULT, getLocationResultTitle() + "\n" +
getLocationResultText())
.apply();
}
/**
* this method get shared preferences store location update.
*/
public static String getSavedLocationResult(Context context) {
return PreferenceManager.getDefaultSharedPreferences(context)
.getString(KEY_LOCATION_UPDATES_RESULT, "");
}
/**
* Get the notification mNotificationManager.
* <p>
* Utility method as this helper works with it a lot.
*
* @return The system service NotificationManager
*/
private NotificationManager getNotificationManager() {
if (mNotificationManager == null) {
mNotificationManager = (NotificationManager) mContext.getSystemService(
Context.NOTIFICATION_SERVICE);
}
return mNotificationManager;
}
/**
* Displays a notification with the location results.
*/
public void showNotification(){ Intent notificationIntent = new Intent(mContext,MainActivity.class);
// Construct a task stack.
TaskStackBuilder stackBuilder = TaskStackBuilder.create(mContext);
// Add the main Activity to the task stack as the parent.
stackBuilder.addParentStack(MainActivity.class);
// Push the content Intent onto the stack.
stackBuilder.addNextIntent(notificationIntent);
// Get a PendingIntent containing the entire back stack.
PendingIntent notificationPendingIntent =
stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
Notification.Builder notificationBuilder = new Notification.Builder(mContext,
PRIMARY_CHANNEL)
.setContentTitle(getLocationResultTitle())
.setContentText(getLocationResultText())
.setSmallIcon(R.drawable.common_google_signin_btn_icon_dark)
.setAutoCancel(true)
.setContentIntent(notificationPendingIntent);
getNotificationManager().notify(0, notificationBuilder.build());
}
}
然后为请求位置数据制作第三类
/ ** *此类使用为请求进行位置更新而选择的保存用户并删除位置更新。 * /
public class LocationRequestHelper {
final static public String KEY_LOCATION_UPDATES_REQUESTED = "location-updates-requested";
public static void setRequesting(Context context, boolean value) {
PreferenceManager.getDefaultSharedPreferences(context)
.edit()
.putBoolean(KEY_LOCATION_UPDATES_REQUESTED, value)
.apply();
}
public static boolean getRequesting(Context context) {
return PreferenceManager.getDefaultSharedPreferences(context)
.getBoolean(KEY_LOCATION_UPDATES_REQUESTED, false);
}
}
然后在进行主要活动并实施所有事情之后。public class MainActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
SharedPreferences.OnSharedPreferenceChangeListener {
private static final String TAG = MainActivity.class.getSimpleName();
private static final int REQUEST_PERMISSIONS_REQUEST_CODE = 34;
/**
* The used for interval for location updates.
*/
private static final long UPDATE_INTERVAL = 10 * 1000;
/**
* The fastest interval to update for active location updates.
*/
private static final long FASTEST_UPDATE_INTERVAL = UPDATE_INTERVAL / 2;
/**
* The max time to wait for location update.
*/
private static final long MAX_WAIT_TIME = UPDATE_INTERVAL * 3;
/**
* Stores parameters for requests to the FusedLocationProviderApi.
*/
private LocationRequest mLocationRequest;
/**
* The entry point to Google Play Services.
*/
private GoogleApiClient mGoogleApiClient;
private Button mRequestUpdatesButton;
private Button mRemoveUpdatesButton;
private TextView mLocationUpdatesResultView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
/**
* this method initialized view control.
*/
private void initView() {
mRequestUpdatesButton = (Button) findViewById(R.id.request_updates_button);
mRemoveUpdatesButton = (Button) findViewById(R.id.remove_updates_button);
mLocationUpdatesResultView = (TextView) findViewById(R.id.location_updates_result);
// Check if the user revoked runtime permissions.
if (!checkPermissions()) {
requestPermissions();
}
buildGoogleApiClient();
}
@Override
protected void onStart() {
super.onStart();
PreferenceManager.getDefaultSharedPreferences(this)
.registerOnSharedPreferenceChangeListener(this);
}
@Override
protected void onResume() {
super.onResume();
updateButtonsState(LocationRequestHelper.getRequesting(this));
mLocationUpdatesResultView.setText(LocationResultHelper.getSavedLocationResult(this));
}
@Override
protected void onStop() {
PreferenceManager.getDefaultSharedPreferences(this)
.unregisterOnSharedPreferenceChangeListener(this);
super.onStop();
}
/**
* this method used to location data update settings.
*/
private void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL);
// Sets the fastest rate for active location updates. This interval is exact, and your
// application will never receive updates faster than this value.
mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
// Sets the maximum time when batched location updates are delivered. Updates may be
// delivered sooner than this interval.
mLocationRequest.setMaxWaitTime(MAX_WAIT_TIME);
}
/**
* this method used to invoke google location service.
*/
private void buildGoogleApiClient() {
if (mGoogleApiClient != null) {
return;
}
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.enableAutoManage(this, this)
.addApi(LocationServices.API)
.build();
createLocationRequest();
}
@Override
public void onConnected(@Nullable Bundle bundle) {
Log.i(TAG, "GoogleApiClient connected");
}
/**
* this method call particular class or services
* if you used intent service then pass intent in class name LocationUpdatesIntentService
*if you used Broadcast service then pass intent in class name LocationUpdatesBroadcastReceiver
* @return
*/
private PendingIntent getPendingIntent() {
Intent intent = new Intent(this, LocationUpdatesBroadcastReceiver.class);
intent.setAction(LocationUpdatesBroadcastReceiver.ACTION_PROCESS_UPDATES);
return PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
@Override
public void onConnectionSuspended(int i) {
final String text = "Connection suspended";
Log.w(TAG, text + ": Error code: " + i);
showSnackbar("Connection suspended");
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
final String text = "Exception while connecting to Google Play services";
Log.w(TAG, text + ": " + connectionResult.getErrorMessage());
showSnackbar(text);
}
/**
* this method show snack bar notification.
*/
private void showSnackbar(final String text) {
View container = findViewById(R.id.activity_main);
if (container != null) {
Snackbar.make(container, text, Snackbar.LENGTH_LONG).show();
}
}
/**
* this method check permission and return current state of permission need.
*/
private boolean checkPermissions() {
int permissionState = ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION);
return permissionState == PackageManager.PERMISSION_GRANTED;
}
/**
* this method request to permission asked.
*/
private void requestPermissions() {
boolean shouldProvideRationale =
ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.ACCESS_FINE_LOCATION);
if (shouldProvideRationale) {
Log.i(TAG, "Displaying permission rationale to provide additional context.");
Snackbar.make(
findViewById(R.id.activity_main),
R.string.permission_rationale,
Snackbar.LENGTH_INDEFINITE)
.setAction(R.string.ok, new View.OnClickListener() {
@Override
public void onClick(View view) {
// Request permission
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
REQUEST_PERMISSIONS_REQUEST_CODE);
}
})
.show();
} else {
Log.i(TAG, "Requesting permission");
// previously and checked "Never ask again".
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
REQUEST_PERMISSIONS_REQUEST_CODE);
}
}
/**
* Callback received when a permissions request has been completed.
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
Log.i(TAG, "onRequestPermissionResult");
if (requestCode == REQUEST_PERMISSIONS_REQUEST_CODE) {
if (grantResults.length <= 0) {
// If user interaction was interrupted, the permission request is cancelled and you
// receive empty arrays.
Log.i(TAG, "User interaction was cancelled.");
} else if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Permission was granted. Kick off the process of building and connecting
// GoogleApiClient.
buildGoogleApiClient();
} else {
// Permission denied.
Snackbar.make(
findViewById(R.id.activity_main),
R.string.permission_denied_explanation,
Snackbar.LENGTH_INDEFINITE)
.setAction(R.string.settings, new View.OnClickListener() {
@Override
public void onClick(View view) {
// Build intent that displays the App settings screen.
Intent intent = new Intent();
intent.setAction(
Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package",
BuildConfig.APPLICATION_ID, null);
intent.setData(uri);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
})
.show();
}
}
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String s) {
if (s.equals(LocationResultHelper.KEY_LOCATION_UPDATES_RESULT)) {
mLocationUpdatesResultView.setText(LocationResultHelper.getSavedLocationResult(this));
} else if (s.equals(LocationRequestHelper.KEY_LOCATION_UPDATES_REQUESTED)) {
updateButtonsState(LocationRequestHelper.getRequesting(this));
}
}
/**
* Handles the Request Updates button and requests start of location updates also disable button after selected.
*/
public void requestLocationUpdates(View view) {
try {
Log.i(TAG, "Starting location updates");
LocationRequestHelper.setRequesting(this, true);
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, getPendingIntent());
} catch (SecurityException e) {
LocationRequestHelper.setRequesting(this, false);
e.printStackTrace();
}
}
/**
* Handles the Remove Updates button, and requests removal of location updates also disable button after selected.
*/
public void removeLocationUpdates(View view) {
Log.i(TAG, "Removing location updates");
LocationRequestHelper.setRequesting(this, false);
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient,
getPendingIntent());
}
/**
* maintain button state is selected or not if selected then show disable.
*/
private void updateButtonsState(boolean requestingLocationUpdates) {
if (requestingLocationUpdates) {
mRequestUpdatesButton.setEnabled(false);
mRemoveUpdatesButton.setEnabled(true);
} else {
mRequestUpdatesButton.setEnabled(true);
mRemoveUpdatesButton.setEnabled(false);
}
}
}
然后将boradcast接收器添加到应用程序标签之间的android清单文件中。
<receiver
android:name=".notification.LocationUpdatesBroadcastReceiver"
android:exported="true">
<intent-filter>
<action android:name=".notification.LocationUpdatesBroadcastReceiver.ACTION_PROCESS_UPDATES" />
</intent-filter>
</receiver>
在这个演示中使用了两个按钮,它通过在LocationRequestHelper中定义布尔值来启用或禁用mange。
您需要参考以下链接的更多信息.. https://codelabs.developers.google.com/codelabs/background-location-updates-android-o/index.html?index=..%2F..%2Findex#0
答案 1 :(得分:0)
不确定距离,但您可以使用定期工作的JobScheduler(最多15分钟)
否则您可以使用ForegroundService一直获取位置。
Android Oreo将不允许长时间运行后台服务。