2013-06-15 18 views
9

Tôi đang phát triển một ứng dụng liệt kê các nhà hàng gần nhất với người dùng. Khi nút làm mới được nhấp, nút này sẽ liệt kê các nhà hàng cho vị trí hiện tại của người dùng. Tôi đang sử dụng Trình quản lý vị trí và chỉ yêu cầu cập nhật khi hoạt động đến tiền cảnh (onResume) để tránh việc sử dụng pin liên tục. Khi ứng dụng đi vào onPause(), các cập nhật vị trí sẽ bị dừng. Nó hoạt động tốt trên trình giả lập khi tôi chuyển các bản cập nhật thông qua thiết bị đầu cuối.Android locationManager requestLocationUpdates không hoạt động

Vấn đề: Khi tôi về thể chất thay đổi vị trí của tôi (nói lái xe 5 dặm) và tôi mở ứng dụng của tôi và các hoạt động để hiển thị các nhà hàng gần nhất, phải mất thời gian dài (4-5 phút) cho vị trí để làm mới và cho đến khi ứng dụng tiếp tục hiển thị các nhà hàng cho vị trí trước đó. Nhưng nếu tôi thay đổi vị trí của mình và truy cập Google Maps, sau đó mở ứng dụng nhà hàng của tôi, sau đó nó hoạt động ngay lập tức. Tôi đã đảm bảo rằng GPS được bật. Tôi có thể làm gì để Trình quản lý vị trí bắt đầu và làm mới vị trí ngay khi tôi mở hoạt động của mình? Cảm ơn bạn trước!

package com.mortley.android.restaurantsaver; 

