2012-01-12 4 views
45

Мне нужно отслеживать местоположения пользователя с помощью службы фона, а затем загружать их и показывать путь к пользователю.Получить местоположение GPS через службу в Android

С помощью этой операции было довольно легко получить местоположение GPS, но когда мне нужно было это сделать через службу, у меня возникла проблема, поскольку она работает только для потоков петлителя (или что-то в этом роде).

Как я искал в Интернете решение, я обнаружил, что у многих людей такая же проблема, но я не мог найти рабочего решения. Некоторые люди говорят, что вам нужно использовать prepare-> loop-> quit, а некоторые говорят, что вам нужно использовать handlerThread, но все же я не могу точно определить, как это сделать.

+0

Loopy нитей: D Вы имеете в виду нити петлителя. Looper thread - это специальный поток с механизмом очереди запросов. Основной поток или поток пользовательского интерфейса - поток Looper. Что касается проблемы с Сервисом, вы вызываете requestLocationUpdates в основном потоке? Или вы делаете это в другом потоке? Поскольку действия и службы выполняются через основной поток, который является потоком петлителя, поэтому вызов requestLocationUpdates должен быть таким же. Можете ли вы указать на другие сообщения, в которых упоминается этот вопрос, о котором вы говорите? –

ответ

-7

нормально, я уже решил проблему, создав обработчик на OnCreate службы и вызова функций gps.

+62

Отправьте код, пожалуйста. Это действительно помогло бы другим, которые наткнулись бы на эту страницу при поиске ответов. – Razgriz

+1

Это был дан ответ давным-давно, но я попытаюсь объяснить: поскольку обработка GPS должна запускаться в потоке пользовательского интерфейса, создайте объект Handler для любого из методов службы, которые запускаются в потоке пользовательского интерфейса (например, onCreate) и установите его в поле в службе. Затем, в любое время, когда вам нужно использовать операции GPS, просто вызовите сообщение (Runnable) в этом экземпляре обработчика. –

+0

Можете ли вы отправить код, пожалуйста? – delive

40

Я не понимаю, в чем проблема с реализацией функций прослушивания местоположения в Сервисе. Он выглядит довольно похоже на то, что вы делаете в Activity. Просто определите приемник местоположения и зарегистрируйтесь для обновлений местоположения. Вы можете обратиться к следующему коду в качестве примера:

манифеста файла:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> 
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> 
<application 
    android:icon="@drawable/ic_launcher" 
    android:label="@string/app_name" > 
    <activity android:label="@string/app_name" android:name=".LocationCheckerActivity" > 
     <intent-filter > 
      <action android:name="android.intent.action.MAIN" /> 
      <category android:name="android.intent.category.LAUNCHER" /> 
     </intent-filter> 
    </activity> 
    <service android:name=".MyService" android:process=":my_service" /> 
</application> 

Файл службы:

import android.app.Service; 
import android.content.Context; 
import android.content.Intent; 
import android.location.Location; 
import android.location.LocationManager; 
import android.os.Bundle; 
import android.os.IBinder; 
import android.util.Log; 

public class MyService extends Service 
{ 
private static final String TAG = "BOOMBOOMTESTGPS"; 
private LocationManager mLocationManager = null; 
private static final int LOCATION_INTERVAL = 1000; 
private static final float LOCATION_DISTANCE = 10f; 

private class LocationListener implements android.location.LocationListener{ 
    Location mLastLocation; 
    public LocationListener(String provider) 
    { 
     Log.e(TAG, "LocationListener " + provider); 
     mLastLocation = new Location(provider); 
    } 
    @Override 
    public void onLocationChanged(Location location) 
    { 
     Log.e(TAG, "onLocationChanged: " + location); 
     mLastLocation.set(location); 
    } 
    @Override 
    public void onProviderDisabled(String provider) 
    { 
     Log.e(TAG, "onProviderDisabled: " + provider);    
    } 
    @Override 
    public void onProviderEnabled(String provider) 
    { 
     Log.e(TAG, "onProviderEnabled: " + provider); 
    } 
    @Override 
    public void onStatusChanged(String provider, int status, Bundle extras) 
    { 
     Log.e(TAG, "onStatusChanged: " + provider); 
    } 
} 
LocationListener[] mLocationListeners = new LocationListener[] { 
     new LocationListener(LocationManager.GPS_PROVIDER), 
     new LocationListener(LocationManager.NETWORK_PROVIDER) 
}; 
@Override 
public IBinder onBind(Intent arg0) 
{ 
    return null; 
} 
@Override 
public int onStartCommand(Intent intent, int flags, int startId) 
{ 
    Log.e(TAG, "onStartCommand"); 
    super.onStartCommand(intent, flags, startId);  
    return START_STICKY; 
} 
@Override 
public void onCreate() 
{ 
    Log.e(TAG, "onCreate"); 
    initializeLocationManager(); 
    try { 
     mLocationManager.requestLocationUpdates(
       LocationManager.NETWORK_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE, 
       mLocationListeners[1]); 
    } catch (java.lang.SecurityException ex) { 
     Log.i(TAG, "fail to request location update, ignore", ex); 
    } catch (IllegalArgumentException ex) { 
     Log.d(TAG, "network provider does not exist, " + ex.getMessage()); 
    } 
    try { 
     mLocationManager.requestLocationUpdates(
       LocationManager.GPS_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE, 
       mLocationListeners[0]); 
    } catch (java.lang.SecurityException ex) { 
     Log.i(TAG, "fail to request location update, ignore", ex); 
    } catch (IllegalArgumentException ex) { 
     Log.d(TAG, "gps provider does not exist " + ex.getMessage()); 
    } 
} 
@Override 
public void onDestroy() 
{ 
    Log.e(TAG, "onDestroy"); 
    super.onDestroy(); 
    if (mLocationManager != null) { 
     for (int i = 0; i < mLocationListeners.length; i++) { 
      try { 
       mLocationManager.removeUpdates(mLocationListeners[i]); 
      } catch (Exception ex) { 
       Log.i(TAG, "fail to remove location listners, ignore", ex); 
      } 
     } 
    } 
} 
private void initializeLocationManager() { 
    Log.e(TAG, "initializeLocationManager"); 
    if (mLocationManager == null) { 
     mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE); 
    } 
} 
} 
+0

