2011-12-31 8 views
34

से कोई स्थान प्राप्त करते समय एक मृत धागे पर हैंडलर को संदेश भेजना मेरे ऐप को नियमित आधार पर स्थान फ़िक्स की आवश्यकता होती है, भले ही फ़ोन जागृत न हो। ऐसा करने के लिए, मैं CommonsService द्वारा प्रदान किए गए पैटर्न के साथ IntentService का उपयोग कर रहा हूं। https://github.com/commonsguy/cwac-wakefulकिसी इंटेंट सेवा

स्थान सुधार प्राप्त करने के लिए, मैं फेडरर नामक सदस्य द्वारा प्रदान किए गए निम्नलिखित कोड पर भरोसा करता हूं। What is the simplest and most robust way to get the user's current location on Android?। मैंने अंतिम ज्ञात स्थान

दोनों संयुक्त रूप से ठीक काम करते हैं, तो मैं पूरी तरह से ठीक काम करता हूं: मैं एक गतिविधि में फेडरर की कक्षा से एक स्थान तय कर सकता हूं, और मैं कुछ बुनियादी चीजें कर सकता हूं (जैसे लॉगिंग कुछ) Commonsware वर्ग का उपयोग कर।

समस्या तब होती है जब मैं Commonsware के WakefulIntentService उपclass से स्थान फ़िक्स प्राप्त करने का प्रयास कर रहा हूं। स्थान लिस्टनर स्थान अपडेट पर प्रतिक्रिया नहीं करते हैं और मुझे ये चेतावनियां मिलती हैं (मुझे अभी तक धागे, हैंडलर, ... की सूक्ष्मता नहीं मिलती है)। क्या कोई मुझे समझने में मदद कर सकता है कि समस्या क्या है? धन्यवाद और मैं आप सभी एक बहुत ही नया साल मुबारक हो :)

12-31 14:09:33.664: W/MessageQueue(3264): Handler (android.location.LocationManager$ListenerTransport$1) {41403330} sending message to a  Handler on a dead thread 
12-31 14:09:33.664: W/MessageQueue(3264): java.lang.RuntimeException: Handler (android.location.LocationManager$ListenerTransport$1) {41403330} sending message to a Handler on a dead thread 
12-31 14:09:33.664: W/MessageQueue(3264): at android.os.MessageQueue.enqueueMessage(MessageQueue.java:196) 
12-31 14:09:33.664: W/MessageQueue(3264): at android.os.Handler.sendMessageAtTime(Handler.java:473) 
12-31 14:09:33.664: W/MessageQueue(3264): at android.os.Handler.sendMessageDelayed(Handler.java:446) 
12-31 14:09:33.664: W/MessageQueue(3264): at android.os.Handler.sendMessage(Handler.java:383) 
12-31 14:09:33.664: W/MessageQueue(3264): at android.location.LocationManager$ListenerTransport.onLocationChanged(LocationManager.java:193) 
12-31 14:09:33.664: W/MessageQueue(3264): at android.location.ILocationListener$Stub.onTransact(ILocationListener.java:58) 
12-31 14:09:33.664: W/MessageQueue(3264): at android.os.Binder.execTransact(Binder.java:338) 
12-31 14:09:33.664: W/MessageQueue(3264): at dalvik.system.NativeStart.run(Native Method) 

यह मेरा WakefulIntentService उपवर्ग है इच्छा:

public class AppService extends WakefulIntentService { 
public static final String TAG = "AppService"; 
public AppService() { 
    super("AppService"); 
} 

public LocationResult locationResult = new LocationResult() { 
    @Override 
    public void gotLocation(final Location location) { 
     if (location == null) 
      Log.d(TAG, "location could not be retrieved"); 
     else 
      sendMessage(location); 
    } 
}; 

@Override 
protected void doWakefulWork(Intent intent) { 
    PhoneLocation myLocation; 
    myLocation = new PhoneLocation(); 
    myLocation.getLocation(getApplicationContext(), locationResult); 
} 

और यहाँ Fedor की क्लास की एक प्रति (थोड़ा संशोधित: जीपीएस और न ही पिछले की कोई जरूरत नहीं ज्ञात स्थान)

public class PhoneLocation { 
public static String TAG = "MyLocation"; 
Timer timer1; 
LocationManager lm; 
LocationResult locationResult; 
boolean gps_enabled=false; 
boolean network_enabled=false; 

public boolean getLocation(Context context, LocationResult result) 
{ 
    //I use LocationResult callback class to pass location value from MyLocation to user code. 
    locationResult=result; 
    if(lm==null) lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); 

    //exceptions will be thrown if provider is not permitted. 
    try{gps_enabled=lm.isProviderEnabled(LocationManager.GPS_PROVIDER);}catch(Exception ex){} 
    try{network_enabled=lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);}catch(Exception ex){} 

