了解 Service、LocationListener 和 BroadcastReceiver 如何在后台获取位置
Posted
技术标签:
【中文标题】了解 Service、LocationListener 和 BroadcastReceiver 如何在后台获取位置【英文标题】:Understanding how Service, LocationListener and BroadcastReceiver work to get location in background 【发布时间】:2013-10-02 20:27:42 【问题描述】:我是android
的新手,我正在开发一个跟踪用户距离的应用程序。它只会在用户点击按钮时开始跟踪,并在他们再次点击时停止。似乎有大量关于如何做到这一点的混淆信息和方法,所以我至少对最佳实践有一个大致的了解。
public class BackgroundLocationService extends Service implements GooglePlayServicesClient.ConnectionCallbacks, GooglePlayServicesClient.OnConnectionFailedListener, LocationListener
IBinder mBinder = new LocalBinder();
private LocationClient mLocationClient;
private LocationRequest mLocationRequest;
private boolean mInProgress;
//Milliseconds per second
private static final int MILLISECONDS_PER_SECOND = 1000;
// Update frequency in seconds
private static final int UPDATE_INTERVAL_IN_SECONDS = 30;
// Update frequency in milliseconds
public static final long UPDATE_INTERVAL = MILLISECONDS_PER_SECOND * UPDATE_INTERVAL_IN_SECONDS;
// The fastest update frequency, in seconds
private static final int FASTEST_INTERVAL_IN_SECONDS = 30;
// A fast frequency ceiling in milliseconds
public static final long FASTEST_INTERVAL = MILLISECONDS_PER_SECOND * FASTEST_INTERVAL_IN_SECONDS;
private static final int TWO_MINUTES = 1000 * 60 * 2;
public Location previousBestLocation = null;
private Boolean servicesAvailable = false;
public class LocalBinder extends Binder
public BackgroundLocationService getServerInstance()
return BackgroundLocationService.this;
@Override
public void onCreate()
super.onCreate();
mInProgress = false;
mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(UPDATE_INTERVAL);
mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
// Check that Google Play Services are connected
servicesAvailable = servicesConnected();
// Create the client
mLocationClient = new LocationClient(this, this, this);
//end
private boolean servicesConnected()
// Check that Google Play services is available
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
// If Google Play services is available
if (ConnectionResult.SUCCESS == resultCode)
return true;
else
return false;
//end
public int onStartCommand (Intent intent, int flags, int startId)
super.onStartCommand(intent, flags, startId);
if(!servicesAvailable || mLocationClient.isConnected() || mInProgress)
return START_STICKY;
setUpLocationClientIfNeeded();
if(!mLocationClient.isConnected() || !mLocationClient.isConnecting() && !mInProgress)
mInProgress = true;
mLocationClient.connect();
return START_STICKY;
//end
private void setUpLocationClientIfNeeded()
if (mLocationClient == null)
mLocationClient = new LocationClient(this, this, this);
@Override
public void onLocationChanged(Location location)
String msg = Double.toString(location.getLatitude()) + "," +Double.toString(location.getLongitude());
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
//end
@Override
public IBinder onBind(Intent intent)
return mBinder;
public String getTime()
SimpleDateFormat mDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return mDateFormat.format(new Date());
@Override
public void onDestroy()
// Turn off the request flag
mInProgress = false;
if(servicesAvailable && mLocationClient != null)
mLocationClient.removeLocationUpdates(this);
// Destroy the current location client
mLocationClient = null;
// Display the connection status
Toast.makeText(this, DateFormat.getDateTimeInstance().format(new Date()) + ": Disconnected. Please re-connect.", Toast.LENGTH_SHORT).show();
super.onDestroy();
/*
* Called by Location Services when the request to connect the
* client finishes successfully. At this point, you can
* request the current location or start periodic updates
*/
@Override
public void onConnected(Bundle bundle)
// Request location updates using static settings
mLocationClient.requestLocationUpdates(mLocationRequest, this);
/*
* Called by Location Services if the connection to the
* location client drops because of an error.
*/
@Override
public void onDisconnected()
// Turn off the request flag
mInProgress = false;
// Destroy the current location client
mLocationClient = null;
// Display the connection status
Toast.makeText(this, DateFormat.getDateTimeInstance().format(new Date()) + ": Disconnected. Please re-connect.", Toast.LENGTH_SHORT).show();
/*
* Called by Location Services if the attempt to
* Location Services fails.
*/
@Override
public void onConnectionFailed(ConnectionResult connectionResult)
mInProgress = false;
/*
* Google Play services can resolve some errors it detects.
* If the error has a resolution, try sending an Intent to
* start a Google Play services activity that can resolve
* error.
*/
if (connectionResult.hasResolution())
// If no resolution is available, display an error dialog
else
那么我的问题:
从我的主要Activity
我如何启动我的服务?我该如何阻止它?
我的Activity
班级如何知道我的Service
何时收到Location
更新,以便我可以更新 UI?
我还需要BroadcastReceiver
吗?
有什么需要进入我的Manifest
吗?
【问题讨论】:
【参考方案1】:让我们按顺序回答您的问题:
-
http://www.androidhive.info/2012/07/android-gps-location-manager-tutorial/
onLocationChanged(位置位置)
不,转到 1
是的,再次,转到 1
编辑:向 MainActivity 报告
在你的 MainActivity 中添加一个这样的界面:
public class MainActivity implements NewLocationsListener
public interface NewLocationsListener
public void onNewLocation(Location location);
private GPSTracker gps;
...
// when your button is clicked or where ever you want to start gps
gps = new GPSTracker(this, this);
...
// and get Locations in onNewLocation
public void onNewLocation(Location location)
// location reported back from gps
// if you want gps to stop after exiting your app
@Override
protected void onPause()
if (gps != null)
gps.stopUsingGPS();
super.onPause();
并添加到 GPSTracker:
private NewLocationsListener mListener;
public GPSTracker(Context context, NewLocationsListener listener)
this.mContext = context;
this.mListener = listener;
getLocation();
@Override
public void onLocationChanged(Location location)
// report back to MainActivity
mListener.onNewLocation(location);
canGetLocation = true;
Edit2:如何处理退出重新进入和方向更改的示例:
正如您所说,由于您是 Android 新手,所以我想我不妨添加这个。
public class StrategyActivity extends Activity
public static final String TAG = "StrategyActivity";
protected GPSTracker gps;
private Button startButton;
private boolean isStarted = false;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
startButton = (Button) findViewById(R.id.start_button);
if (savedInstanceState != null)
isStarted = savedInstanceState.getBoolean("isStarted");
@Override
protected void onResume()
if (isStarted)
startStrategy();
updateOnOffButton();
super.onResume();
@Override
protected void onSaveInstanceState(Bundle outState)
outState.putBoolean("isStarted", isStarted);
super.onSaveInstanceState(outState);
@Override
public void onBackPressed()
if (isStarted)
stopStrategy();
super.onBackPressed();
@Override
protected void onPause()
if (isStarted)
killStrategy();
super.onPause();
@Override
protected void onDestroy()
killStrategy();
super.onDestroy();
public void startStopClicked(View view)
if (isStarted)
stopStrategy();
else
startStrategy();
private void updateOnOffButton()
if (isStarted)
startButton.setText("Stop");
else
startButton.setText("Start");
protected void killStrategy()
if (gps != null)
gps.stopUsingGPS();
protected void startStrategy()
isStarted = true;
gps = new GPSTracker(this);
updateOnOffButton();
Toast.makeText(this, "Started", Toast.LENGTH_LONG).show();
protected void stopStrategy()
isStarted = false;
killStrategy();
updateOnOffButton();
Toast.makeText(this, "Stopped", Toast.LENGTH_LONG).show();
【讨论】:
好吧,即使我离开应用程序,它也能正常工作并为我提供位置更新。在我的Activity
中,我使用startService(new Intent(this, BackgroundLocationService.class));
开始了我的服务。仍然不清楚我的Service
如何与我的主要Activity
交谈,以便在我每次获得位置更新时让它知道。
实际上我现在可以使用LocalBroadcastManager
。我可以发送一个字符串。但我现在正在努力解决如何发送Location
对象。
现在我做了一个例子。可能有错别字,但应该能很好地展示主要思想。以上是关于了解 Service、LocationListener 和 BroadcastReceiver 如何在后台获取位置的主要内容,如果未能解决你的问题,请参考以下文章
了解 Service、LocationListener 和 BroadcastReceiver 如何在后台获取位置