Highway62 February 2016

Is there a way to have getSystemService() return a completely new instance every time in Android?

In Android Wear, registering and unregistering SensorEventListeners repeatedly with a SensorManager causes the SensorManager to fail. I'm wondering if there is a way that I can get a new instance of SensorManager every time I load my fragment. So that I can get a new SensorManager, register my listeners, and unregister them when the fragment is destroyed, and then de-reference that SensorManager and get a new one the next time the fragment is loaded.

In my fragment I am currently doing this:

@Override
public View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
    // ... 
    mSensorMgr = (SensorManager) mMainWearActivity.getSystemService(Activity.SENSOR_SERVICE);
    // ...
}

private void startListening(){

    yGesture.setOnShakeListener(yListener);
    xGesture.setOnShakeListener(xListener);
    mSensorMgr.registerListener(yGesture, mSensorMgr.getDefaultSensor(Sensor.TYPE_GYROSCOPE), SensorManager.SENSOR_DELAY_NORMAL);
    mSensorMgr.registerListener(xGesture, mSensorMgr.getDefaultSensor(Sensor.TYPE_GYROSCOPE), SensorManager.SENSOR_DELAY_NORMAL);
}

@Override
public void onResume(){
    super.onResume();
    startListening();
}

@Override
public void onPause(){
    stopListening();
    super.onPause();
}

private void stopListening(){

    mSensorMgr.unregisterListener(yGesture);
    mSensorMgr.unregisterListener(xGesture);
    mSensorMgr = null;
}

I need mSensorMgr = (SensorManager) mMainWearActivity.getSystemService(Activity.SENSOR_SERVICE); to return a new instance, otherwise registering and unregistering listeners multiple times makes the SensorManager fail. Is this possible? Preferably without having to make a new Activity and just stick to using fragments. Thanks

EDIT:

I've moved registering the listeners with the sensorManager to onResume(), and yet the same problem still persists. Is this a bug in the Android Wear framework?

Answers


Doug Stevenson February 2016

Generally speaking, you always want to use correctly paired Activity or Fragment lifecycle methods to register and unregister listeners of any kind. So you would use create/destroy, or start/stop, or resume/pause.

In your particular case, you are registering in onCreateView, which is called only once for a fragment instance, however, your unregister is happening during onPause, which could be called multiple times. As soon as this fragment is paused for any reason (and there are a lot of reasons this could happen), your listeners are forever gone until a new instance of the fragment is created.

So you might want to consider using create/destroy or start/stop depending on what exactly you're trying to do with the listener in your fragment. If you don't understand these lifecycle methods, please study it here.


qbix February 2016

Is there is a way that I can get a new instance of SensorManager...?

No. The object returned by getSystemService(Context.SENSOR_SERVICE) is basically an interface object to a system-level service. There is only one instance of that service on the device.

You can get some insights into what the SensorManager service is doing by creating an Android Studio logcat filter with selected tag "SensorManager" and Debug level. The filter will enable output such as this:

D/SensorManager: registerListener :: 6, CM3323 RGB Sensor, 200000, 0,
D/SensorManager: unregisterListener ::

Looking at this output might help you see something unexpected in the way you are registering and unregistering your listeners.

It is not good practice to register your listeners in onCreateView() and unregister in onPause(). When the fragment's activity gets paused and resumed, the fragment is also paused and resumed with no call onCreateView(). This is explained in the documentation.

You might also try experimenting with slower sensor update rates. SENSOR_DELAY_GAME is 20 milliseconds, maybe faster than you need for your application. SENSOR_DELAY_UI is 67 milliseconds, SENSOR_DELAY_NORMAL is 200 milliseconds.

Post Status

Asked in February 2016
Viewed 1,542 times
Voted 12
Answered 2 times

Search




Leave an answer