2010-08-15 35 views
26

Tôi đang viết một ứng dụng yêu cầu vị trí hiện tại của người dùng (lastknownlocation sẽ không hữu ích) và hiển thị danh sách tất cả các mục "gần nhất" được lấy từ cơ sở dữ liệu.Android tìm vị trí GPS một lần, hiển thị hộp thoại tải

Tôi đã tìm thấy các mục gần nhất hoạt động tốt nhưng chỉ sử dụng vị trí kinh độ và vĩ độ được mã hóa trong lúc này nhưng bây giờ là lúc để thực hiện tìm vị trí thực tế.

Bất kỳ ai cũng có thể cung cấp ví dụ về cách ứng dụng tìm vị trí hiện tại trong nền và yêu cầu ứng dụng chờ. Tôi chỉ cần vị trí một lần không cập nhật khi người đó di chuyển. Tôi đã thực hiện một người nghe vị trí tuy nhiên tôi hiểu việc sửa chữa GPS có thể chậm. Tôi đã thấy các ví dụ khác sử dụng vị trí đã biết cuối cùng hoặc triển khai trình nghe vị trí tiếp tục chạy và cập nhật tuy nhiên khi Hoạt động của tôi cần tọa độ vị trí trước khi nó có thể hiển thị mọi thứ mà ứng dụng chỉ gặp sự cố. Tôi cần hiển thị Hộp thoại tiến trình trong khi tìm kiếm.

Tôi làm cách nào để trình điều khiển vị trí chạy một lần trong nền và sau đó xóa các cập nhật vị trí khi tìm thấy vị trí đó. Tôi cần phần còn lại của ứng dụng để chờ cho đến khi nó có vị trí GPS hoặc hết thời gian chờ sau 20-30 giây. Tôi muốn có một ProgressDialog để người dùng biết rằng một cái gì đó đang diễn ra, nhưng nó chỉ là hoạt hình tải quay không phải là một tỷ lệ phần trăm hay bất cứ thứ gì. Nếu có thể, tôi muốn người dùng có thể hủy hộp thoại nếu họ bị bệnh chờ đợi sau đó họ có thể tìm kiếm bằng cách nhập ngoại ô, vv thay vào đó.

Tôi đã cố gắng để làm điều đó với chủ đề nhưng nó là nhận được cách phức tạp hơn tôi cảm thấy nó nên được và vẫn không làm việc anyway. Trên iPhone, điều này đơn giản hơn nhiều?

Bất cứ ai có thể cung cấp một cách tốt đẹp để làm điều này, tôi đã tách tóc của tôi ra trong một tuần về điều này và nó thực sự đưa tôi đằng sau lịch trình cho phần còn lại của ngày hoàn thành ứng dụng.

Nói tóm lại tôi muốn:
* Tìm tọa độ hiện tại
* Hiện Progress Dialog trong khi nhận được vị trí
* Có ứng dụng có thể chờ đợi cho vị trí thành công hay từ bỏ sau một thời gian nhất định?
* Nếu thành công: Loại bỏ hộp thoại tiến trình và sử dụng tọa độ để chạy các phương pháp khác của tôi để tìm kiếm các mục gần đúng.
* Nếu không thể nhận vị trí: Bỏ qua hộp thoại tiến trình và hiển thị thông báo lỗi và khuyến khích người dùng sử dụng menu để chuyển đến Hoạt động tìm kiếm.
* Sử dụng các tọa độ này nếu người dùng chọn chế độ xem bản đồ từ trình đơn, để hiển thị vị trí hiện tại trên bản đồ và ghim ở tất cả các mục lân cận bằng cách sử dụng tọa độ của chúng từ cơ sở dữ liệu.

Cảm ơn các bạn, tôi hy vọng tôi đã giải thích cho bản thân mình đủ tốt. Mọi câu hỏi chỉ hỏi, tôi sẽ kiểm tra lại thường xuyên vì tôi muốn hoàn thành phần này. Cheers

EDIT
Mã theo yêu cầu

tập tin hoạt động locationList

protected void onStart() 
{ 
    super.onStart(); 

    // .... 

    new LocationControl().execute(this); 
} 


private class LocationControl extends AsyncTask<Context, Void, Void> 
{ 
    private final ProgressDialog dialog = new ProgressDialog(branchAtmList.this); 

    protected void onPreExecute() 
    { 
     this.dialog.setMessage("Determining your location..."); 
     this.dialog.show(); 
    } 

    protected Void doInBackground(Context... params) 
    { 
     LocationHelper location = new LocationHelper(); 

     location.getLocation(params[0], locationResult); 

     return null; 
    } 

    protected void onPostExecute(final Void unused) 
    { 
     if(this.dialog.isShowing()) 
     { 
      this.dialog.dismiss(); 
     } 

     useLocation(); //does the stuff that requires current location 
    } 

} 

public LocationResult locationResult = new LocationResult() 
{ 
    @Override 
    public void gotLocation(final Location location) 
    { 
     currentLocation = location; 
    } 
}; 

lớp LocationHelper

