44

मुझे Google Play पर अपने आवेदन अपलोड कर दिया है, लेकिन उपयोगकर्ताओं को निम्नलिखित अपवादjava.lang.RuntimeException: Wakelock तहत बंद कर दिया C2DM_LIB

java.lang.RuntimeException सूचना दी है: C2DM_LIB तहत बंद कर दिया Wakelock। यह अपवाद तब होता है जब मैं WakeLock जारी करने का प्रयास करता हूं। क्या कोई बता सकता है कि समस्या क्या हो सकती है।

उत्तर

51

मैंने नई जीसीएम लाइब्रेरी में भी एक ही अपवाद का पता लगाया है। दरअसल पुरानी सी 2 डीएम एंड्रॉइड लाइब्रेरी में एक ही त्रुटि है, एक ही क्रैश है, और Google ने अभी तक इसे ठीक नहीं किया है। जैसा कि हम अपने आंकड़ों से देख सकते हैं, इस क्रैश का सामना करने वाले उपयोगकर्ताओं का लगभग 0.1%।

मेरी जांच से पता चलता है कि समस्या जीसीएम लाइब्रेरी में नेटवर्क WakeLock के गलत रिलीज में है, जब लाइब्रेरी WakeLock जारी करने का प्रयास करती है जिसमें कुछ भी नहीं है (आंतरिक लॉक काउंटर नकारात्मक हो जाता है)।

मैं सरल समाधान से संतुष्ट था - बस इस अपवाद को पकड़ें और कुछ भी नहीं करें, क्योंकि हमें कोई अतिरिक्त नौकरी करने की आवश्यकता नहीं है तो हमारे वाकेलॉक में कुछ भी नहीं है।

ऐसा करने के लिए आपको पहले से संकलित .jar फ़ाइल की बजाय, अपने प्रोजेक्ट में जीसीएम लाइब्रेरी स्रोत आयात करने की आवश्यकता है। आप जीसीएम लाइब्रेरी स्रोतों को "$ एंड्रॉइड_SDK_Home $/extras/google/gcm/gcm-client/src" फ़ोल्डर के अंतर्गत पा सकते हैं (आपको एंड्रॉइड एसडीके प्रबंधक का उपयोग करके इसे पहले डाउनलोड करना होगा)।

अगला ओपन GCMBaseIntentService वर्ग, लाइन

sWakeLock.release(); 

खोजने के लिए और कोशिश पकड़ साथ उस पर घेरा। his answer में सुझाव दिया @fasti रूप Alternativally,, आप अगर wakelock वास्तव में इस ताला पकड़े जाँच करने के लिए mWakeLock.isHeld() विधि का उपयोग कर सकते हैं:

यह इस तरह दिखना चाहिए:

synchronized (LOCK) { 
     // sanity check for null as this is a public method 
     if (sWakeLock != null) { 
      Log.v(TAG, "Releasing wakelock"); 
      try { 
       sWakeLock.release(); 
      } catch (Throwable th) { 
       // ignoring this exception, probably wakeLock was already released 
      } 
     } else { 
      // should never happen during normal workflow 
      Log.e(TAG, "Wakelock reference is null"); 
     } 
    } 

अद्यतन।

+0

आप इसे करने की कोशिश की ..? क्या यह कोशिश करने के साथ इसे आसपास के बाद ठीक चलाता है .. – Rookie

+1

हां, मैंने इस समाधान को हमारी सभी परियोजनाओं में कार्यान्वित किया है, यह पूरी तरह से काम करता है (2 एम उपयोगकर्ताओं से अधिक उपयोगकर्ताबेस) – HitOdessit

+0

ठीक है, धन्यवाद ..... – Rookie

135

आपने अपना कोड पोस्ट नहीं किया है, इसलिए मुझे नहीं पता कि आप पहले से ही क्या कर चुके हैं, मैं यहां सुझाव दूंगा, लेकिन मेरे पास यह अपवाद भी था और मैंने इसे ठीक करने के लिए जोड़ा, यह एक सरल "अगर" पर यह सुनिश्चित करें कि इसे जारी करने की कोशिश करने से पहले, वेक लॉक वास्तव में आयोजित किया जा रहा है।

सभी मैं अपने onPause में जोड़ा ("रिलीज()" से पहले) इस "अगर" बयान था:

if (mWakeLock.isHeld()) 
    mWakeLock.release(); 

और अपवाद चला गया था।

+6

यह समाधान स्वीकार किए गए एक से मेरे लिए बहुत साफ दिखता है। – ottel142

+1

ऐसा इसलिए है क्योंकि यह करने के लिए सही तरीका है। यह स्वीकार्य उत्तर होना चाहिए था। – ComputerEngineer88

+0

मेरे पास मेरे कोड में कोई नहीं है। (कोई mWakeLock कभी भी नहीं) लेकिन मुझे अभी भी यह त्रुटि मिल रही है। एकमात्र स्टैकट्रैक मैं देखता हूं: java.lang.RuntimeException: WakeLock GCM_LIB पर लॉक किया गया [...] com.google.android.gcm.GCMBaseIntentService.onHandleIntent (GCMBaseIntentService.java:252) android.app पर। IntentService $ ServiceHandler.handleMessage (IntentService.java:65) – Ted

3

हालांकि हैहेल्ड() समाधान अच्छा लगता है, यह वास्तव में असफल हो सकता है - क्योंकि यह परमाणु नहीं है (यानी थ्रेड सुरक्षित नहीं है)। यदि आपके पास एक से अधिक धागे हैं जो लॉक को छोड़ सकते हैं तो चेक (isHeld) के बीच और किसी अन्य थ्रेड को रिले करने के लिए कॉल लॉक जारी कर सकता है ... और फिर आप असफल हो जाते हैं।

कोशिश/पकड़ का उपयोग करके आप बग को छिपाते हैं, लेकिन थ्रेड-सुरक्षित तरीके से।

+0

क्या पुन: प्रयोज्य तरीके से वेक लॉक रिलीज परमाणु बनाने का कोई अच्छा विकल्प है? यह एक परमाणु ऑपरेशन होना चाहिए। यह सचमुच नाम में "लॉक" है। – colintheshots

1

मुझे तब तक यह समस्या नहीं है जब तक कि मैं जागृत लॉक को पुन: प्रारंभ नहीं करता और नए ऑब्जेक्ट पर कॉल प्राप्त नहीं करता। आपको केवल जागने का एक उदाहरण रखना चाहिए (इसलिए इसे एक फील्ड वैरिएबल बनाएं)। तब आप जानते हैं कि आप हमेशा उस जागने को जारी कर रहे हैं।

तो ....

if (mWakeLock == null) { 
     PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); 
     mWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP 
       | PowerManager.ON_AFTER_RELEASE, "MyWakeLock"); 
    } 

try{ 
     mWakeLock.release();//always release before acquiring for safety just in case 
    } 
    catch(Exception e){ 
     //probably already released 
     Log.e(TAG, e.getMessage()); 
    } 
    mWakeLock.acquire(); 
संबंधित मुद्दे