Werid ClassCastException en TreeMap.containsKey ()

Esta es la línea donde se produce el bloqueo

offsetDuration = duration - (offsets.containsKey(freq) ? offsets.get(freq) : 0l); 

Los valores que conseguí al capturar la Exception y descartar las variables,

 long offsetDuration = 0; long duration = 391144; TreeMap<Long, Long> offsets = {0=4024974.0, 1036800=8588.0, 1190400=88216.0, 1267200=49763.0, 1497600=87476.0, 1574400=7469.0, 1728000=54553.0, 1958400=60512.0, 2265600=246942.0, 300000=390779.0, 422400=39945.0, 652800=55204.0, 729600=46829.0, 883200=19191.0, 960000=23888.0} long freq = 300000; 

La variable TreeMap<Long, Long> offsets se analiza desde un archivo json mediante el código siguiente.

 @NonNull public static TreeMap<Long, Long> getOffsets(Context context) throws CpuStateException { File file = getOffsetsFile(context); TreeMap<Long, Long> map; try { String s = Files.toString(file, Charsets.UTF_8).trim(); Gson gson = new GsonBuilder().create(); Type type = new TypeToken<TreeMap<Long, Long>>(){}.getType(); map = gson.fromJson(s, type); } catch (IOException e) { throw new CpuStateException("Failed to read offsets!"); } if (map == null) throw new CpuStateException("Failed to read offsets!"); return map; } 

Después de examinar el código muchas veces, no puedo identificar una situación donde este código puede lanzar una

 java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Long at java.lang.Long.compareTo(Long.java:32) at java.util.TreeMap.find(TreeMap.java:277) at java.util.TreeMap.findByObject(TreeMap.java:351) at java.util.TreeMap.containsKey(TreeMap.java:182) at com.vibhinna.library.engine.CpuStates.getCpuData(CpuStates.java:96) at com.vibhinna.library.engine.CpuStates.getBarData(CpuStates.java:162) 

¿Algunas ideas?

Actualizaciones 1: esto es cómo se genera el json:

 public static void offsetTimers(TreeMap<Long, Long> offsets, Context context) throws CpuStateException { Gson gson = new GsonBuilder().create(); String json = gson.toJson(offsets); File file = getOffsetsFile(context); try { OutputStreamWriter outputStream = new OutputStreamWriter(new FileOutputStream(file), "UTF-8"); outputStream.write(json); outputStream.flush(); outputStream.close(); } catch (IOException e) { throw new CpuStateException("Failed to save offsets!"); } } 

Actualización 2 : Ni siquiera soy capaz de reproducir esto incluso en la aplicación original, el accidente es raro y reportado por aproximadamente sólo en menos del 1% de los clientes.

Actualización 3

 offset class: class java.lang.String value: 1036800 offset class: class java.lang.String value: 1190400 offset class: class java.lang.String value: 1267200 offset class: class java.lang.String value: 1497600 offset class: class java.lang.String value: 1574400 offset class: class java.lang.String value: 1728000 offset class: class java.lang.String value: 1958400 offset class: class java.lang.String value: 2265600 offset class: class java.lang.String value: 300000 offset class: class java.lang.String value: 422400 offset class: class java.lang.String value: 652800 offset class: class java.lang.String value: 729600 offset class: class java.lang.String value: 883200 offset class: class java.lang.String value: 960000 

Json

 { "0":256093, "300000":105045, "422400":9677, "652800":10443, "729600":8868, "883200":3951, "960000":7323, "1036800":18668, "1190400":34938, "1267200":17151, "1497600":11018, "1574400":1173, "1728000":22881, "1958400":21076, "2265600":66501 } 

Aquí está la horrible solución que parece estar funcionando.

 @NonNull public static TreeMap<Long, Long> getOffsets(Context context) throws CpuStateException { File file = getOffsetsFile(context); TreeMap map; try { String s = Files.toString(file, Charsets.UTF_8).trim(); Gson gson = new GsonBuilder().create(); Type type = new TypeToken<TreeMap<Long, Long>>(){}.getType(); map = gson.fromJson(s, type); } catch (IOException e) { throw new CpuStateException("Failed to read offsets!"); } if (map == null) throw new CpuStateException("Failed to read offsets!"); // So, I don't trust Gson. On some devices the above code seems to be producing a // TreeMap<String, Double/Float>. So let's assume it's either a String or a boxed primitive. // Even if the assumption is wrong we're no worse off than we were before. // The String we'll parse, the primitive we'll cast. Brace yourselves for a horrible hack! // TODO find a proper fix. Iterator it = map.keySet().iterator(); TreeMap<Long, Long> treeMap = new TreeMap<>(); while (it.hasNext()) { Object key = it.next(); Object value = map.get(key); Long lKey, lValue; if ((key instanceof Long)) { lKey = (Long) key; } else { Log.e(TAG, "Invalid key type in TreeMap: " + key.getClass()); if (key instanceof Number) { lKey = ((Number) key).longValue(); } else if (key instanceof String) { lKey = Double.valueOf((String) key).longValue(); } else { throw new IllegalArgumentException("Invalid key in TreeMap: " + key); } } if ((value instanceof Long)) { lValue = (Long) value; } else { Log.e(TAG, "Invalid value type in TreeMap: " + value.getClass()); if (value instanceof Number) { lValue = ((Number) value).longValue(); } else if (value instanceof String) { lValue = Double.valueOf((String) value).longValue(); } else { throw new IllegalArgumentException("Invalid value in TreeMap: " + value); } } treeMap.put(lKey, lValue); } return treeMap; } 
  • ¿Cómo medir el tiempo de solicitud y respuesta del servidor?
  • Android Volley varias solicitudes
  • Android no procesar objeto JSON
  • Dibujo de rutas de conducción con waypoints en android (Google Maps, api dirección de Google, json parsing, decodificar google polyline)
  • ¿Cómo puede Retrofit 2.0 analizar objeto JSON anidado?
  • ¿Cómo comprobar si existe una llave json?
  • Vaciar RecyclerView utilizando datos obtenidos de parse.com
  • Escribir datos en el archivo JSON local
  • Aplicación Web de Android RESTful con Zend Framework
  • JSONObject no funciona para Android 2.3, pero funciona bien con Android 4.2, ¿por qué?
  • Cree un archivo JSON analizable para la aplicación android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.