在后台连续获取当前位置
Posted
技术标签:
【中文标题】在后台连续获取当前位置【英文标题】:Getting current location continuously in background 【发布时间】:2015-02-17 07:40:00 【问题描述】:在我的项目中,我使用了一项服务来在后台连续检索位置。我的LocationService
如下:
public class LocationService extends Service
private static final int TWO_MINUTES = 1000 * 60 * 2;
public LocationManager locationManager;
public MyLocationListener listener;
public Location previousBestLocation = null;
Intent i;
@Override
public void onCreate()
super.onCreate();
i = new Intent("LOCATION_CHANGED");
@Override
public int onStartCommand(Intent intent,int flags, int startId)
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
listener = new MyLocationListener();
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 4000, 0, listener);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 4000, 0, listener);
return super.onStartCommand(intent, flags, startId);
@Override
public IBinder onBind(Intent intent)
return null;
protected boolean isBetterLocation(Location location, Location currentBestLocation)
if (currentBestLocation == null)
// A new location is always better than no location
return true;
// Check whether the new location fix is newer or older
long timeDelta = location.getTime() - currentBestLocation.getTime();
boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
boolean isNewer = timeDelta > 0;
// If it's been more than two minutes since the current location, use the new location
// because the user has likely moved
if (isSignificantlyNewer)
return true;
// If the new location is more than two minutes older, it must be worse
else if (isSignificantlyOlder)
return false;
// Check whether the new location fix is more or less accurate
int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
boolean isLessAccurate = accuracyDelta > 0;
boolean isMoreAccurate = accuracyDelta < 0;
boolean isSignificantlyLessAccurate = accuracyDelta > 200;
// Check if the old and new location are from the same provider
boolean isFromSameProvider = isSameProvider(location.getProvider(),
currentBestLocation.getProvider());
// Determine location quality using a combination of timeliness and accuracy
if (isMoreAccurate)
return true;
else if (isNewer && !isLessAccurate)
return true;
else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider)
return true;
return false;
/** Checks whether two providers are the same */
private boolean isSameProvider(String provider1, String provider2)
if (provider1 == null)
return provider2 == null;
return provider1.equals(provider2);
@Override
public void onDestroy()
// handler.removeCallbacks(sendUpdatesToUI);
super.onDestroy();
Log.v("STOP_SERVICE", "DONE");
locationManager.removeUpdates(listener);
public static Thread performOnBackgroundThread(final Runnable runnable)
final Thread t = new Thread()
@Override
public void run()
try
runnable.run();
catch(Exception e)
System.out.print(e);
;
t.start();
return t;
public class MyLocationListener implements LocationListener
public void onLocationChanged(final Location loc)
Log.i("**************************************", "Location changed");
if(isBetterLocation(loc, previousBestLocation))
String newLocation = "Lat: " + loc.getLatitude() + " and Long: " + loc.getLongitude();
i = new Intent("LOCATION_CHANGED");
i.putExtra("location", newLocation);
sendBroadcast(i);
public void onProviderDisabled(String provider)
Toast.makeText( getApplicationContext(), "Gps Disabled", Toast.LENGTH_SHORT ).show();
public void onProviderEnabled(String provider)
Toast.makeText(getApplicationContext(), "Gps Enabled", Toast.LENGTH_SHORT).show();
public void onStatusChanged(String provider, int status, Bundle extras)
我在MainActivity
收到了广播意图,如下:
public class MainActivity extends Activity
TextView txt_location;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txt_location = (TextView)findViewById(R.id.current_location);
if (savedInstanceState == null)
getFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment()).commit();
public class LocationBroadcast extends BroadcastReceiver
@Override
public void onReceive(Context ctx, Intent intent)
txt_location.setText(intent.getExtras().getString("location"));
public static class PlaceholderFragment extends Fragment
public PlaceholderFragment()
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
return inflater.inflate(R.layout.fragment_main, container,
false);
我要做的就是在txt_location
上设置位置的纬度和经度。此代码不起作用并按原样显示txt_location
:
如您所见,它没有显示任何位置更新...Logcat 没有显示任何错误..谁能指导我是什么错误?
【问题讨论】:
使用 AndoridHive 教程:androidhive.info/2012/07/android-gps-location-manager-tutorial @TusharPandey 它用于在某些按钮单击时检索位置。我说我想在后台连续获取位置(使用服务或任何其他方法) 为它创建一个服务,或者无限时间使用后台线程并在位置变化时生成本地广播消息。 @TusharPandey 我已经做了服务..LocationService 类扩展了服务 无限时间使用后台线程并生成 【参考方案1】:将此类用作服务。但在此之前在清单中定义服务类
<service android:name="com.example.androidservice.beckend.EndlessService" />
在活动类中使用
startService(new Intent ( this , EndlessService.class)) ;
import android.app.Service;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Process;
import android.util.Log;
import android.widget.Toast;
public class EndlessService extends Service
private Looper mServiceLooper;
private ServiceHandler mServiceHandler;
// Handler that receives messages from the thread
private final class ServiceHandler extends Handler
public ServiceHandler(Looper looper)
super(looper);
@Override
public void handleMessage(Message msg)
new HitToTheInternet().execute("");
@Override
public void onCreate()
// Start up the thread running the service. Note that we create a
// separate thread because the service normally runs in the process's
// main thread, which we don't want to block. We also make it
// background priority so CPU-intensive work will not disrupt our UI.
HandlerThread thread = new HandlerThread("ServiceStartArguments",Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
// Get the HandlerThread's Looper and use it for our Handler
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
@Override
public int onStartCommand(Intent intent, int flags, int startId)
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
// For each start request, send a message to start a job and deliver the
// start ID so we know which request we're stopping when we finish the
// job
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
mServiceHandler.sendMessage(msg);
if ( intent == null )
Log.e("intentStatus", "intent is null");
// If we get killed, after returning from here, restart
return START_STICKY;
@Override
public IBinder onBind(Intent intent)
// We don't provide binding, so return null
return null;
@Override
public void onDestroy()
Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
class HitToTheInternet extends AsyncTask<String, String, String>
@Override
protected String doInBackground(String... params)
// TODO Auto-generated method stub
Log.e("doInBackground", "Running") ;
return null;
@Override
protected void onPostExecute(String result)
// TODO Auto-generated method stub
super.onPostExecute(result);
new Handler().postDelayed(new Runnable()
public void run()
Message msg = mServiceHandler.obtainMessage();
mServiceHandler.sendMessage(msg);
, 10000);
【讨论】:
【参考方案2】:在 5 秒后开始服务说:
AlarmManager alarm =(AlarmManager)context.getSystemService(context.ALARM_SERVICE);
PendingIntent pi = PendingIntent.getService(context, 0, new Intent(context,MonitorService.class), 0);
alarm.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(), 5*1000, pi);
停止报警:
AlarmManager mgr =(AlarmManager)getSystemService(ALARM_SERVICE);
PendingIntent pi = PendingIntent.getService(context, 0, new Intent(this,MonitorService.class), 0);
mgr.cancel(pi);
pi.cancel();
【讨论】:
以上是关于在后台连续获取当前位置的主要内容,如果未能解决你的问题,请参考以下文章