package org.xxx.xxx.utils; 

import java.util.Timer; 
/* 
imports 
*/ 

public class LocationHelper 
{ 
    LocationManager locationManager; 
    private LocationResult locationResult; 
    boolean gpsEnabled = false; 
    boolean networkEnabled = false; 

    public boolean getLocation(Context context, LocationResult result) 
    {  
     locationResult = result; 

     if(locationManager == null) 
     { 
      locationManager = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE); 
     } 
      //exceptions thrown if provider not enabled 
      try 
      { 
       gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); 
      } 
      catch (Exception ex) {} 
      try 
      { 
       networkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER); 
      } 
      catch (Exception ex) {} 

      //dont start listeners if no provider is enabled 
      if(!gpsEnabled && !networkEnabled) 
      { 
       return false; 
      } 

      if(gpsEnabled) 
      { 
       locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListenerGps); 
      } 
      if(networkEnabled) 
      { 
       locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListenerNetwork); 
      } 


      GetLastLocation(); 
      return true; 
    } 

    LocationListener locationListenerGps = new LocationListener() { 
     public void onLocationChanged(Location location) 
     { 
      locationResult.gotLocation(location); 
      locationManager.removeUpdates(this); 
      locationManager.removeUpdates(locationListenerNetwork); 

     } 
     public void onProviderDisabled(String provider) {} 
     public void onProviderEnabled(String provider) {} 
     public void onStatusChanged(String provider, int status, Bundle extra) {} 
    }; 

    LocationListener locationListenerNetwork = new LocationListener() { 
     public void onLocationChanged(Location location) 
     { 
      locationResult.gotLocation(location); 
      locationManager.removeUpdates(this); 
      locationManager.removeUpdates(locationListenerGps); 

     } 
     public void onProviderDisabled(String provider) {} 
     public void onProviderEnabled(String provider) {} 
     public void onStatusChanged(String provider, int status, Bundle extra) {} 

    }; 

    private void GetLastLocation() 
    { 
      locationManager.removeUpdates(locationListenerGps); 
      locationManager.removeUpdates(locationListenerNetwork); 

      Location gpsLocation = null; 
      Location networkLocation = null; 

      if(gpsEnabled) 
      { 
       gpsLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); 
      } 
      if(networkEnabled) 
      { 
       networkLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER); 
      } 

      //if there are both values use the latest one 
      if(gpsLocation != null && networkLocation != null) 
      { 
       if(gpsLocation.getTime() > networkLocation.getTime()) 
       { 
        locationResult.gotLocation(gpsLocation); 
       } 
       else 
       { 
        locationResult.gotLocation(networkLocation); 
       } 

       return; 
      } 

      if(gpsLocation != null) 
      { 
       locationResult.gotLocation(gpsLocation); 
       return; 
      } 

      if(networkLocation != null) 
      { 
       locationResult.gotLocation(networkLocation); 
       return; 
      } 

      locationResult.gotLocation(null); 
    } 

    public static abstract class LocationResult 
    { 
     public abstract void gotLocation(Location location); 
    } 
} 

Điều này thực sự có vẻ giống như một nỗ lực lớn chỉ để có được vị trí hiện tại một lần? Tôi không yêu cầu cập nhật hay gì cả? Có cách nào đơn giản hơn để ứng dụng chờ kết quả không? Tôi đã bị mắc kẹt trong chuyện này quá lâu rồi.

+0

http://stackoverflow.com/questions/3145089/what-is-the-simplest-and-most-robust-way-to-get-the-users-current-location-in-a/9811633#9811633 – Rajal

Trả lời

17

Sử dụng một AsyncTask và sử dụng cả network_provider cũng như gps_provider, có nghĩa là hai người nghe. gps mất nhiều thời gian hơn để sửa chữa, có thể đôi khi một phút và chỉ hoạt động ngoài trời, trong khi mạng có vị trí khá nhanh.

Một ví dụ mã tốt là ở đây: What is the simplest and most robust way to get the user's current location on Android?

Đối AsyncTask, nhìn http://developer.android.com/reference/android/os/AsyncTask.html

Ngoài ra còn rất nhiều mã ví dụ ở đây trên SO cho nó, ví dụ ở đây: Android Show a dialog until a thread is done and then continue with the program

EDIT: mã khái niệm:

thêm biến lớp

boolean hasLocation = false; 

cuộc gọi trong onCreate (không phải trong AsyncTask):

locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener); 
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener); 

sau đó trong locationListener.onLocationChanged, thay đổi giá trị một lần một vị trí được tìm thấy:

boolean hasLocation = false; 

AsyncTask: nghỉ vì nó là , nhưng không gọi

LocationHelper location = new LocationHelper(); 
location.getLocation(params[0], locationResult); 

ở đó, thay vào đó hãy làm

Long t = Calendar.getInstance().getTimeInMillies(); 
while (!hasLocation && Calendar.getInstance().getTimeInMillies()-t<30000)) { 
    Thread.Sleep(1000); 
};  

