2011-07-08 11 views
7

मैंने अपने नए एप्लिकेशन में एक सेवा शुरू की है। एक अधिसूचना के साथ, सेवा अग्रभूमि है। जब यह एवीडी 2.1 एपीआई लेवल 7 में चलाया जाता है, तो सब ठीक काम करता है। लेकिन जब यह एक सैमसंग गैलेक्सी टैब पर जिंजरब्रेड चला रहा है, तो सेवा शुरू होगी (आइकन और ऐप नाम अधिसूचना क्षेत्र के शीर्ष पर दिखाई देगा), लेकिन कुछ सेकंड बाद, सेवा गायब हो जाती है। लॉग में अंतिम प्रविष्टि जो मैं देख सकता हूं वह मेरे ऐप से जुड़ा हुआ है, मेरे Log.d ("टैगलाइन", "रिटर्निंग" + START_STICKY) का परिणाम है, जो तुरंत "वापस START_STICKY" से पहले होता है; मेरी सेवा का onStartCommand ओवरराइड में, के रूप में इस प्रकार है:START_STICKY, अग्रभूमि एंड्रॉइड सेवा नोटिस के बिना दूर जाती है

@Override 
public int onStartCommand(Intent intent, int flags, int startId) { 

    int rc ; 
    Log.d("Taglines","onStartCommand()"); 
    Toast.makeText(this, "Starting service TagsManager", Toast.LENGTH_SHORT).show(); 
    Log.d("Taglines","Calling super.onStartCommand()"); 
    rc = super.onStartCommand(intent,flags,startId); 
    Log.d("Taglines","super.onStartCommand return code was " + rc); 
    createNotification(INITIAL_NOTIFICATION_TEXT); 
    Log.d("Taglines","Returning with " + START_STICKY); 
    return START_STICKY ; 
} 

अधिसूचना इस तरह सेट किया गया है:

D/Taglines(21863): Starting service 
D/Taglines(21863): TagsManager(nullary) completed 
D/Taglines(21863): onStartCommand() 
D/Taglines(21863): Calling super.onStartCommand() 
D/Taglines(21863): super.onStartCommand eturn code was 2 
D/Taglines(21863): createNotification called 
D/Taglines(21863): Obtained reference to Notification Manager 
D/Taglines(21863): createNotificacion() .. getApplicationContext 
D/Taglines(21863): createNotificacion() ... passing notification 
D/Taglines(21863): Starting foreground 
D/Taglines(21863): Started 
D/Taglines(21863): Returning with 1 
:

इस 'adb logcat "जब सेवा प्रारंभ होने से परिणाम है

उसके बाद, कुछ विशेष नहीं (पीआईडी ​​21863 से कुछ भी नहीं)। बस का एक समूह:

D/KeyguardViewMediator( 302): setHidden false 
D/KeyguardViewMediator( 302): setHidden false 
D/KeyguardViewMediator( 302): setHidden false 
D/KeyguardViewMediator( 302): setHidden false 
D/KeyguardViewMediator( 302): setHidden false 
W/InputManagerService( 302): Window already focused, ignoring focus gain of:   [email protected] 
D/KeyguardViewMediator( 302): setHidden false 
D/KeyguardViewMediator( 302): setHidden false 
D/KeyguardViewMediator( 302): setHidden false 
D/KeyguardViewMediator( 302): setHidden false 
D/KeyguardViewMediator( 302): setHidden false 
D/KeyguardViewMediator( 302): setHidden false 
D/KeyguardViewMediator( 302): setHidden false 
D/KeyguardViewMediator( 302): setHidden false 
D/KeyguardViewMediator( 302): setHidden false 

मुझे नहीं लगता कि यह इस मामले में आवश्यक है, लेकिन यहाँ AndroidManifest.xml के संबंधित भाग है:

<service android:name=".TagsManager" 
      android:exported="false"> 
    </service> 

मैं कहाँ गलत हो गया हो सकता है? मैं कौन सी जानकारी प्रदान कर सकता हूं?

+0

हमम ... मैं startForeground के बारे में और अधिक पढ़ता हूं, और ऐसा लगता है कि यह वास्तव में कुछ कार्रवाई करने के बजाए अधिसूचना ऑब्जेक्ट पर ध्वज सेट करता है। तो एक सनकी पर, मैंने अनुक्रम को उलट दिया ताकि अब प्रारंभिक भूमि अधिसूचना प्रबंधक से पहले हो। अब तक, यह बहुत अच्छा लग रहा है। तो अब मैं उस उदाहरण की तलाश कर रहा हूं जिसने मुझे दूसरी तरफ ऐसा करने का नेतृत्व किया ... – Dennis

+0