    //don't start listeners if no provider is enabled 
    if(!gps_enabled && !network_enabled) 
     return false; 

    if(network_enabled) lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListenerNetwork); 

    timer1=new Timer(); 
    timer1.schedule(new ReturnNullLocation(), 20000); 
    return true; 
} 

LocationListener locationListenerNetwork = new LocationListener() { 
    public void onLocationChanged(Location location) { 
     timer1.cancel(); 
     locationResult.gotLocation(location); 
     lm.removeUpdates(this); 
    } 
    public void onProviderDisabled(String provider) {} 
    public void onProviderEnabled(String provider) {} 
    public void onStatusChanged(String provider, int status, Bundle extras) {} 
}; 

class ReturnNullLocation extends TimerTask { 
    @Override 
    public void run() { 
      lm.removeUpdates(locationListenerNetwork); 
      locationResult.gotLocation(null); 
    } 
} 

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

} 

}

उत्तर

33

आप सुरक्षित रूप से एक ०१२३५४६८२० से श्रोताओं पंजीकृत नहीं कर सकता, IntentServiceonHandleIntent() (ए.के.ए., doWakefulWork()) के रूप में जल्द ही चला जाता है। इसके बजाए, आपको नियमित सेवा का उपयोग करने की आवश्यकता होगी, साथ ही टाइमआउट जैसे विवरण संभाल लेंगे (उदा।, उपयोगकर्ता बेसमेंट में है और जीपीएस सिग्नल नहीं मिल सकता है)।

+1

यह एक आकर्षण की तरह काम करता है! आपको बहुत - बहुत धन्यवाद! मैंने अपने एप्लिकेशन सबक्लास में अलार्म सेट किया है और वहां startLocationPoll() और stopLocationPoll() विधियों का निर्माण किया है। नया साल मुबारक हो! – znat

+0

जब मैं लिंक पर उदाहरण का उपयोग करता हूं .... मुझे मिल गया ... "ई/लोकेशन पोलर (442): अवैध इरादा - कोई प्रदाता नहीं है" ... कोई सुराग कृपया? – user836026

+1

@ user836026: आप 'Intent' पर' LocationPoller.EXTRA_PROVIDER' अतिरिक्त प्रदान करने में विफल रहे, जो दर्शाता है कि कौन सा प्रदाता उपयोग करना है। यदि आपके पास इस घटक पर अतिरिक्त प्रश्न हैं, तो कृपया टिप्पणियां पोस्ट करने के बजाय "प्रश्न पूछें" बटन का उपयोग करें। – CommonsWare

6

मेरे जैसे अन्य लोगों के लिए: मुझे AsyncTask से संबंधित एक ही समस्या थी। जैसा कि मैं समझता हूं, वह कक्षा मानती है कि इसे यूआई (मुख्य) थ्रेड पर प्रारंभ किया गया है।

@Override 
public void onCreate() { 
    // workaround for http://code.google.com/p/android/issues/detail?id=20915 
    try { 
     Class.forName("android.os.AsyncTask"); 
    } catch (ClassNotFoundException e) {} 
    super.onCreate(); 
} 

(भूल AndroidManifest.xml में यह उल्लेख करने के लिए नहीं है::

<application 
    android:icon="@drawable/ic_launcher" 
    android:label="@string/app_name" 
    android:name="MyApplication" 
    > 

)

12

का संभावित हल (कई संभव में से एक) MyApplication कक्षा में निम्नलिखित जगह है मेरे पास एक समान स्थिति है, और मैंने एंड्रॉइड लूपर सुविधा का अच्छा प्रभाव डाला है: http://developer.android.com/reference/android/os/Looper.html

वस्तुतः, बस समारोह श्रोता की स्थापना बुला के बाद, मैं फोन:

Looper.loop(); 

ब्लॉक वर्तमान धागा यह इतना मरता नहीं है यही कारण है कि लेकिन एक ही समय में की सुविधा देता है यह घटनाओं की प्रक्रिया है, तो आप आपके श्रोता को बुलाए जाने पर अधिसूचित होने का मौका मिलेगा। श्रोता कहलाते समय एक साधारण लूप आपको अधिसूचित होने से रोक देगा।

और जब श्रोता कहा जाता है और मैं अपने डेटा संसाधन पूरा हो गया हूँ, मैं डाल:

Looper.myLooper().quit(); 
+1

मैं वही करता हूं। लेकिन मैं जोड़ता हूं (Looper.myLooper() == शून्य) Looper.prepare(); Looper.loop() से पहले; –

+0

मैं कुछ विशिष्ट समय के बाद टाइमआउट में एक अलग धागा भी चलाता हूं (नेटवर्क के लिए 5-15 सेकंड, जीपीएस के लिए 45-120 सेकेंड)। क्योंकि अन्यथा Looper.loop() डिवाइस को हमेशा के लिए जागृत रखेगा। –

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