Я знаю, он отлично работал на побочном проекте, но я работаю с некоторыми людьми, и по какой-то причине я всегда получаю исключение: java.lang.RuntimeException: не удается создать обработчик внутри потока, который не вызвал Looper. prepare() Я просмотрел код, и я не вижу, что он работает в специальном потоке, и точно так же, как и в вашем коде, служба запускается в процессе с указанным именем. –

+0

, возможно, это потому, что у службы есть свой процесс, и когда вы позже открываете приложение, он использует другой поток, который не является оригинальным? –

+1

Кстати, нужно ли вызывать «removeUpdates» для метода «onDestroy»? Я думаю, что удаление его не приведет к утечке памяти, нет? –

2

Просто дополнения, я осуществил этот путь, и, как правило, работал в моем классе обслуживания

В моих службах

@Override 
public void onCreate() 
{ 
    mHandler = new Handler(Looper.getMainLooper()); 
    mHandler.post(this); 
    super.onCreate(); 
} 

@Override 
public void onDestroy() 
{ 
    mHandler.removeCallbacks(this);  
    super.onDestroy(); 
} 

@Override 
public void run() 
{ 
    InciarGPSTracker(); 
} 
17
public class GPSService extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, com.google.android.gms.location.LocationListener { 
    private LocationRequest mLocationRequest; 
    private GoogleApiClient mGoogleApiClient; 
    private static final String LOGSERVICE = "#######"; 

    @Override 
    public void onCreate() { 
     super.onCreate(); 
     buildGoogleApiClient(); 
     Log.i(LOGSERVICE, "onCreate"); 

    } 

    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 
     Log.i(LOGSERVICE, "onStartCommand"); 

     if (!mGoogleApiClient.isConnected()) 
      mGoogleApiClient.connect(); 
     return START_STICKY; 
    } 


    @Override 
    public void onConnected(Bundle bundle) { 
     Log.i(LOGSERVICE, "onConnected" + bundle); 

     Location l = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient); 
     if (l != null) { 
      Log.i(LOGSERVICE, "lat " + l.getLatitude()); 
      Log.i(LOGSERVICE, "lng " + l.getLongitude()); 

     } 

     startLocationUpdate(); 
    } 

    @Override 
    public void onConnectionSuspended(int i) { 
     Log.i(LOGSERVICE, "onConnectionSuspended " + i); 

    } 

    @Override 
    public void onLocationChanged(Location location) { 
     Log.i(LOGSERVICE, "lat " + location.getLatitude()); 
     Log.i(LOGSERVICE, "lng " + location.getLongitude()); 
     LatLng mLocation = (new LatLng(location.getLatitude(), location.getLongitude())); 
     EventBus.getDefault().post(mLocation); 

    } 

    @Override 
    public void onDestroy() { 
     super.onDestroy(); 
     Log.i(LOGSERVICE, "onDestroy - Estou sendo destruido "); 

    } 

    @Nullable 
    @Override 
    public IBinder onBind(Intent intent) { 
     return null; 
    } 

    @Override 
    public void onConnectionFailed(ConnectionResult connectionResult) { 
     Log.i(LOGSERVICE, "onConnectionFailed "); 

    } 

    private void initLocationRequest() { 
     mLocationRequest = new LocationRequest(); 
     mLocationRequest.setInterval(5000); 
     mLocationRequest.setFastestInterval(2000); 
     mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); 

    } 

    private void startLocationUpdate() { 
     initLocationRequest(); 

     if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { 
      // TODO: Consider calling 
      // ActivityCompat#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 ActivityCompat#requestPermissions for more details. 
      return; 
     } 
     LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this); 
    } 

    private void stopLocationUpdate() { 
     LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this); 

    } 

    protected synchronized void buildGoogleApiClient() { 
     mGoogleApiClient = new GoogleApiClient.Builder(this) 
       .addOnConnectionFailedListener(this) 
       .addConnectionCallbacks(this) 
       .addApi(LocationServices.API) 
       .build(); 
    } 

} 
+0

Я использую lib EventBus для отправки местоположения для просмотра. -> EventBus.getDefault(). Post (mLocation) – vrbsm

+0

Это не работает в фоновом режиме. Я использую Red MI note 3. Его работа прекрасна, когда приложение включено, но не работает как служба, когда я убиваю приложение. –

+1

как справиться с разрешениями и настройками местоположения здесь? –

Смежные вопросы