2010-08-15 14 views
26

मैं एक ऐप लिख रहा हूं जिसके लिए उपयोगकर्ता के वर्तमान स्थान की आवश्यकता है (अंतिम अज्ञात स्थान बहुत उपयोगी नहीं होगा) और डेटाबेस से ली गई सभी निकटतम "वस्तुओं" की एक सूची प्रदर्शित करता है।एंड्रॉइड एक बार जीपीएस स्थान ढूंढता है, लोडिंग संवाद दिखा रहा है

मुझे अच्छी तरह से काम करने वाली सबसे नज़दीकी वस्तुओं की खोज मिल गई है, लेकिन समय के लिए केवल एक हार्डकोडेड अक्षांश और देशांतर स्थान का उपयोग कर रहा है, लेकिन अब यह वास्तविक स्थान खोजने के लिए लागू करने का समय है।

कोई भी इस बात का एक उदाहरण प्रदान कर सकता है कि ऐप को पृष्ठभूमि में वर्तमान ठीक स्थान कैसे ढूंढें और ऐप प्रतीक्षा करें। व्यक्ति को स्थानांतरित होने के बाद मुझे केवल अपडेट की आवश्यकता नहीं होती है। मैंने एक स्थान श्रोता लागू किया है, हालांकि मुझे लगता है कि एक जीपीएस फिक्स धीमा हो सकता है। मैंने अंतिम ज्ञात स्थान का उपयोग करके अन्य स्थान देखे हैं या स्थान श्रोता को कार्यान्वित कर रहे हैं जो चलाना और अपडेट करना जारी रखता है, हालांकि मेरी गतिविधि को स्थान निर्देशांक की आवश्यकता होती है इससे पहले कि यह ऐप को क्रैश कर दे। इसकी खोज करते समय मुझे एक प्रगति संवाद दिखाने की जरूरत है।

पृष्ठभूमि में एक बार स्थानसूचीकर्ता कैसे चला सकता है और फिर स्थान ढूंढने के बाद स्थान अपडेट को हटा सकता है। 20-30 सेकेंड के बाद मुझे जीपीएस स्थान या टाइमआउट होने तक इंतजार करने के लिए शेष एप्लिकेशन की आवश्यकता है। मैं एक प्रोग्रेसडियलॉग अप करना चाहता हूं ताकि उपयोगकर्ता जानता है कि कुछ चल रहा है, लेकिन यह केवल कताई लोडिंग एनीमेशन होना चाहिए जो कि प्रतिशत या कुछ भी नहीं है। यदि संभव हो तो मैं चाहता हूं कि उपयोगकर्ता संवाद को रद्द करने में सक्षम हो, यदि वे प्रतीक्षा करने में बीमार हैं, तो वे इसके बजाय उपनगर टाइप करके खोज सकते हैं।

मैं इसे थ्रेड के साथ करने की कोशिश कर रहा हूं लेकिन मुझे लगता है कि यह होना चाहिए और अभी भी काम नहीं कर रहा है, इससे कहीं अधिक जटिल हो रहा है। आईफोन पर यह बहुत आसान है?

क्या कोई इसे करने का एक अच्छा तरीका प्रदान कर सकता है, मैं इस पर एक सप्ताह के लिए अपने बालों को फेंक रहा हूं और यह वास्तव में मुझे बाकी ऐप पूर्ण होने की तारीख के लिए शेड्यूल के पीछे रख रहा है।
* वर्तमान निर्देशांक
खोजें * दिखाएँ प्रगति संवाद जबकि हो रही स्थान
* एप्लिकेशन सफल स्थान के लिए इंतजार करना या एक निश्चित समय के बाद छोड़ देना सक्षम हो कहें:

सारांश में मैं करना चाहते हैं?
* यदि सफल: प्रगति संवाद को खारिज करें और वस्तुओं को ढूंढने के लिए मेरे अन्य तरीकों को चलाने के लिए निर्देशांक का उपयोग करें।
* यदि स्थान प्राप्त करने में विफल: प्रगति संवाद को खारिज करें और त्रुटि संदेश दिखाएं, और उपयोगकर्ता को खोज गतिविधि पर जाने के लिए मेनू का उपयोग करने के लिए प्रोत्साहित करें।
* उपयोगकर्ता द्वारा मानचित्र से वर्तमान स्थान दिखाने के लिए, मेनू से मानचित्र दृश्य चुनने के लिए इन निर्देशांकों का उपयोग करें और डेटाबेस से उनके निर्देशांक का उपयोग करके सभी आस-पास के आइटमों पर पिन डाले गए हैं।

धन्यवाद दोस्तों, मुझे उम्मीद है कि मैंने खुद को काफी समझाया है। कोई सवाल सिर्फ पूछता है, मैं नियमित रूप से जांच करूँगा क्योंकि मैं इस भाग को पूरा करने के इच्छुक हूं। चीयर्स

संपादित
कोड के रूप में अनुरोध

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

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); 
    } 
} 

यह वास्तव में एक बार वर्तमान स्थान प्राप्त करने के लिए एक बड़े प्रयास की तरह लगता है? मुझे अपडेट या कुछ भी चाहिए? क्या परिणाम के लिए एप्लिकेशन का इंतजार करने का कोई आसान तरीका नहीं है? मैं इस पर इतने लंबे समय से अटक गया हूं।