có thể có sự chậm trễ ở giữa là đủ.

+0

Cảm ơn điều này có vẻ hữu ích. Tôi nghĩ rằng công cụ GPS API không đồng bộ? Hay tôi vẫn cần triển khai điều này để ứng dụng chờ kết quả? Dựa trên các ví dụ sau: Vì vậy, tôi sẽ gọi myLocation.getLocation (this, locationResult) từ bên trong doInBackground (chuỗi cuối cùng ... args)? Tôi chỉ không thực sự hiểu khi onPostExecute (cuối cùng Void không sử dụng) sẽ được gọi là kết quả cuối cùng của công cụ MyLocation là gotLocation (vị trí cuối cùng vị trí)? điều gì sẽ xảy ra nếu bộ hẹn giờ hết giờ? –

+0

có những thứ gps là không đồng bộ, nhưng cho thấy một tiến bộ không phải là. do đó bạn cần bọc nó trong AsyncTask, vì hộp thoại tiến trình phụ thuộc vào trạng thái/kết quả gps của bạn. onPostExecute và onPreExecute chạy trên luồng chính của giao diện người dùng, do đó bạn cập nhật giao diện người dùng của mình ở đó, ví dụ: khi bạn đã sửa lỗi gps và cũng loại bỏ hộp thoại tiến trình trong đó. –

+0

Ok cảm ơn tôi sẽ cho phép điều này. Làm thế nào để onPostExecute biết khi nào tôi có bản sửa lỗi gps hoặc khi nó được thực hiện xong? tức là làm thế nào để nó biết khi nào một trong hai gotLocation() được gọi là hoặc bộ đếm thời gian chạy ra ngoài? –

12

tôi vẫn không thích cách làm việc này ở tất cả và có vẻ như cách phức tạp hơn nó nên nhưng cho đến khi một người nào đó cung cấp một cách tốt hơn tôi có nó làm việc cho bây giờ ...

Nếu ai đó đi qua điều này và đề xuất một kết quả sạch hơn nhiều để chỉ nhận được tọa độ vị trí hiện tại của người dùng chỉ một lần sau đó ngừng tìm kiếm sẽ được đánh giá rất nhiều !!

private LocationControl locationControlTask; 
private boolean hasLocation = false; 
LocationHelper locHelper; 

Từ onCreate() tôi gọi

locHelper = new LocationHelper(); 
locHelper.getLocation(context, locationResult); 
locationControlTask = new LocationControl(); 
locationControlTask.execute(this); 

sau đó tôi có aa lớp LocationControl tin

private class LocationControl extends AsyncTask<Context, Void, Void> 
    { 
     private final ProgressDialog dialog = new ProgressDialog(activityname.this); 

     protected void onPreExecute() 
     { 
      this.dialog.setMessage("Searching"); 
      this.dialog.show(); 
     } 

     protected Void doInBackground(Context... params) 
     { 
      //Wait 10 seconds to see if we can get a location from either network or GPS, otherwise stop 
      Long t = Calendar.getInstance().getTimeInMillis(); 
      while (!hasLocation && Calendar.getInstance().getTimeInMillis() - t < 15000) { 
       try { 
        Thread.sleep(1000); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      }; 
      return null; 
     } 

     protected void onPostExecute(final Void unused) 
     { 
      if(this.dialog.isShowing()) 
      { 
       this.dialog.dismiss(); 
      } 

      if (currentLocation != null) 
      { 
       useLocation(); 
      } 
      else 
      { 
       //Couldn't find location, do something like show an alert dialog 
      } 
     } 
    } 

Sau đó, một locationResult ..

public LocationResult locationResult = new LocationResult() 
    { 
     @Override 
     public void gotLocation(final Location location) 
     { 
      currentLocation = new Location(location); 
      hasLocation = true; 
     } 
    }; 

Ngoài ra để tránh bạn kéo tóc của bạn ra như tôi đã làm cho các lứa tuổi nhớ để ngăn chặn các nhiệm vụ kiểm soát vị trí nếu ai đó rời khỏi hoạt động sớm và cũng dừng cập nhật vị trí để ngăn chặn GPS chạy khi người dùng lá. Trong onStop() làm một cái gì đó như thế này:

locHelper.stopLocationUpdates(); 
locationControlTask.cancel(true); 

Cũng stopLocationUpdates trong lớp Location Helper nào sau đây:

public void stopLocationUpdates() 
{ 
locationManager.removeUpdates(locationListenerGps); 
locationManager.removeUpdates(locationListenerNetwork); 
} 

Chúc may mắn với nó, tôi cần nó ...

+6

đăng mã làm việc hoàn chỉnh (tức là github) sẽ là tuyệt vời cho bạn và cho chúng tôi :) – ant

0

Thay vào đó tạo một AsyncTask tại sao bạn không tạo một hộp ProgressDialog và loại bỏ nó trên public void gotLocation(final Location location){}? Bạn cũng có thể thêm onCancelListener vào hộp ProgressDialog và hủy bất kỳ yêu cầu vị trí hiện tại nào.

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