0

Ich habe eine Anwendung mit Sensoren Listener. Grundsätzlich habe ich eine Haupttätigkeit mit etwas wie folgt aus:Android/Java-Sensor hashCode() geben verschiedene Werte in verschiedenen Aktivitäten/Service

MainActivity.java

public class MainActivity extends AppCompatActivity 
{ 
    (...) 
    @Override 
    protected void onCreate(Bundle savedInstanceState) 
    { 
     SensorManager mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); 

     Log.d(LOG_TAG, "Accelerometer hashCode MA: " + mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER).hashCode()); 
     Log.d(LOG_TAG, "Accelerometer reference MA: " + Integer.toHexString(System.identityHashCode(mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)))); 
    } 
} 

Und ich habe ein Dienst gestartet vom MainActivity wie folgt aus:

startService(new Intent(MainActivity.this, SensorService.class)); 

Meine Service-Klasse ist:

SensorService.java

Wenn mein Smartphone Lollipop hatte, war die Ausgabe der hashCodes in der Aktivität und im Service identisch. Allerdings habe ich mein Smartphone auf Marshmallow aktualisiert und nun ist der HashCode anders. Die oben genannten Ausgänge sind jetzt immer wie folgt aus:

Accelerometer hashCode MA: 262356196

Accelerometer Referenz MA: fa33ce4

Accelerometer hashCode SS: 26510821

Accelerometer Referenz SS : 19485e5

Ich kann nicht herausfinden, warum ein einfaches Software-Update die HashCodes mit einem anderen Verhalten behaftet, und ich brauche sie das gleiche Verhalten zu haben. Kannst du mir helfen?

- UPDATE -

Warum ich das wollen?

In meiner MainActivity "drucke" ich in der Ansicht alle Sensoren, die das Smartphone hat. Dies wird dynamisch wie dies geschehen:

TextView sensorLayout = new TextView(this); 
sensorLayout.setText(sensor.getStringType()); 
sensorLayout.setId(sensor.hashCode()); 
sensorLayout.setLayoutParams(new ViewGroup.LayoutParams(
    ViewGroup.LayoutParams.WRAP_CONTENT, 
    ViewGroup.LayoutParams.WRAP_CONTENT)); 

mainLayout.addView(sensorLayout); 

Dann wird der SensorService ein Zuhörer ist. Jedes Mal, wenn die onSensorChanged() aufgerufen wird, möchte ich die Hauptaktivität dieser Änderung informieren, damit ich die neuen Werte sehen kann.
Ich mache das, indem ich eine Absicht mit zwei Extras (eine Zeichenfolge mit den neuen Werten und eine ganze Zahl mit dem HashCode des Sensors) ausstrahlt. Die MainActivity muss wissen, welche es ändern sehen sollte, und es ist so wie dies geschehen:

int hashCode = intent.getIntExtra(SensorService.EXTRA_SENSOR_HASHCODE, 0); 
TextView sensorLayout = (TextView) mainLayout.findViewById(hashCode); 
sensorLayout.setText(intent.getStringExtra(SensorService.EXTRA_SENSOR_INFO)); 
+0

"Ich brauche sie, um das gleiche Verhalten zu haben" - warum? Ich würde niemals davon ausgehen, dass 2+ 'Sensor'-Objekte den gleichen 'hashCode()' Wert haben, sogar für den gleichen Sensortyp. – CommonsWare

+0

In meinem Kopf denke ich, dass es vernünftig ist zu denken, dass * getDefaultSensor() * sollte einen Verweis auf den gleichen Sensor (in meinem Code der Beschleunigungsmesser), wo auch immer es heißt. Tatsächlich scheint es das Verhalten im Lollipop gewesen zu sein. – tjiagoM

+0

"In meinem Kopf denke ich, dass es vernünftig ist zu denken, dass getDefaultSensor() einen Verweis auf den gleichen Sensor geben sollte" - ich bin mir keiner Dokumentation bewusst, die dieses Verhalten implizieren würde. AFAIK, Sie haben sich auf Nebenwirkungen einer Implementierung verlassen, was ein riskantes Unterfangen war, und Sie zahlen jetzt den Preis. Also, ich werde wieder fragen: ** Warum ** brauchst du sie, um das gleiche Verhalten zu haben? Wenn Sie erklären, warum Sie sich auf diesen Nebeneffekt verlassen haben, können wir Ihnen vielleicht eine Lösung vorschlagen. – CommonsWare

Antwort

0

Danke für Ihre Hilfe.

In meinem speziellen Fall, entschied ich mich, eine einfache Lösung zu tun:
Als ich den Hash in Form einer ganzen Zahl benötigt, ich habe die sensor.getType() Funktion anstelle des sensor.hashCode() und mein Problem gelöst wird nun verwendet! Soweit ich in der Dokumentation gesehen habe, gibt diese Methode eine eindeutige Ganzzahl für jeden Sensor in einem Smartphone zurück.

1

Die Identität hashcode ist immer die Standard java.lang.Object Implementierung, auch wenn die Klasse für ein bestimmtes Objekt überschreibt diese und berechnet einen anderen Hash-Code.

Der Identitäts-Hashcode berücksichtigt nicht den Inhalt des Objekts, nur dort, wo es sich befindet. Der gewöhnliche Hashcode kann (sollte) den Inhalt berücksichtigen. Somit wären die Identitäts-Hashcodes für zwei Strings, die jeweils "Hallo Welt" enthalten, unterschiedlich, aber die normalen Hashcodes wären gleich.

+0

Ich glaube, ich verstehe, dass ich dieses Problem nicht hatte, wenn ich Lollipop benutze. Warum? Und wie könnte ich jetzt das gleiche Verhalten bei Android 6 haben? – tjiagoM

+0

@tjiagoM Das bedeutet nur, dass die Objektposition in Lollipop gleich ist. Wie auch immer, ich denke, Ihre gewünschte Implementierung ist gewöhnlicher Hashcode. Es sollte in jeder Klasse verfügbar sein, die von Object herrührt, also probiere mSensorManager.getDefaultSensor (Sensor.TYPE_ACCELEROMETER)). HashCode() – Jehy

+0

Aber in meinem Post zeige ich, dass ich hashCode() verwende und es verschiedene Werte gibt ... – tjiagoM

1

Ich tue dies, indem ich eine Absicht mit zwei Extras (eine Zeichenfolge mit den neuen Werten und eine Ganzzahl mit dem HashCode des Sensors) ausstrahlt.

Wenn von „Rundfunk eine Absicht“, meinen Sie, dass Sie sendBroadcast() auf einem Context anrufen, beachten Sie bitte, dass Sie standardmäßig private Benutzerdaten sind undicht. Jede App kann Ihre Übertragungen hören und Sensordaten erhalten, auch ohne die entsprechenden Berechtigungen.

Wenn von „Rundfunk eine Absicht“, meinen Sie, dass Sie sendBroadcast() auf LocalBroadcastManager anrufen, dann kann ich drei wahrscheinlich sehen nähert sich Ihr Problem zu lösen:

  1. ersetzen, die mit einem Ereignis-Bus (zB greenrobot's EventBus), so dass Sie das Objekt Sensor selbst an die UI-Ebene übergeben können.

  2. Verwenden Sie Ihre eigene ID anstelle von hashCode(), damit sowohl der Dienst als auch die Aktivität vereinbaren können, wie ein bestimmter Sensor identifiziert werden kann.

  3. Lassen Sie den Dienst los und lassen Sie die Aktivität selbst für Sensor-Ereignisse registrieren.