// Clears static properties on OneSignal to simulate an app cold start. package com.onesignal; import org.json.JSONArray; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Map; public class StaticResetHelper { private static Collection<ClassState> classes = new ArrayList<>(); static { classes.add(new StaticResetHelper().new ClassState(OneSignal.class, new OtherFieldHandler() { @Override public boolean onOtherField(Field field) throws Exception { if (field.getName().equals("unprocessedOpenedNotifis")) { field.set(null, new ArrayList<JSONArray>()); return true; } return false; } })); classes.add(new StaticResetHelper().new ClassState(OneSignalStateSynchronizer.class, new OtherFieldHandler() { @Override public boolean onOtherField(Field field) throws Exception { if (field.getName().equals("currentUserState") || field.getName().equals("toSyncUserState")) { field.set(null, null); return true; } return false; } })); classes.add(new StaticResetHelper().new ClassState(OneSignalChromeTab.class, null)); classes.add(new StaticResetHelper().new ClassState(OneSignalDbHelper.class, null)); } private interface OtherFieldHandler { boolean onOtherField(Field field) throws Exception; } private class ClassState { private OtherFieldHandler otherFieldHandler; private Class stateClass; private Map<Field, Object> orginalVals = new HashMap<Field, Object>(); ClassState(Class inClass, OtherFieldHandler inOtherFieldHandler) { stateClass = inClass; otherFieldHandler = inOtherFieldHandler; } private Object tryClone(Object v) throws Exception { if (v instanceof Cloneable) return v.getClass().getMethod("clone").invoke(v); return v; } private void saveStaticValues() throws Exception { Field[] allFields = stateClass.getDeclaredFields(); try { for (Field field : allFields) { int fieldModifiers = field.getModifiers(); if (Modifier.isStatic(fieldModifiers) && !Modifier.isFinal(fieldModifiers)) { field.setAccessible(true); Object value = tryClone(field.get(null)); orginalVals.put(field, value); } } } catch (IllegalAccessException e) { System.err.println(e); } } private void restSetStaticFields() throws Exception { for (Map.Entry<Field, Object> entry : orginalVals.entrySet()) { Field field = entry.getKey(); Object value = entry.getValue(); Class<?> type = field.getType(); field.getName(); field.setAccessible(true); if (otherFieldHandler == null || !otherFieldHandler.onOtherField(field)) field.set(null, tryClone(value)); } } } public static void saveStaticValues() { for(ClassState aClass : classes) { try { aClass.saveStaticValues(); } catch (Exception e) { e.printStackTrace(); } } } public static void restSetStaticFields() { for(ClassState aClass : classes) { try { aClass.restSetStaticFields(); } catch (Exception e) { e.printStackTrace(); } } } }