public class NearbyRestaurantActivity extends ListActivity implements OnClickListener, LocationListener{ 
    private Button refreshButton, searchRestaurants; 
    ImageButton goToSearch; 
    private double[] lastKnownLocation; 
    private EditText locationEditText; 
    private LocationManager locManager; 
    private LocationListener locListener; 
    private boolean gps_enabled = false; 
    private boolean network_enabled = false; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.nearbyrestaurants); 
     refreshButton = (Button)findViewById(R.id.reloadButton); 
     refreshButton.setOnClickListener(this); 

     searchRestaurants = (Button)findViewById(R.id.searchButton); 
     searchRestaurants.setOnClickListener(this); 
     goToSearch = (ImageButton)findViewById(R.id.goLocationButton); 
     goToSearch.setOnClickListener(this); 
     locationEditText = (EditText)findViewById(R.id.addressTextBox); 
     locationEditText.setVisibility(View.GONE); 
     goToSearch.setVisibility(View.GONE); 

     locManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);//?? 


     locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 100, this); 

     //checks network connectivity 
     boolean checkConnection = isNetworkAvailable(); 
     if(!checkConnection){ 
      Toast.makeText(getApplicationContext(), "Check your Network Connectivity", Toast.LENGTH_LONG).show(); 
     } 

     if(checkConnection){ 
      //sets current location parameters for the user 
      lastKnownLocation = RestaurantHelper.getLastKnownLocation(this); 
      //Log.v("NearbyRestaurantActivity", "This"+this); 

      RestaurantApplication application = (RestaurantApplication) this.getApplication(); 
      RestaurantAdapter restaurantAdapter = new RestaurantAdapter(this, R.layout.restaurantrow, R.id.label,new ArrayList<RestaurantReference>()); 
      restaurantAdapter.setLastKnownLocation(lastKnownLocation); 


      //set a global variable for the RestaurantAdapter in the RestaurantApplication class. 
      application.setRestaurantAdapter(restaurantAdapter); 
      //Set the adapter first and then update it when the RestaurantHttpAsyncTask makes a web service call. 
      setListAdapter(restaurantAdapter); 
      //Make a webservice call in a different thread passing Keyword for URL as a string array. 
      RestaurantHttpAsyncTask m_progressTask; 
      String[] keywords = {"", "american", "asian", "italian","mexican"}; 
      //String[] keywords = {"indian"}; 
      m_progressTask = new RestaurantHttpAsyncTask(NearbyRestaurantActivity.this, keywords); 
      m_progressTask.setRestaurantAdapter(restaurantAdapter); 
      m_progressTask.execute(); 
     } 
    } 

    @Override 
    public void onClick(View v) { 
     //Refresh button helps to refresh the restaurant list on location change. Again it makes a call to the webservice using Async Task 
     if(v.getId() == refreshButton.getId()){ 


      try { 
       gps_enabled = locManager.isProviderEnabled(LocationManager.GPS_PROVIDER); 
      } catch (Exception ex) { 
       ex.printStackTrace(); 
      } 
      try { 
       network_enabled = locManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER); 
      } catch (Exception ex) { 
       ex.printStackTrace(); 
      } 

      // don't start listeners if no provider is enabled 
      if (!gps_enabled && !network_enabled) { 
       Toast.makeText(getApplicationContext(), "Sorry, Location is not determined. Please enable your Network Providers.", Toast.LENGTH_LONG).show(); 


      } 

      //check network connectivity before refresh 
      boolean checkConnection = isNetworkAvailable(); 
      if(!checkConnection){ 
       Toast.makeText(getApplicationContext(), "Check your Network Connectivity", Toast.LENGTH_LONG).show(); 
      } 
      if(checkConnection){ 

       RestaurantApplication application = (RestaurantApplication) this.getApplication(); 
       RestaurantAdapter restaurantAdapter = new RestaurantAdapter(this, R.layout.restaurantrow, R.id.label, new ArrayList<RestaurantReference>()); 
       restaurantAdapter.setLastKnownLocation(lastKnownLocation); 
       //set a global variable for the RestaurantAdapter in the RestaurantApplication class. 
       application.setRestaurantAdapter(restaurantAdapter); 
       //Set the adapter first and then update it when the RestaurantHttpAsyncTask makes a web service call. 
       setListAdapter(restaurantAdapter); 
       //Make a webservice call in a different thread passing Keyword for URL as a string array. 
       RestaurantHttpAsyncTask m_progressTask, m_progressTask1; 
       String[] keywords = {"", "american", "asian", "italian","mexican", "chinese", "indian"}; 
       //String[] keywords = {"Chinese"}; 
       m_progressTask = new RestaurantHttpAsyncTask(NearbyRestaurantActivity.this, keywords); 
       m_progressTask.setRestaurantAdapter(restaurantAdapter); 
       m_progressTask.execute(); 
      } 
     } 

     if(v.getId() == goToSearch.getId()){ 

      Activity child = this; 
      while(child.getParent() != null){ 
       child = child.getParent(); 
      } 
      TabGroup1Activity parent = (TabGroup1Activity)getParent(); 


      InputMethodManager imm = (InputMethodManager)getSystemService(
        Context.INPUT_METHOD_SERVICE); 
      imm.hideSoftInputFromWindow(locationEditText.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); 

      //changes ** restaurantAdapter to RestaurantAdapter1 to test & application to application1 
      RestaurantApplication application1 = (RestaurantApplication) this.getApplication(); 
      RestaurantAdapter restaurantAdapter1 = new RestaurantAdapter(this, R.layout.restaurantrow, R.id.label, new ArrayList<RestaurantReference>()); 
      restaurantAdapter1.setLastKnownLocation(lastKnownLocation); 
      //set a global variable for the RestaurantAdapter in the RestaurantApplication class. 
      application1.setRestaurantAdapter(restaurantAdapter1); 
      //Set the adapter first and then update it when the RestaurantHttpAsyncTask makes a web service call. 
      setListAdapter(restaurantAdapter1); 
      //Make a webservice call in a different thread passing Keyword for URL as a string array. 
      RestaurantHttpAsyncTaskTextSearch m_progressTask, m_progressTask1; 
      String keywords = locationEditText.getText().toString(); 
      if(keywords.equals("")){ 
       keywords = "Pizza in Palo Alto"; 
      } 
      keywords = keywords.replaceAll(" ", "%20"); 
      keywords = keywords.replaceAll(",", "%20"); 
      m_progressTask = new RestaurantHttpAsyncTaskTextSearch (NearbyRestaurantActivity.this, keywords); 
      m_progressTask.setRestaurantAdapter(restaurantAdapter1); 
      m_progressTask.execute(); 

      locationEditText.setVisibility(View.GONE); 
      goToSearch.setVisibility(View.GONE); 
     } 
     if(v.getId() == searchRestaurants.getId()){ 
      if(goToSearch.isShown() == true){ 
       goToSearch.setVisibility(View.GONE); 
       locationEditText.setVisibility(View.GONE); 
      } 
      else if(goToSearch.isShown() == false){ 
       //check network connectivity before refresh 
       boolean checkConnection = isNetworkAvailable(); 
       if(!checkConnection){ 
        Toast.makeText(getApplicationContext(), "Check your Network Connectivity", Toast.LENGTH_LONG).show(); 
       } 
       if(checkConnection){ 
        goToSearch.setVisibility(View.VISIBLE); 
        locationEditText.setVisibility(View.VISIBLE); 

       } 
      } 
     } 

    } 
    //Method to check network connectivity 
    public boolean isNetworkAvailable() { 
     ConnectivityManager connectivityManager 
     = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE); 
     NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo(); 
     if (activeNetworkInfo != null && activeNetworkInfo.isConnectedOrConnecting()) { 
      //Log.d("network", "Network available:true"); 
      return true; 
     } else { 
      //Log.d("network", "Network available:false"); 
      return false; 
     } 
    } 

    @Override 
    protected void onResume() { 
     super.onResume(); 
     locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 50, 100, this); 
     //Log.v("NearbyRestaurantActivity", "In OnResume()"); 
    } 

    @Override 
    protected void onPause() { 
     super.onPause(); 
     locManager.removeUpdates(this); 
     //Log.v("NearbyRestaurantActivity", "In onPause()"); 

    } 

    @Override 
    public void onLocationChanged(Location location) { 
     // TODO Auto-generated method stub 

    } 

    @Override 
    public void onProviderDisabled(String provider) { 
     // TODO Auto-generated method stub 

    } 

    @Override 
    public void onProviderEnabled(String provider) { 
     // TODO Auto-generated method stub 

    } 

    @Override 
    public void onStatusChanged(String provider, int status, Bundle extras) { 
     // TODO Auto-generated method stub 

    } 
} 