+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

उत्तर

17

उपयोग एक AsyncTask और दोनों का उपयोग network_provider gps_provider है, जो दो श्रोताओं का मतलब है के रूप में भी। जीपीएस को ठीक करने में अधिक समय लगता है, शायद कभी-कभी एक मिनट और केवल सड़क पर काम करता है, जबकि नेटवर्क को बहुत तेज़ी से स्थान मिलता है।

एक अच्छा कोड उदाहरण यहाँ है: What is the simplest and most robust way to get the user's current location on Android?

AsyncTask के लिए, देखने के http://developer.android.com/reference/android/os/AsyncTask.html

भी कई कोड उदाहरण यहां इतने पर इसके लिए कर रहे हैं, उदाहरण के लिए यहाँ के लिए,: Android Show a dialog until a thread is done and then continue with the program

संपादित करें: कोड अवधारणा:

कक्षा परिवर्तनीय

जोड़ें OnCreate (AsyncTask में नहीं) में
boolean hasLocation = false; 

कॉल:

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

locationListener.onLocationChanged में, मूल्य बदल एक बार एक स्थान पाया जाता है:

boolean hasLocation = false; 

AsyncTask: के रूप में यह है छुट्टी , लेकिन

LocationHelper location = new LocationHelper(); 
location.getLocation(params[0], locationResult); 
पर कॉल न करें वहाँ

, बजाय शायद में बीच पर्याप्त होगा देरी से

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

है।

+0

धन्यवाद यह मददगार लगता है। मैंने सोचा कि जीपीएस एपीआई सामान वैसे भी असीमित था? या ऐप को परिणाम के लिए इंतजार करने के लिए अभी भी इसे लागू करने की आवश्यकता है? उन उदाहरणों के आधार पर: तो क्या मैं doLBackground (अंतिम स्ट्रिंग ... args) के भीतर से myLocation.getLocation (यह, locationResult) को कॉल करूंगा? मैं वास्तव में समझ में नहीं आता कि ऑनपोस्टएक्सक्यूट (अंतिम शून्य अप्रयुक्त) को माइलोकेशन सामान का अंतिम परिणाम मिल जाएगा स्थान (अंतिम स्थान स्थान)? टाइमर खत्म होने पर भी क्या होता है? –

+0

हां जीपीएस सामान एसिंक है, लेकिन प्रगति दिखाना नहीं है। इसलिए आपको इसे AsyncTask में लपेटने की आवश्यकता है, क्योंकि प्रगति संवाद आपके जीपीएस स्थिति/परिणामों पर निर्भर करता है। onPostExecute और onPreExecute UI मुख्य थ्रेड पर चलाएं, इसलिए आप वहां अपना यूआई अपडेट करते हैं, यानी एक बार जब आप उदाहरण के लिए एक जीपीएस तय करते हैं, और वहां प्रगति संवाद को भी खारिज कर देते हैं। –

+0

ठीक है धन्यवाद, मैं इसे एक दूंगा। onPostExecute कैसे पता चलता है जब मेरे पास एक जीपीएस तय होता है या जब इसे निष्पादित किया जाता है? यानी यह कैसे पता चलता है कि जब कोई स्थान मिला() कहा जाता है या टाइमर समाप्त हो जाता है? –

12

मैं अभी भी पसंद नहीं है कि यह कैसे सब पर काम करता है और जिस तरह से और अधिक जटिल की तुलना में यह होना चाहिए लगता है, लेकिन जब तक किसी को एक बेहतर तरीका मैं इसे अभी के लिए काम है ... प्रदान करता है

किसी भर आता है तो यह और उपयोगकर्ता के वर्तमान स्थान को केवल एक बार समन्वयित करने के लिए एक बेहतर बेहतर क्लीनर परिणाम का सुझाव देता है, फिर यह देखना बंद कर देता है कि इसकी सराहना की जाएगी !!

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

onCreate से() मैं फोन

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

मैं तो आ निजी वर्ग LocationControl

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

फिर एक locationResult है ..

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

भी से बचने के लिए आप खींच रहे हैं आपके बालों को मैंने उम्र के लिए किया था जैसे कि कोई स्थान गतिविधि को छोड़ देता है और उपयोगकर्ता छोड़ने पर जीपीएस को चलाने से रोकने के लिए स्थान अपडेट को रोकता है। onStop() में कुछ इस तरह करते हैं:

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

इसके साथ गुड लक, मैं यह आवश्यक ...

+6

पूर्ण कार्य कोड पोस्ट करना (यानी गितूब) आपके लिए और हमारे लिए भी शानदार होगा :) – ant

0

बजाय:

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

भी स्थान हेल्पर कक्षा में निम्नलिखित करता stopLocationUpdates एक AsyncTask बनाने के लिए आपने ProgressDialog बॉक्स क्यों नहीं बनाया और इसे public void gotLocation(final Location location){} पर खारिज कर दिया? आप प्रोग्रेसडिअलॉग बॉक्स पर ऑन कैंसल लिस्टनर भी जोड़ सकते हैं और किसी भी मौजूदा स्थान अनुरोध को रद्द कर सकते हैं।

संबंधित मुद्दे