Tencent/matrix · error · RuntimeException
Use #onStateChanged(BatteryState, String) instead
Error message
Use #onStateChanged(BatteryState, String) instead
What it means
DefaultListenerImpl deliberately overrides onStateChanged(String) to throw RuntimeException unconditionally, steering callers to the newer onStateChanged(BatteryState, String) callback. The raw-string variant is deprecated because it loses typed battery-state information.
Solutions
- Override onStateChanged(BatteryState batteryState, String event) in your listener subclass and put handling logic there.
- Remove any explicit calls to onStateChanged(String) in listener code.
- Migrate custom listeners to implement the current BatteryEventDelegate listener interface directly instead of extending DefaultListenerImpl.
Example fix
// before
new BatteryEventDelegate.DefaultListenerImpl(true) {
// no override: base throws on callback
}
// after
new BatteryEventDelegate.DefaultListenerImpl(true) {
@Override
public boolean onStateChanged(BatteryState state, String event) {
return handle(state, event);
}
} Defensive patterns
Strategy: try-catch
Prevention
- Always override onStateChanged(BatteryState, String) in DefaultListenerImpl subclasses.
- When upgrading the library, re-check listener method signatures for breaking changes.
- Favor implementing the listener interface directly over extending the default base class.
When it happens
Trigger: Registering a listener object whose class extends DefaultListenerImpl (or uses it as a base) and relies on the inherited string-based onStateChanged(String) without overriding it — the delegate will call the base implementation and throw.
Common situations: Upgrading the battery-canary library where the callback signature changed from String to (BatteryState, String); copying an old listener implementation that fails to override the new method.
Understand the failure class
Background: "is deprecated and will be removed" — deprecation warnings for old API names, keywords, and options, and how to migrate before the removal release — this error's family across 29 libraries.
Related errors
- Call #init() first!
- Context should not be null
- Illegal battery state
- <getTag()> is not yet init!
- No start tag found
AI-assisted analysis of Tencent/matrix@3b8293bd65 (2026-09-08).
Data as JSON: /api/errors/f11b100ec35895d9.
Report an issue: GitHub.
Appendix: source
Thrown at matrix/matrix-android/matrix-battery-canary/src/main/java/com/tencent/matrix/batterycanary/BatteryEventDelegate.java:669
* @param isLowBattery {@link Intent#ACTION_BATTERY_LOW}, {@link Intent#ACTION_BATTERY_OKAY}
* @return return true if your listening is done, thus we remove your listener
*/
@UiThread
boolean onBatteryStateChanged(BatteryState batteryState, boolean isLowBattery);
}
@SuppressWarnings("unused")
class DefaultListenerImpl implements ExListener {
final boolean mKeepAlive;
public DefaultListenerImpl(boolean keepAlive) {
mKeepAlive = keepAlive;
}
@Override
public boolean onStateChanged(String event) {
throw new RuntimeException("Use #onStateChanged(BatteryState, String) instead");
}
@Override
public boolean onAppLowEnergy(BatteryState batteryState, long backgroundMillis) {
return !mKeepAlive;
}
@Override
public boolean onStateChanged(BatteryState batteryState, String event) {
return !mKeepAlive;
}
@Override
public boolean onBatteryTemperatureChanged(BatteryState batteryState, int temperature) {
return !mKeepAlive;
}
@OverrideView on GitHub (pinned to 3b8293bd65)