अफसोस की बात है कि उस अनुक्रम को उलटने की सफलता अल्पकालिक थी। ऐसा लगता है कि चिपचिपा "छड़ी" होगा या नहीं, यह एक जुआ का थोड़ा सा लगता है। इस सेवा को शुरू करने के प्रयासों के _many_ दर्जनों प्रयासों के साथ, मैंने अभी तक तीन बार शुरू किया है। :( – Dennis

+0

ठीक है, क्या आपका गैलेक्सी टैब कम स्मृति की स्थिति का अनुभव कर रहा था, या शायद आपकी सेवा मुख्य धागे पर कुछ स्मृति गहन कर रही थी? –

उत्तर

10

कुछ बातें:

  1. mNotificationManager.notify(NOTIFICATION_ID, notification); से छुटकारा। startForeground() आपके लिए अधिसूचना आइकन प्रदर्शित करता है।

  2. अग्रभूमि Service एस अभी भी मारे जा सकते हैं, वे होने की संभावना कम है।

  3. 2.3 में एक बग है (सुनिश्चित नहीं है कि यह अभी तक तय किया गया है) जहां Service मारे गए और पुनरारंभ किया गया है, तो इसके onStartCommand() को फिर से नहीं बुलाया जाएगा। इसके बजाय आपको onCreate() में कोई भी सेटिंग करने की आवश्यकता होगी।

+0

बहुत बहुत धन्यवाद; यह सब समझ में आता है। मैंने जो कहा है, मैंने कोशिश की है, और इसलिए अब तक यह सकारात्मक दिख रहा है। – Dennis

+0

+1 आपको बहुत बहुत धन्यवाद। 2.3 में बग, आईओएस में बग ... यदि ओएस में हर जगह बग है तो मेरे क्लाइंट के लिए एक सॉफ्टवेयर कैसे लिखें :) - हाँ, मंच के साथ स्वतंत्र ढांचे के साथ! :) मैंने START_STICKY और ऑनस्ट्रोय() को कभी-कभी फिर से बनाया होगा ... –

1

दोनों कोड केवल प्रासंगिक है जब स्मृति से बाहर फोन रन और Service को मारता है इससे पहले कि यह निष्पादित नहीं हो रहे हैं। START_STICKY ओएस को पर्याप्त स्मृति के बाद सेवा को फिर से बनाने के लिए कहता है और एक शून्य उद्देश्य के साथ onStartCommand() पर कॉल करें। START_NOT_STICKY ओएस को फिर से सेवा को पुनर्जीवित करने से परेशान नहीं करता है। एक तीसरा कोड START_REDELIVER_INTENT भी है जो ओएस को Service को फिर से बनाने के लिए कहता है और उसी उद्देश्य को onStartCommand() पर पुनः वितरित करता है।

This article डियान हैकबर्न ने आधिकारिक दस्तावेज़ीकरण के बाद इसकी पृष्ठभूमि को बेहतर समझाया।

यहाँ महत्वपूर्ण हिस्सा एक नया परिणाम, समारोह से वापस लौटे प्रणाली को इस सेवा के साथ क्या करना चाहिए कह कोड अगर इसकी प्रक्रिया मार दिया जाता है, जबकि यह चल रहा है है:

START_STICKY मूल रूप से रूप में ही है पिछला व्यवहार, जहां सेवा "प्रारंभ" छोड़ी गई है और बाद में सिस्टम द्वारा पुनरारंभ किया जाएगा। प्लेटफॉर्म के पिछले संस्करणों में से एकमात्र अंतर यह है कि यह है, यदि यह पुनरारंभ हो जाता है क्योंकि इसकी प्रक्रिया मारे जाती है, तो स्टार्टकॉमैंड() को शून्य के इरादे के साथ सेवा के अगले उदाहरण पर कॉल किया जाएगा । इस मोड का उपयोग करने वाली सेवाएं हमेशा इस मामले की जांच करें और उचित तरीके से इसका निपटारा करें।

START_NOT_STICKY का कहना है कि, onStartCreated() से लौटने के बाद, अगर प्रक्रिया कोई शेष शुरुआत देने के लिए आदेश के साथ मार डाला, तो सेवा के बजाय रोक दिया जाएगा पुनरारंभ। यह सेवाओं के लिए बहुत अधिक समझ में आता है जो केवल उन्हें भेजे गए आदेश निष्पादित करते समय चलाने के लिए लक्षित हैं। उदाहरण के लिए, कुछ नेटवर्क राज्य को मतदान करने के लिए अलार्म से हर 15 मिनट में सेवा शुरू की जा सकती है। अगर यह काम करने के दौरान मारे गए, तो यह को रोकने के लिए सबसे अच्छा होगा और अगली बार अलार्म आग लगने लगेगा।

START_REDELIVER_INTENT इससे पहले कि यह एक दिया इरादे, कि आशय यह करने के लिए फिर से वितरित किया जाएगा के लिए stopSelf() कहता है, जब तक यह पूरा करता है को छोड़कर अगर सेवा की प्रक्रिया मार दिया जाता है, START_NOT_STICKY की तरह है (जब तक और अवसर की कुछ संख्या के बाद यह अभी भी पूरा नहीं हो सकता है, पर जो सिस्टम को छोड़ देता है)। यह उन सेवाओं के लिए उपयोगी है जो काम करने के आदेश प्राप्त कर रहे हैं, और यह सुनिश्चित करना चाहते हैं कि वे अंततः भेजे गए प्रत्येक आदेश के लिए कार्य को पूरा करें।

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