public class RestaurantHelper { 

public static double[] getLastKnownLocation(Activity activity){ 
    double lat = 0.0; 
    double lon = 0.0; 
    LocationManager lm = (LocationManager) activity.getSystemService(Context.LOCATION_SERVICE);  
    Location location = lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER); 

    if(location == null){ 
     lat = 0.0; 
     lon = 0.0; 
    } 
    else{ 
     //Log.v("Latitude", Double.toString(location.getLatitude())); 
     //Log.v("Longitude", Double.toString(location.getLongitude())); 

     lat = location.getLatitude(); 
     lon = location.getLongitude(); 
    } 
    return new double[]{lat,lon}; 
} 
} 
+0

Có vẻ như bạn đang thiếu một số mã - "RestaurantHelper.getLastKnownLocation (this)" là gì và nó hoạt động như thế nào? Ngoài ra, bạn không có mã trong "onLocationChanged()", đây là nơi các bản cập nhật từ locManager.requestLocationUpdates() chuyển vào các Vị trí mới. Cuối cùng, bạn không hiển thị mã OnClickListener. –

+0

Xin lỗi, tôi đã thêm mã cho lớp RestaurantHelper. – Sia

+0

http://android-developers.blogspot.com/2011/06/deep-dive-into-location.html (Và xem lại nội dung mới, như nhà cung cấp vị trí hợp nhất.) –

Trả lời

8

Lý do chính tại sao bạn lại không nhận được cập nhật thông tin vị trí một cách nhanh chóng là bạn đang dựa trên NETWORK_PROVIDER trong phương pháp RestaurantHelper.getLastKnownLocation(), nhưng việc đăng ký một LocationListener cho GPS_PROVIDER trong onCreate().

Vì vậy, mã này trong RestaurantHelper.getLastKnownLocation():

Location location = lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER); 

... nên được thay đổi:

Location location = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER); 

Về lý thuyết, điều này sau đó sẽ cho bạn vị trí GPS mới nhất, mà cần phải có được làm mới khi bạn đăng ký người nghe. Ngược lại, bạn cũng có thể thay đổi để nghe số NETWORK_PROVIDER trong onCreate() và để lại RestaurantHelper.getLastKnownLocation(). Tùy thuộc vào yêu cầu độ chính xác của bạn - nếu bạn muốn vị trí chính xác cao trả lại vị trí gần nhất cho cấp độ tòa nhà gần nhất (ví dụ: 5-30m), bạn nên sử dụng GPS_PROVIDER. Tuy nhiên, nếu bạn có thể sống với độ chính xác thô hơn, thì NETWORK_PROVIDER thường trả về một vị trí mới nhanh hơn nhiều so với GPS, đặc biệt nếu bạn ở trong nhà và đôi khi điều này có thể khá chính xác nếu được lấy từ WiFi.

