2014-11-15 3 views
5

मेरा ऐप एक Service onStartCommand एक SensorManager बना सकते हैं और सेंसर से एक के लिए एक SensorEventListener संलग्न करने के लिए ओवरराइड करता है कि बनाता है विफल रहता है।Android के SensorManager प्रभावी रूप से श्रोताओं का पंजीकरण रद्द करना

मैं ओवरराइड करने के लिए Service के onDestroy() विधि चाहते हैं और, उस में, सेंसर को मारने:

sensorManager.unregisterListener(activeListener); 

लेकिन जब मैं यह करते हैं, कुछ भी नहीं है वास्तव में होता है! मेरा onSensorChanged() श्रोता एक्सेलेरोमीटर (या मेरे मामले में सॉफ़्टवेयर LINEAR_ACCELERATION सेंसर) से सही मान प्राप्त करना जारी रखता है। समस्या, बेशक, docs में यहाँ उद्धृत किया गया है:

हमेशा सेंसर आप की जरूरत नहीं है निष्क्रिय करने के लिए, खासकर जब अपनी गतिविधि रोक दिया गया है सुनिश्चित करें। ऐसा करने में विफल होने से बैटरी कुछ ही घंटों में निकल सकती है।

मेरा ऐप केवल जब तक स्क्रीन वास्तव में अनलॉक हो गया है के लिए accelerometer पिंग करने की जरूरत है। मैंने BroadcastReceiver एस के सही कार्य को कार्यान्वित किया है (और सही कार्य सत्यापित किया है जो Service को फोन लॉक करते समय नष्ट कर देता है, सफलतापूर्वक onDestroy() विधि को कॉल कर रहा है। लेकिन श्रोताओं को अपंजीकृत करने का प्रयास करने के बाद वास्तव में कुछ भी नहीं होता है।

मुझे कुछ अन्य लोगों को इस सवाल से कोई समाधान नहीं मिला है।

मैं केवल यह एक एपीआई बग है, और वहाँ वास्तव में इन को मारने के लिए कोई अच्छा तरीका है कि यह मान सकते हैं सेंसर एक बार मैंने उनसे डेटा हथियाने शुरू कर दिया है। मैंने SensorManager, Sensor, और SensorEventListener को शून्य करने के साथ-साथ प्रबंधक के साथ एक नल सेंसर श्रोता को पंजीकृत करने का प्रयास करने का प्रयास किया है। इनमें से कोई भी मतदान पर कोई प्रभाव नहीं पड़ता है।

मेरा वर्तमान "वर्कअराउंड" बैटरी जीवन पर लगभग कोई प्रभाव नहीं पड़ता है। मेरे वर्ग की परिभाषा में मेरे पास निजी बूलियन है कि मैं true या false पर सेट करता हूं कि मैं सेंसर मान चाहता हूं या नहीं। सेंसर श्रोता को निष्क्रिय होने पर, onSensorChanged() विधि में, मैं तुरंत return में हूं। लेकिन तब तक, यह बहुत देर हो चुकी है: ओएस (सेंसर मूल्य प्राप्त करने) द्वारा किए जा रहे काम की झटके से पहले मैं onSensorChanged() विधि छोड़ने का प्रबंधन कर सकता हूं, इसलिए जब तक मेरी सेवा चल रही है तब तक बैटरी जीवन अभी भी भयानक है।

मेरा असली प्रश्न यहां कुछ चमत्कार वास्तविक समाधान को छोड़कर, है सेंसर मूल्य प्राप्त करने के लिए मैं क्या कर सकता हूं? जाहिर है, सेंसर श्रोता को अनधिकृत करने से इस बिंदु पर काम नहीं होता है; यहां तक ​​कि सबकुछ को शून्य करने और सेवा को नष्ट करने के लिए भी कोई प्रभाव नहीं पड़ता है।लेकिन ऑपरेटिंग सिस्टम को इंगित करने के लिए कुछ तरीका होना चाहिए कि मेरे ऐप को अब सेंसर मूल्यों के उपयोग की आवश्यकता नहीं है। क्या मेरा पूरा ऐप मारने का कोई तरीका है, फोन अनलॉक होने पर ही इसे पुनरारंभ करना? हो सकता है कि ऑपरेटिंग सिस्टम को यह पता चले कि मेरे ऐप को अब मूल्यों की आवश्यकता नहीं है। असल में, कोई भी समाधान जो वैध रूप से सेंसर को मतदान करना बंद कर देता है लेकिन मुझे इसे पुनरारंभ करने का कोई तरीका देता है, भले ही कोड बदसूरत हो, मुझे खुश कर देगा।

अपने प्रोजेक्ट के लिए न्यूनतम API स्तर 9.

उत्तर

2

मैं वही समस्या का सामना करना पड़ा है।

बैटरी निकालने से सेंसर को रोकने के लिए वर्कअराउंड।

मैंने एक स्थिर बूलियन mIsSensorUpdateEnabled का उपयोग किया। जब आप सेंसर से मूल्य प्राप्त करना बंद करना चाहते हैं तो इसे 'झूठी' पर सेट करें। और सेंसर चेंज() विधि में, बूलियन वैरिएबल के मान की जांच करें और फिर सेंसर को अनधिकृत करने के लिए कॉल करें। और इस बार, यह काम करता है। सेंसर को अनियंत्रित किया जाएगा और अब आप सेंसर चेंज कॉलबैक पर नहीं पहुंच पाएंगे।

public class MainActivity extends Activity implements SensorEventListener{ 
     private static boolean mIsSensorUpdateEnabled = false; 
     private SensorManager mSensorManager; 
     private Sensor mAccelerometer; 

     @override 
     protected void onCreate(){ 
      mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); 
     } 

     private startSensors(){ 
      mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); 
      int delay = 100000; //in microseconds equivalent to 0.1 sec 
      mSensorManager.registerListener(this, 
         mAccelerometer, 
         delay 
       ); 
      mIsSensorUpdateEnabled =true; 
     } 

     private stopSensors(){ 
      mSensorManager.unregisterListener(this, mAccelerometer); 
      mIsSensorUpdateEnabled =false; 
     } 


     @Override 
     public void onSensorChanged(SensorEvent event) { 
      if (!mIsSensorUpdateEnabled) { 
       stopSensors(); 
       Log.e("SensorMM", "SensorUpdate disabled. returning"); 
       return; 
      } 
      //Do other work with sensor data 
     } 
    }` 
+0

इस उत्तर के लिए धन्यवाद; मुझे अभी तक इसे आजमाने का मौका नहीं मिला है, लेकिन जब मैं करता हूं तो मैं आपके उत्तर को स्वीकार किए जाने पर स्वीकार कर लेता हूं। –

1

मुझे एक ही समस्या थी। और अंततः मैं सेंसर मैनेजर ऑब्जेक्ट को शून्य के रूप में सेट करके सेंसर पढ़ने में सक्षम था। तो सेंसर प्रबंधक किसी श्रोता को पंजीकृत नहीं कर सकता है। और जब आप सेंसर डेटा को पढ़ना चाहते हैं, तो सेंसर प्रबंधक ऑब्जेक्ट और श्रोताओं को परिभाषित करने के लिए स्टार्ट रजिस्टर्ड विधि को कॉल करें। यहां मेरा कोड है:

public class SensorReadingClass implements SensorEventListener { 

    public SensorReadingClass(Service c){ 
     this.mContext=c; 
     mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE); 
     if (mSensorManager != null) { 
      // list available sensors and power consumption 
      List<Sensor> sensors = mSensorManager.getSensorList(Sensor.TYPE_ALL); 
     } else { 
      if(DBG) Log.e(TAG, "Could not get SensorManager instance"); 
     } 
    } 

    public float getHeartRate(){ 
     Log.d(TAG,"Heart Rate return value: " + heartRate); 
     return heartRate; 
    } 

    public void startSensorListeners() { 
     Log.d(TAG, "startSensorListeners"); 

     if(mSensorManager==null){ 
      mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE); 
     } 

     readSensors=true; 

     mSensorManager.registerListener(this, mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL); 
     mSensorManager.registerListener(this, mSensorManager.getDefaultSensor(Sensor.TYPE_HEART_RATE), SensorManager.SENSOR_DELAY_NORMAL); 
     mSensorManager.registerListener(this, mSensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER), SensorManager.SENSOR_DELAY_NORMAL); 
     mSensorManager.registerListener(this, mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE), SensorManager.SENSOR_DELAY_NORMAL); 

     Log.d(TAG, "Sensor started: " + mSensorManager.registerListener(this, mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL)); 

    } 

    public void stopSensorListeners() { 
     Log.d(TAG, "stopSensorListeners"); 

     if(mSensorManager!=null) { 
      mSensorManager.unregisterListener(this); 
      mSensorManager=null; 
     } 

     Log.d(TAG, "Sensor stoppped: " + mSensorManager); 
     readSensors=false; 

    } 

    @Override 
    public void onSensorChanged(SensorEvent event) { 

      String key = event.sensor.getName(); 
      float values = event.values[0]; 
      Sensor sensor = event.sensor; 

      if (sensor.getType() == Sensor.TYPE_ACCELEROMETER) { 
       accellerometerEvent++;     // this is event counts when sensor changes, this counts all the events changings. It shouldnt be necessary though 
       accellerometerSensor = values + " " + event.values[1] + " " + event.values[2] + " " + accellerometerEvent; // This is the string for value and seen event count. 

      } 

      if (sensor.getType() == Sensor.TYPE_HEART_RATE) { 
       heartRateEvent++; 
       heartRateSensor = values + " " + heartRateEvent; 
       heartRate = values; 

      } 

      if (sensor.getType() == Sensor.TYPE_STEP_COUNTER) { 
       stepCounterEvent++; 
       stepCounterSensor = values + " " + stepCounterEvent; 

      } 

      if (sensor.getType() == Sensor.TYPE_GYROSCOPE) { 
       gyroscopeEvent++; 
       try { 
        gyroscopeSensor = values + " " + event.values[1] + " " + event.values[2] + " " + gyroscopeEvent; 
       } catch (Exception e) { 
       } 

      } 

      lastTime = System.currentTimeMillis(); 
     } 

    @Override 
    // since we will always capture the data whether it changes or not, we don't need this method 
    public void onAccuracyChanged(Sensor sensor, int accuracy) { 
     return; 
    } 

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