package com.google.android.stardroid.activities; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.location.LocationManager; import android.location.LocationProvider; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.util.Log; import android.widget.TextView; import com.google.android.stardroid.R; import com.google.android.stardroid.StardroidApplication; import com.google.android.stardroid.activities.util.SensorAccuracyDecoder; import com.google.android.stardroid.control.AstronomerModel; import com.google.android.stardroid.control.LocationController; import com.google.android.stardroid.units.GeocentricCoordinates; import com.google.android.stardroid.units.LatLong; import com.google.android.stardroid.util.Analytics; import com.google.android.stardroid.util.MiscUtil; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashSet; import java.util.Locale; import java.util.Set; import java.util.TimeZone; import javax.inject.Inject; public class DiagnosticActivity extends InjectableActivity implements SensorEventListener { private static final String TAG = MiscUtil.getTag(DiagnosticActivity.class); private static final int UPDATE_PERIOD_MILLIS = 500; @Inject Analytics analytics; @Inject StardroidApplication app; @Inject SensorManager sensorManager; @Inject ConnectivityManager connectivityManager; @Inject LocationManager locationManager; @Inject LocationController locationController; @Inject AstronomerModel model; @Inject Handler handler; @Inject SensorAccuracyDecoder sensorAccuracyDecoder; private Sensor accelSensor; private Sensor magSensor; private Sensor gyroSensor; private Sensor rotationVectorSensor; private Sensor lightSensor; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); DaggerDiagnosticActivityComponent.builder().applicationComponent( getApplicationComponent()).diagnosticActivityModule(new DiagnosticActivityModule(this)) .build().inject(this); setContentView(R.layout.activity_diagnostic); } @Override public void onStart() { super.onStart(); analytics.trackPageView(Analytics.DIAGNOSTICS_ACTIVITY); setText(R.id.diagnose_phone_txt, Build.MODEL + " (" + Build.HARDWARE + ") " + Locale.getDefault().getLanguage()); String androidVersion = String.format(Build.VERSION.RELEASE + " (%d)", Build.VERSION.SDK_INT); setText(R.id.diagnose_android_version_txt, androidVersion); String skyMapVersion = String.format( app.getVersionName() + " (%d)", app.getVersion()); setText(R.id.diagnose_skymap_version_txt, skyMapVersion); } private boolean continueUpdates; @Override public void onResume() { super.onResume(); onResumeSensors(); continueUpdates = true; handler.post(new Runnable() { public void run() { updateLocation(); updateModel(); updateNetwork(); if (continueUpdates) { handler.postDelayed(this, UPDATE_PERIOD_MILLIS); } } }); } private void onResumeSensors() { accelSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); int absentSensorColor = getResources().getColor(R.color.absent_sensor); if (accelSensor == null) { setColor(R.id.diagnose_accelerometer_values_txt, absentSensorColor); } else { sensorManager.registerListener(this, accelSensor, SensorManager.SENSOR_DELAY_NORMAL); } magSensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); if (magSensor == null) { setColor(R.id.diagnose_compass_values_txt, absentSensorColor); } else { sensorManager.registerListener(this, magSensor, SensorManager.SENSOR_DELAY_NORMAL); } gyroSensor = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE); if (gyroSensor == null) { setColor(R.id.diagnose_gyro_values_txt, absentSensorColor); } else { sensorManager.registerListener(this, gyroSensor, SensorManager.SENSOR_DELAY_NORMAL); } rotationVectorSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR); if (rotationVectorSensor == null) { setColor(R.id.diagnose_rotation_values_txt, absentSensorColor); } else { sensorManager.registerListener(this, rotationVectorSensor, SensorManager.SENSOR_DELAY_NORMAL); } lightSensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT); if (lightSensor == null) { setColor(R.id.diagnose_light_values_txt, absentSensorColor); } else { sensorManager.registerListener(this, lightSensor, SensorManager.SENSOR_DELAY_UI); } } private void updateLocation() { // TODO(johntaylor): add other things like number of satellites and status String gpsStatusMessage; try { LocationProvider gps = locationManager.getProvider(LocationManager.GPS_PROVIDER); boolean gpsStatus = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); if (gps == null) { gpsStatusMessage = getString(R.string.no_gps); } else { gpsStatusMessage = gpsStatus ? getString(R.string.enabled) : getString(R.string.disabled); } } catch (SecurityException ex) { gpsStatusMessage = getString(R.string.permission_disabled); } setText(R.id.diagnose_gps_status_txt, gpsStatusMessage); LatLong currentLocation = locationController.getCurrentLocation(); String locationMessage = currentLocation.getLatitude() + ", " + currentLocation.getLongitude(); // Current provider not working + " (" + locationController.getCurrentProvider() + ")"; setText(R.id.diagnose_location_txt, locationMessage); } private void updateModel() { float magCorrection = model.getMagneticCorrection(); setText(R.id.diagnose_magnetic_correction_txt, Math.abs(magCorrection) + " " + (magCorrection > 0 ? getString(R.string.east) : getString(R.string.west)) + " " + getString(R.string.degrees)); AstronomerModel.Pointing pointing = model.getPointing(); GeocentricCoordinates lineOfSight = pointing.getLineOfSight(); // TODO(johntaylor): maybe show RA in hours instead setText(R.id.diagnose_pointing_txt, lineOfSight.getRa() + ", " + lineOfSight.getDec()); Date nowTime = model.getTime(); SimpleDateFormat dateFormatUtc = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss"); dateFormatUtc.setTimeZone(TimeZone.getTimeZone("UTC")); SimpleDateFormat dateFormatLocal = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss"); setText(R.id.diagnose_utc_datetime_txt, dateFormatUtc.format(nowTime)); setText(R.id.diagnose_local_datetime_txt, dateFormatLocal.format(nowTime)); } @Override public void onPause() { super.onPause(); continueUpdates = false; sensorManager.unregisterListener(this); } public void onAccuracyChanged(Sensor sensor, int accuracy) { knownSensorAccuracies.add(sensor); Log.d(TAG, "set size" + knownSensorAccuracies.size()); int sensorViewId; if (sensor == accelSensor) { sensorViewId = R.id.diagnose_accelerometer_values_txt; } else if (sensor == magSensor) { sensorViewId = R.id.diagnose_compass_values_txt; } else if (sensor == gyroSensor) { sensorViewId = R.id.diagnose_gyro_values_txt; } else if (sensor == rotationVectorSensor) { sensorViewId = R.id.diagnose_rotation_values_txt; } else if (sensor == lightSensor) { sensorViewId = R.id.diagnose_light_values_txt; } else { Log.e(TAG, "Receiving accuracy change for unknown sensor " + sensor); return; } setColor(sensorViewId, sensorAccuracyDecoder.getColorForAccuracy(accuracy)); } private Set<Sensor> knownSensorAccuracies = new HashSet<>(); public void onSensorChanged(SensorEvent event) { Sensor sensor = event.sensor; if (!knownSensorAccuracies.contains(sensor)) { onAccuracyChanged(sensor, event.accuracy); } int valuesViewId; if (sensor == accelSensor) { valuesViewId = R.id.diagnose_accelerometer_values_txt; } else if (sensor == magSensor) { valuesViewId = R.id.diagnose_compass_values_txt; } else if (sensor == gyroSensor) { valuesViewId = R.id.diagnose_gyro_values_txt; } else if (sensor == rotationVectorSensor) { valuesViewId = R.id.diagnose_rotation_values_txt; } else if (sensor == lightSensor) { valuesViewId = R.id.diagnose_light_values_txt; } else { Log.e(TAG, "Receiving values for unknown sensor " + sensor); return; } float[] values = event.values; setArrayValuesInUi(valuesViewId, values); // Something special for rotation sensor - convert to a matrix. if (sensor == rotationVectorSensor) { float[] matrix = new float[9]; SensorManager.getRotationMatrixFromVector(matrix, event.values); for (int row = 0; row < 3; ++row) { switch(row) { case 0: valuesViewId = R.id.diagnose_rotation_matrix_row1_txt; break; case 1: valuesViewId = R.id.diagnose_rotation_matrix_row2_txt; break; case 2: default: valuesViewId = R.id.diagnose_rotation_matrix_row3_txt; } float[] rowValues = new float[3]; for (int col = 0; col < 3; ++col) { rowValues[col] = matrix[row * 3 + col]; } setArrayValuesInUi(valuesViewId, rowValues); } } } private void setArrayValuesInUi(int valuesViewId, float[] values) { StringBuilder valuesText = new StringBuilder(); for (float value : values) { valuesText.append(String.format("%.2f", value)); valuesText.append(','); } valuesText.setLength(valuesText.length() - 1); setText(valuesViewId, valuesText.toString()); } private void updateNetwork() { NetworkInfo activeNetwork = connectivityManager.getActiveNetworkInfo(); boolean isConnected = activeNetwork != null && activeNetwork.isConnectedOrConnecting(); String message = isConnected ? getString(R.string.connected) : getString(R.string.disconnected); if (isConnected) { if (activeNetwork.getType() == ConnectivityManager.TYPE_WIFI) { message += getString(R.string.wifi); } if (activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE) { message += getString(R.string.cell_network); } } setText(R.id.diagnose_network_status_txt, message); } private void setText(int viewId, String text) { ((TextView) findViewById(viewId)).setText(text); } private void setColor(int viewId, int color) { ((TextView) findViewById(viewId)).setTextColor(color); } }