cách tiếp cận khác sẽ được nghe cả GPS_PROVIDERNETWORK_PROVIDER bằng cách đăng ký cả hai qua hai requestLocationUpdates() dòng trong onCreate(), và sau đó kiểm tra để xem hầu hết các dấu thời gian gần đây về Vị trí từ lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);, và sử dụng một trong đó đã được cập nhật gần đây .

Tôi cũng muốn giới thiệu những thay đổi sau đây để làm cho mã của bạn đáng tin cậy về một số lượng lớn các thiết bị Android:

  1. Xác định tham số requestLocationUpdates()minDistance như 0 khi nghe cho GPS hoặc vị trí NETWORK cập nhật - tham số minDistance có một lịch sử không đáng tin cậy và không thể đoán trước theo cách nó được các OEM giải thích, cho đến Android 4.1.
  2. Chuyển sang Fused Location Provider mới - điều này sẽ đáng tin cậy hơn nhiều khi gọi phương thức getLastKnownLocation() so với API vị trí khung Android và nhất quán hơn trên các thiết bị khác nhau. Lưu ý rằng điều này dựa trên SDK dịch vụ của Google Play, chỉ khả dụng trên Android 2.2 trở lên.
+0

Nhà cung cấp vị trí hợp nhất này bạn nói đến ở đâu? Liên kết đi tới tài liệu Android về "Nhận cập nhật vị trí". Không đề cập đến bất kỳ nhà cung cấp "hợp nhất" ở đó. – Nilzor

+0

Nếu bạn đang sử dụng vị trí Dịch vụ của Google Play (ví dụ: [LocationClient'] (http://developer.android.com/reference/com/google/android/gms/location/LocationClient.html), hiện tại không được chấp nhận hoặc ['LocationServices'] (http://developer.android.com/reference/com/google/android/gms/location/LocationServices.html)), bạn đang sử dụng nhà cung cấp được hợp nhất. Nhà cung cấp hợp nhất là nhà cung cấp duy nhất có sẵn thông qua các triển khai này. –

+0

Nhờ đề cập đến Nhà cung cấp vị trí hợp nhất. –

5

tôi có 2 lời khuyên cho bạn

  1. LocationClient video, là phương pháp mới để làm công cụ địa điểm. Nó có những cải tiến so với Trình quản lý vị trí có thể là một nỗi đau để quản lý và phát triển.

  2. Nếu bạn cần sử dụng LocationManager, bạn phải biết rằng requestLocationUpdates là lỗi (rất lỗi). Vì tất cả các triển khai của nó trên phần cứng tùy chỉnh khác nhau. Có một hack/workaround hoạt động. Trước khi bạn gọi requestLocationUpdates, chỉ cần kick bắt đầu nó như sau

Code:

HomeScreen.getLocationManager().requestLocationUpdates(
    LocationManager.NETWORK_PROVIDER, 0, 0, new LocationListener() { 
     @Override 
     public void onStatusChanged(String provider, int status, Bundle extras) { 
     } 
     @Override 
     public void onProviderEnabled(String provider) { 
     } 
     @Override 
     public void onProviderDisabled(String provider) { 
     } 
     @Override 
     public void onLocationChanged(final Location location) { 
     } 
    }); 
+0

Điều khởi động này không giúp [Android Bug 57707] (https://code.google.com/p/android/issues/detail?id=57707) ảnh hưởng đến ít nhất nhà cung cấp mạng. –

+0

Chỉ cần đặt câu trả lời của tôi ở đó. Cho phép chờ đợi và nghe lại từ họ. – Siddharth

2

requestLocationUpdates là lỗi. Sử dụng nhà cung cấp mạng luôn để kích hoạt onLocationChanged (...)

locManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000, 100, this) 

chỉ sau khi sử dụng nhà cung cấp mạng cung cấp dịch vụ sử dụng gps back to back:

locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 100, this) 

đừng quên kiểm tra xem gps được kích hoạt hay không trước yêu cầu cập nhật vị trí bằng gps.

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