2012-01-12 34 views
45

Tôi cần theo dõi vị trí của người dùng bằng dịch vụ nền, sau đó tải chúng và hiển thị đường dẫn tới người dùng.Nhận vị trí GPS qua dịch vụ trong Android

Sử dụng một hoạt động, khá dễ dàng để có được vị trí GPS, nhưng khi tôi làm điều đó qua dịch vụ, tôi gặp vấn đề vì nó chỉ hoạt động cho các chủ đề looper (hoặc một thứ gì đó tương tự).

Khi tôi đã tìm kiếm trên Internet một giải pháp, tôi đã phát hiện ra rằng nhiều người gặp vấn đề tương tự, nhưng tôi không thể tìm được giải pháp làm việc. Một số người nói rằng bạn cần phải sử dụng chuẩn bị-> loop-> bỏ thuốc lá, và một số nói rằng bạn phải sử dụng một handlerThread, nhưng vẫn còn, tôi không thể tìm hiểu làm thế nào để làm những việc như vậy một cách thích hợp.

+0

đề điên rồ: D Bạn có nghĩa là đề looper. Một luồng Looper là một chuỗi đặc biệt với cơ chế xếp hàng yêu cầu. Chủ đề chính hoặc giao diện người dùng là chủ đề Looper. Đối với vấn đề với một Dịch vụ, bạn có đang gọi requestLocationUpdates trên luồng chính không? Hay bạn đang làm nó trong một chủ đề khác? Bởi vì các hoạt động và dịch vụ được chạy qua luồng chính, đó là một luồng looper, nên việc gọi requestLocationUpdates phải giống nhau. Bạn có thể chỉ ra các bài viết khác đề cập đến vấn đề này mà bạn đang nói đến không? –

Trả lời

-7

ok, tôi đã giải quyết nó bằng cách tạo ra một handler trên onCreate của dịch vụ và gọi các chức năng của gps thông qua đó.

+62

Hãy đăng mã. Nó thực sự sẽ giúp những người khác mà sẽ vấp ngã khi trang này khi tìm kiếm câu trả lời. – Razgriz

+1

điều này đã được trả lời một thời gian dài trước đây, nhưng tôi sẽ cố gắng giải thích: vì việc xử lý GPS cần chạy trên chuỗi giao diện người dùng, tạo đối tượng Trình xử lý trên bất kỳ phương thức nào trên dịch vụ chạy trên chuỗi giao diện người dùng (như onCreate) và đặt nó vào một trường trong dịch vụ. Hơn nữa, bất cứ khi nào bạn cần sử dụng các hoạt động GPS, chỉ cần gọi bài (Runnable) trên phiên bản Handler này. –

+0

Bạn có thể gửi mã không? – delive

40

Tôi không hiểu chính xác vấn đề với việc triển khai chức năng nghe vị trí trong Dịch vụ là gì. Nó trông khá giống với những gì bạn làm trong Activity. Chỉ cần xác định người nghe vị trí và đăng ký cập nhật vị trí. Bạn có thể tham khảo các mã sau đây làm ví dụ:

Manifest file:

<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> 

Các tập tin dịch vụ:

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

tôi biết, nó làm việc tốt trên một dự án phụ, nhưng tôi làm việc với một số người và vì một lý do nào đó, tôi luôn có ngoại lệ: java.lang.RuntimeException: Không thể tạo bộ xử lý bên trong luồng mà không được gọi là Looper. chuẩn bị() Tôi đã xem mã và tôi không thể thấy rằng nó hoạt động trên một chuỗi đặc biệt và giống như trên mã của bạn, dịch vụ chạy trên một quy trình có tên được chỉ định. –

+0

có lẽ đó là vì dịch vụ có quy trình riêng của nó và khi bạn mở ứng dụng, nó sử dụng một luồng khác, không phải là luồng gốc? –

+1

btw, phải gọi "removeUpdates" cho phương thức "onDestroy"? tôi nghĩ rằng việc xóa nó sẽ không dẫn đến rò rỉ bộ nhớ, phải không? –

2

Chỉ cần bổ sung, tôi thực hiện theo cách này và thường làm việc trong lớp dịch vụ của tôi

Trong Dịch vụ của tôi

@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

Tôi đang sử dụng EventBus lib để gửi vị trí để xem. -> EventBus.getDefault(). Post (mLocation) – vrbsm

+0

Nó không chạy ở chế độ nền. Tôi đang sử dụng Red MI note 3. Làm việc tốt khi ứng dụng được bật nhưng không hoạt động như một dịch vụ khi tôi giết ứng dụng. –

+1

cách xử lý quyền và cài đặt vị trí tại đây ?? –

Các vấn đề liên quan