我怎样才能像谷歌地图一样在Android中获得连续的位置更新?
我正在构建一个朋友追踪android应用程序。当我的朋友启动了应用程序,带着他的GPS和手机数据离开时,我需要在我的设备上跟踪他。这就是概念 我已经实现了LocationListener类,现在我可以从Gps或网络获取最后更新的位置,但除非启动Google Maps并返回到我的应用程序,否则不会更新。在谷歌搜索之后,我了解到位置缓存只由GMAP更新我怎样才能像谷歌地图一样在Android中获得连续的位置更新?,android,gps,location,Android,Gps,Location,我正在构建一个朋友追踪android应用程序。当我的朋友启动了应用程序,带着他的GPS和手机数据离开时,我需要在我的设备上跟踪他。这就是概念 我已经实现了LocationListener类,现在我可以从Gps或网络获取最后更新的位置,但除非启动Google Maps并返回到我的应用程序,否则不会更新。在谷歌搜索之后,我了解到位置缓存只由GMAP更新 是否有其他方法可以持续更新位置 如果在设备锁定后,我需要在不使用Wakelock的情况下获取连续位置,该怎么办 这是我的位置侦听器类: packag
package com.amazinginside;
/** AMAZING LOCATION SUPPORT CLASS, Devoloped By SANGEETH NANDAKUMAR */
import android.app.AlertDialog;
import android.app.Service;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.Settings;
public class AmazingLocation extends Service implements LocationListener
{
private final Context mContext;
boolean isGPSEnabled = false;
boolean isNetworkEnabled = false;
boolean canGetLocation = false;
Location location;
double latitude=0.0;
double longitude=0.0;
//MINIMUM DISTANCE FOR UPDATE (meters)
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 0; // 0 Meters
//MINIMUM TIME BETWEEN UPDATES
private static final long MIN_TIME_BW_UPDATES = 1000 * 0; // 0 Seconds
//LOCATION MANAGER
protected LocationManager locationManager;
//CONSTRUCTOR
public AmazingLocation(Context context)
{
this.mContext = context;
getLocation();
}
//LOCATION PROVISION
public Location getLocation()
{
try
{
//GET LOCATION MANAGER
locationManager = (LocationManager) mContext.getSystemService(LOCATION_SERVICE);
//CHECK GPS STATE
isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
//CHECK NETWORK STATE
isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (!isGPSEnabled && !isNetworkEnabled)
{
//NO LOCATION PROVIDERS
}
else
{
this.canGetLocation = true;
/** GET LOCATION FROM NETWORK */
//FIRST GET LOCATION FROM NETWORK
if (isNetworkEnabled)
{
//REQUEST LOCATION
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
if (locationManager != null)
{
//START WITH LAST KNOWN LOCATION
location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
//EXTRACT LOCATION
if (location != null)
{
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
/** GET LOCATION FROM GPS SENSOR */
//THEN GET LOCATION FROM GPS
if (isGPSEnabled)
{
if (location == null)
{
//REQUEST GPS LOCATION
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
if (locationManager != null)
{
//EXTRACT LAST KNOWN LOCATION
location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
//RETURN LOCATION
if (location != null)
{
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
return location;
}
//STOP GPS SENSOR
public void stopUsingGPS()
{
if(locationManager != null)
{
locationManager.removeUpdates(AmazingLocation.this);
}
}
//EXTRACT LATTITUDE
public double getLatitude()
{
if(location != null)
{
latitude = location.getLatitude();
}
// return latitude
return latitude;
}
//EXTACT LONGITUDE
public double getLongitude()
{
if(location != null)
{
longitude = location.getLongitude();
}
// return longitude
return longitude;
}
//CAN I GET THE LOCATION.?
public AmazingStatus canGetLocation()
{
AmazingStatus status=new AmazingStatus();
if(this.canGetLocation)
{
status.setStatus(true);
status.setErrorcode(0);
status.setErrormsg("Task completed");
}
else
{
status.setStatus(false);
status.setErrorcode(145);
status.setErrormsg("Please turn on GPS access manually");
}
return status;
}
//SHOW LOCATION SETTINGS
public AmazingStatus showSettingsAlert()
{
final AmazingStatus status=new AmazingStatus();
AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);
alertDialog.setTitle("REQUIRES LOCATION ACCESS");
alertDialog.setMessage("Please allow GPS access to this app");
//POSSITIVE REPLY
alertDialog.setPositiveButton("Allow", new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog,int which)
{
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
mContext.startActivity(intent);
status.setStatus(true);
status.setErrorcode(0);
status.setErrormsg("Task completed");
}
});
//NEGATIVE REPLY
alertDialog.setNegativeButton("Deny", new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int which)
{
status.setStatus(false);
status.setErrorcode(408);
status.setErrormsg("User denied permission");
dialog.cancel();
}
});
// Showing Alert Message
alertDialog.show();
return status;
}
//UNUSED OVERRIDE METHORDS...
@Override
public void onLocationChanged(Location location)
{
getLocation();
}
@Override
public void onProviderDisabled(String provider)
{
}
@Override
public void onProviderEnabled(String provider)
{
getLocation();
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras)
{
getLocation();
}
@Override
public IBinder onBind(Intent arg0)
{
return null;
}
}
这是我的onCreate()
方法:
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//CREATE A BUTTON HANDLER
Button start_btn=(Button)findViewById(R.id.start_location_streaming);
//ON BUTTON CLICK EVENT
start_btn.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
//REPEAT A METHORD AT SPECIFIC INTERVALS
Timer myTimer = new Timer();
myTimer.schedule(new TimerTask()
{
@Override
public void run()
{
TimerMethod();
}
}, 0, 8000);
}
}); }
以下是其他方法:
private void TimerMethod()
{
//START METHORD
this.runOnUiThread(Timer_Tick);
}
//LOCATION REPORTING METHORD
private Runnable Timer_Tick = new Runnable()
{
public void run()
{
Toast.makeText(MainActivity.this, "Current latitude : "+Double.toString(getLocation().latitude), Toast.LENGTH_SHORT).show();
Toast.makeText(MainActivity.this, "Current longitude : "+Double.toString(getLocation().longitude), Toast.LENGTH_SHORT).show();
}
};
private LatLng getLocation()
{
//CREATE A LOCATION CLASS INSTANCE
AmazingLocation gps = new AmazingLocation(this);
//RETRIVE LOCATION
double latitude = gps.getLatitude();
double longitude = gps.getLongitude();
//RETURN LOCATION
LatLng loc=new LatLng(latitude,longitude);
return loc;
}
现在的问题是,toast只显示以前已知的位置,除非我打开谷歌地图并返回,否则不会更新
任何帮助对我都是非常好的。你应该使用android服务,而不是应用程序本身。通过这种方式,您将实现在后台连续运行代码,即使应用程序关闭,您也将收到位置信息
使用Android中的融合位置提供程序设置时间间隔: 例如,创建如下活动:
public class LocationActivity extends Activity implements
LocationListener,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
private static final String TAG = "LocationActivity";
private static final long INTERVAL = 1000 * 10;
private static final long FASTEST_INTERVAL = 1000 * 5;
Button btnFusedLocation;
TextView tvLocation;
LocationRequest mLocationRequest;
GoogleApiClient mGoogleApiClient;
Location mCurrentLocation;
String mLastUpdateTime;
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(INTERVAL);
mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate ...............................");
//show error dialog if GoolglePlayServices not available
if (!isGooglePlayServicesAvailable()) {
finish();
}
createLocationRequest();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
setContentView(R.layout.activity_main);
tvLocation = (TextView) findViewById(R.id.tvLocation);
btnFusedLocation = (Button) findViewById(R.id.btnShowLocation);
btnFusedLocation.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
updateUI();
}
});
}
@Override
public void onStart() {
super.onStart();
if (mGoogleApiClient.isConnected()) {
startLocationUpdates();
Log.d(TAG, "Location update resumed .....................");
}
}
@Override
public void onStop() {
super.onStop();
Log.d(TAG, "onStop fired ..............");
mGoogleApiClient.disconnect();
Log.d(TAG, "isConnected ...............: " + mGoogleApiClient.isConnected());
}
private boolean isGooglePlayServicesAvailable() {
int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (ConnectionResult.SUCCESS == status) {
return true;
} else {
GooglePlayServicesUtil.getErrorDialog(status, this, 0).show();
return false;
}
}
@Override
public void onConnected(Bundle bundle) {
Log.d(TAG, "onConnected - isConnected ...............: " + mGoogleApiClient.isConnected());
startLocationUpdates();
}
protected void startLocationUpdates() {
PendingResult<Status> pendingResult = LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
Log.d(TAG, "Location update started ..............: ");
}
@Override
public void onConnectionSuspended(int i) {
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.d(TAG, "Connection failed: " + connectionResult.toString());
}
@Override
public void onLocationChanged(Location location) {
Log.d(TAG, "Firing onLocationChanged..............................................");
mCurrentLocation = location;
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
updateUI();
}
private void updateUI() {
Log.d(TAG, "UI update initiated .............");
if (null != mCurrentLocation) {
String lat = String.valueOf(mCurrentLocation.getLatitude());
String lng = String.valueOf(mCurrentLocation.getLongitude());
tvLocation.setText("At Time: " + mLastUpdateTime + "\n" +
"Latitude: " + lat + "\n" +
"Longitude: " + lng + "\n" +
"Accuracy: " + mCurrentLocation.getAccuracy() + "\n" +
"Provider: " + mCurrentLocation.getProvider());
} else {
Log.d(TAG, "location is null ...............");
}
}
@Override
protected void onPause() {
super.onPause();
stopLocationUpdates();
}
protected void stopLocationUpdates() {
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient, this);
Log.d(TAG, "Location update stopped .......................");
}
@Override
public void onResume() {
super.onResume();
if (mGoogleApiClient.isConnected()) {
startLocationUpdates();
Log.d(TAG, "Location update resumed .....................");
}
}
}
公共类LocationActivity扩展活动实现
LocationListener,
GoogleAppClient.ConnectionCallbacks,
GoogleAppClient.OnConnectionFailedListener{
私有静态最终字符串TAG=“LocationActivity”;
专用静态最终长间隔=1000*10;
专用静态最终最长最快_间隔=1000*5;
按钮BTN使用位置;
文本视图位置;
位置请求mLocationRequest;
GoogleapClient MGoogleapClient;
位置mCurrentLocation;
字符串mLastUpdateTime;
受保护的void createLocationRequest(){
mlLocationRequest=新位置请求();
mlLocationRequest.setInterval(间隔);
mLocationRequest.SetFastTestInterval(最快间隔);
mLocationRequest.setPriority(位置请求.优先级高精度);
}
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
日志d(标签“onCreate”);
//如果GoolglePlayServices不可用,则显示错误对话框
如果(!isGooglePlayServicesAvailable()){
完成();
}
createLocationRequest();
mgoogleapclient=新的Googleapclient.Builder(此)
.addApi(LocationServices.API)
.addConnectionCallbacks(此)
.addOnConnectionFailedListener(此)
.build();
setContentView(R.layout.activity_main);
tvLocation=(TextView)findViewById(R.id.tvLocation);
btnFusedLocation=(按钮)findViewById(R.id.btnShowLocation);
btnFusedLocation.setOnClickListener(新视图.OnClickListener(){
@凌驾
公共void onClick(视图arg0){
updateUI();
}
});
}
@凌驾
public void onStart(){
super.onStart();
if(mgoogleapClient.isConnected()){
startLocationUpdates();
Log.d(标签“位置更新恢复…”);
}
}
@凌驾
公共void onStop(){
super.onStop();
日志d(标签“顶部点火……”);
mGoogleApiClient.disconnect();
Log.d(标记“isConnected…”:“+mgoogleapclient.isConnected());
}
私有布尔值isGooglePlayServicesAvailable(){
int status=GooglePlayServicesUtil.isGooglePlayServicesAvailable(此);
if(ConnectionResult.SUCCESS==状态){
返回true;
}否则{
GooglePlayServicesUtil.getErrorDialog(状态,this,0.show();
返回false;
}
}
@凌驾
未连接的公共空间(捆绑包){
Log.d(标记“onConnected-isConnected…”:“+mgoogleapclient.isConnected()”;
startLocationUpdates();
}
受保护的void startLocationUpdates(){
Pendingreult Pendingreult=LocationServices.FusedLocationApi.RequestLocationUpdate(
mgoogleapclient,mLocationRequest,this);
Log.d(标记“位置更新已开始…”);
}
@凌驾
公共空间连接暂停(int i){
}
@凌驾
公共无效onConnectionFailed(ConnectionResult ConnectionResult){
Log.d(标记“连接失败:”+connectionResult.toString());
}
@凌驾
已更改位置上的公共无效(位置){
Log.d(标签“仅点火位置已更改”);
mCurrentLocation=位置;
mLastUpdateTime=DateFormat.getTimeInstance().format(新日期());
updateUI();
}
私有void updateUI(){
Log.d(标记“UI更新已启动……”);
if(null!=mCurrentLocation){
String lat=String.valueOf(mCurrentLocation.getLatitude());
String lng=String.valueOf(mCurrentLocation.getLongitude());
tvLocation.setText(“在时间:+mLastUpdateTime+”\n”+
纬度:“+lat+”\n+
经度:“+lng+”\n+
精度:“+mCurrentLocation.GetAccurance()+”\n”+
提供程序:“+mCurrentLocation.getProvider());
}否则{
Log.d(标记“位置为空……”);
}
}
@凌驾
受保护的void onPause(){
super.onPause();
stopLocationUpdates();
}
受保护的void stopLocationUpdates(){
LocationServices.FusedLocationApi.RemovelocationUpdate(
mGoogleApiClient,本);
Log.d(标记“位置更新已停止…”);
compile 'io.nlopez.smartlocation:library:3.2.9'
Button start_btn=(Button)findViewById(R.id.start_location_streaming);
Context context = start_btn.getContext();
Handler handler = new Handler();
start_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SmartLocation.with(context).location().start(locationListener);
}
});
OnLocationUpdatedListener locationListener = new OnLocationUpdatedListener({
@Override
public void onLocationUpdated(Location location) {
double lat = location.getLatitude();
double lng = location.getLongitude();
handler.postDelayed(locationRunnable,8000);
}
});
Runnable locationRunnable = new Runnable({
@Override
public void run() {
SmartLocation.with(context).location().start(locationListener);
}
});
@Override
public void onStop() {
SmartLocation.with(context).location().stop();
super.onStop();
}
implementation 'com.google.android.gms:play-services-maps:17.0.0'
implementation 'com.google.android.gms:play-services-location:17.0.0'
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
private FusedLocationProviderClient fusedLocationClient;
private LocationRequest mLocationRequest;
private LocationCallback mlocationCallback;
private LocationSettingsRequest.Builder builder;
private static final int REQUEST_CHECK_SETTINGS = 102;
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
fetchLastLocation();
mlocationCallback = new LocationCallback() {
@Override
public void onLocationResult(LocationResult locationResult) {
if (locationResult == null) {
return;
}
for (Location location : locationResult.getLocations()) {
// Update UI with location data
// ...
Log.e("CONTINIOUSLOC: ", location.toString());
}
};
};
mLocationRequest = createLocationRequest();
builder = new LocationSettingsRequest.Builder()
.addLocationRequest(mLocationRequest);
checkLocationSetting(builder);
private void fetchLastLocation() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// Activity#requestPermissions
// 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. See the documentation
// for Activity#requestPermissions for more details.
// Toast.makeText(MainActivity.this, "Permission not granted, Kindly allow permission", Toast.LENGTH_LONG).show();
showPermissionAlert();
return;
}
}
fusedLocationClient.getLastLocation()
.addOnSuccessListener(this, new OnSuccessListener<Location>() {
@Override
public void onSuccess(Location location) {
// Got last known location. In some rare situations this can be null.
if (location != null) {
// Logic to handle location object
Log.e("LAST LOCATION: ", location.toString()); // You will get your last location here
}
}
});
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch (requestCode) {
case 123: {
// If request is cancelled, the result arrays are empty.
if (grantResults[0] == PackageManager.PERMISSION_DENIED) {
// permission was denied, show alert to explain permission
showPermissionAlert();
}else{
//permission is granted now start a background service
if (ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
fetchLastLocation();
}
}
}
}
}
private void showPermissionAlert(){
if (ActivityCompat.checkSelfPermission(MainHomeActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(MainHomeActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainHomeActivity.this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, 123);
}
}
protected LocationRequest createLocationRequest() {
LocationRequest mLocationRequest = LocationRequest.create();
mLocationRequest.setInterval(30000);
mLocationRequest.setFastestInterval(10000);
mLocationRequest.setSmallestDisplacement(30);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
return mLocationRequest;
}
private void checkLocationSetting(LocationSettingsRequest.Builder builder) {
SettingsClient client = LocationServices.getSettingsClient(this);
Task<LocationSettingsResponse> task = client.checkLocationSettings(builder.build());
task.addOnSuccessListener(this, new OnSuccessListener<LocationSettingsResponse>() {
@Override
public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
// All location settings are satisfied. The client can initialize
// location requests here.
// ...
startLocationUpdates();
return;
}
});
task.addOnFailureListener(this, new OnFailureListener() {
@Override
public void onFailure(@NonNull final Exception e) {
if (e instanceof ResolvableApiException) {
// Location settings are not satisfied, but this can be fixed
AlertDialog.Builder builder1 = new AlertDialog.Builder(mContext);
builder1.setTitle("Continious Location Request");
builder1.setMessage("This request is essential to get location update continiously");
builder1.create();
builder1.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
ResolvableApiException resolvable = (ResolvableApiException) e;
try {
resolvable.startResolutionForResult(MainHomeActivity.this,
REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException e1) {
e1.printStackTrace();
}
}
});
builder1.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(mContext, "Location update permission not granted", Toast.LENGTH_LONG).show();
}
});
builder1.show();
}
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
if (requestCode == REQUEST_CHECK_SETTINGS) {
if (resultCode == RESULT_OK) {
// All location settings are satisfied. The client can initialize
// location requests here.
startLocationUpdates();
}
else {
checkLocationSetting(builder);
}
}
}
public void startLocationUpdates() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// Activity#requestPermissions
// 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. See the documentation
// for Activity#requestPermissions for more details.
return;
}
}
fusedLocationClient.requestLocationUpdates(mLocationRequest,
mlocationCallback,
null /* Looper */);
}
private void stopLocationUpdates() {
fusedLocationClient.removeLocationUpdates(mlocationCallback);
}