8080import static eu .basicairdata .clinometer .ClinometerApplication .KEY_PREF_CALIBRATION_OFFSET_2 ;
8181import static eu .basicairdata .clinometer .ClinometerApplication .KEY_PREF_CAMERA_EXPOSURE_COMPENSATION ;
8282import static eu .basicairdata .clinometer .ClinometerApplication .KEY_PREF_KEEP_SCREEN_ON ;
83+ import static eu .basicairdata .clinometer .ClinometerApplication .KEY_PREF_UNIT_OF_MEASUREMENT ;
8384
8485
8586public class ClinometerActivity extends AppCompatActivity implements SensorEventListener {
@@ -91,11 +92,11 @@ public static ClinometerActivity getInstance(){
9192return singleton ;
9293 }
9394
94- private ToneGenerator toneGen1 =new ToneGenerator (AudioManager .STREAM_MUSIC ,ToneGenerator .TONE_CDMA_KEYPAD_VOLUME_KEY_LITE );
95+ private final ToneGenerator toneGen1 =new ToneGenerator (AudioManager .STREAM_MUSIC ,ToneGenerator .TONE_CDMA_KEYPAD_VOLUME_KEY_LITE );
9596private Vibrator vibrator ;
9697
9798// RefAxis Animator
98- private PIDAnimator pid =new PIDAnimator (0.0f ,0.3f ,0.0f ,0.03f ,16 );
99+ private final PIDAnimator pid =new PIDAnimator (0.0f ,0.3f ,0.0f ,0.03f ,16 );
99100private float old_PIDValue =0.0f ;
100101
101102private static final int TOAST_TIME =2500 ;// The time a toast is shown
@@ -105,7 +106,11 @@ public static ClinometerActivity getInstance(){
105106private static final float AUTOLOCK_HORIZON_CHECK_THRESHOLD =5.0f ;// The zone of horizon check (+- 5 degrees)
106107private static final float ROTATION_THRESHOLD =5 ;// The threshold of the boundaries for DisplayRotation (in degrees)
107108private static final int SIZE_OF_MEANVARIANCE =200 ;// 2 seconds
108- private static final float ALPHA =0.04f ;// Weight of the new sensor reading
109+
110+ private static final float ALPHA =0.03f ;// Weight of the new sensor reading
111+ private float alpha0 =ALPHA ;
112+ private float alpha1 =ALPHA ;
113+ private float alpha2 =ALPHA ;
109114
110115private ClinometerApplication clinometerApplication ;
111116private SharedPreferences preferences ;
@@ -132,6 +137,11 @@ public static ClinometerActivity getInstance(){
132137// return singleton;
133138// }
134139
140+ private String formattedAngle0 ;
141+ private String formattedAngle1 ;
142+ private String formattedAngle2 ;
143+ private final DataFormatter dataFormatter =new DataFormatter ();
144+
135145private ClinometerView mClinometerView ;
136146private TextView mTextViewAngles ;
137147private TextView mTextViewToast ;
@@ -150,13 +160,13 @@ public static ClinometerActivity getInstance(){
150160private SensorManager mSensorManager ;
151161private Sensor mRotationSensor ;
152162
153- private float []gravity = {0 ,0 ,0 };// The (filtered) current accelerometers values
154- private float []gravity_gain = {0 ,0 ,0 };
155- private float []gravity_offset = {0 ,0 ,0 };
156- private float []gravity_calibrated = {0 ,0 ,0 };// The (filtered) current calibrated accelerometers values
163+ private final float []gravity = {0 ,0 ,0 };// The (filtered) current accelerometers values
164+ private final float []gravity_gain = {0 ,0 ,0 };
165+ private final float []gravity_offset = {0 ,0 ,0 };
166+ private final float []gravity_calibrated = {0 ,0 ,0 };// The (filtered) current calibrated accelerometers values
157167
158- private float []angle_calibration = {0 ,0 ,0 };// The angles for calibration: alpha, beta, gamma (in degrees)
159- private float []angle = {0 ,0 ,0 };// The (filtered) current angles (in degrees)
168+ private final float []angle_calibration = {0 ,0 ,0 };// The angles for calibration: alpha, beta, gamma (in degrees)
169+ private final float []angle = {0 ,0 ,0 };// The (filtered) current angles (in degrees)
160170
161171private final float [][]calibrationMatrix =new float [3 ][3 ];
162172
@@ -180,6 +190,16 @@ public static ClinometerActivity getInstance(){
180190private static Camera mCamera =null ;
181191private CameraPreview mPreview ;
182192
193+ private boolean doubleBackToExitPressedOnce ;
194+ private Handler mHandler =new Handler ();
195+
196+ private final Runnable mRunnable =new Runnable () {
197+ @ Override
198+ public void run () {
199+ doubleBackToExitPressedOnce =false ;
200+ }
201+ };
202+
183203
184204// --------------------------------------------------------------------------------------------------------------------------
185205// --- GETTERS AND SETTERS --------------------------------------------------------------------------------------------------
@@ -373,6 +393,11 @@ protected void onResume() {
373393
374394loadPreferences ();
375395
396+ formattedAngle0 =dataFormatter .format (angle [0 ]);
397+ formattedAngle1 =dataFormatter .format (angle [1 ]);
398+ formattedAngle2 =dataFormatter .format (angle [2 ]);
399+ mTextViewAngles .setText (formattedAngle0 +" " +formattedAngle1 +" " +formattedAngle2 );
400+
376401mFrameLayoutClinometer .setSystemUiVisibility (
377402//View.SYSTEM_UI_FLAG_IMMERSIVE |
378403// Set the content to appear under the system bars so that the
@@ -410,6 +435,25 @@ public void onStop() {
410435 }
411436
412437
438+ @ Override
439+ protected void onDestroy () {
440+ super .onDestroy ();
441+ if (mHandler !=null ) {mHandler .removeCallbacks (mRunnable ); }
442+ }
443+
444+
445+ @ Override
446+ public void onBackPressed () {
447+ if (doubleBackToExitPressedOnce ) {
448+ super .onBackPressed ();
449+ return ;
450+ }
451+ this .doubleBackToExitPressedOnce =true ;
452+ showToast (getString (R .string .toast_click_back_again_to_exit ));
453+ mHandler .postDelayed (mRunnable ,TOAST_TIME );
454+ }
455+
456+
413457public void onSensorChanged (SensorEvent event ) {
414458
415459if (event .sensor .getType () ==Sensor .TYPE_ACCELEROMETER ) {
@@ -477,6 +521,9 @@ public void onSensorChanged(SensorEvent event) {
477521// SIGNAL PROCESSING
478522
479523if (!isLocked ) {
524+ alpha0 =ALPHA * (float )(1 +Math .abs (mvGravity0 .getMeanValue () -event .values [0 ])*0.1 );
525+ alpha1 =ALPHA * (float )(1 +Math .abs (mvGravity1 .getMeanValue () -event .values [1 ])*0.1 );
526+ alpha2 =ALPHA * (float )(1 +Math .abs (mvGravity2 .getMeanValue () -event .values [2 ])*0.1 );
480527
481528// Weighted gravity reads
482529
@@ -485,16 +532,16 @@ public void onSensorChanged(SensorEvent event) {
485532gravity [1 ] = (event .values [1 ] -gravity_offset [1 ]) /gravity_gain [1 ];// Y
486533gravity [2 ] = (event .values [2 ] -gravity_offset [2 ]) /gravity_gain [2 ];// Z
487534 }else {
488- gravity [0 ] = (1 -ALPHA ) *gravity [0 ] + (ALPHA ) * (event .values [0 ] -gravity_offset [0 ]) /gravity_gain [0 ];
489- gravity [1 ] = (1 -ALPHA ) *gravity [1 ] + (ALPHA ) * (event .values [1 ] -gravity_offset [1 ]) /gravity_gain [1 ];
490- gravity [2 ] = (1 -ALPHA ) *gravity [2 ] + (ALPHA ) * (event .values [2 ] -gravity_offset [2 ]) /gravity_gain [2 ];
535+ gravity [0 ] = (1 -alpha0 ) *gravity [0 ] + (alpha0 ) * (event .values [0 ] -gravity_offset [0 ]) /gravity_gain [0 ];
536+ gravity [1 ] = (1 -alpha1 ) *gravity [1 ] + (alpha1 ) * (event .values [1 ] -gravity_offset [1 ]) /gravity_gain [1 ];
537+ gravity [2 ] = (1 -alpha2 ) *gravity [2 ] + (alpha2 ) * (event .values [2 ] -gravity_offset [2 ]) /gravity_gain [2 ];
491538 }
492539
493540// Apply Calibration values
494541
495- gravity_calibrated [0 ] =( float ) ( gravity [0 ] *calibrationMatrix [0 ][0 ] +gravity [1 ] *calibrationMatrix [0 ][1 ] +gravity [2 ] *calibrationMatrix [0 ][2 ]) ;
496- gravity_calibrated [1 ] =( float ) ( gravity [0 ] *calibrationMatrix [1 ][0 ] +gravity [1 ] *calibrationMatrix [1 ][1 ] +gravity [2 ] *calibrationMatrix [1 ][2 ]) ;
497- gravity_calibrated [2 ] =( float ) ( gravity [0 ] *calibrationMatrix [2 ][0 ] +gravity [1 ] *calibrationMatrix [2 ][1 ] +gravity [2 ] *calibrationMatrix [2 ][2 ]) ;
542+ gravity_calibrated [0 ] =gravity [0 ] *calibrationMatrix [0 ][0 ] +gravity [1 ] *calibrationMatrix [0 ][1 ] +gravity [2 ] *calibrationMatrix [0 ][2 ];
543+ gravity_calibrated [1 ] =gravity [0 ] *calibrationMatrix [1 ][0 ] +gravity [1 ] *calibrationMatrix [1 ][1 ] +gravity [2 ] *calibrationMatrix [1 ][2 ];
544+ gravity_calibrated [2 ] =gravity [0 ] *calibrationMatrix [2 ][0 ] +gravity [1 ] *calibrationMatrix [2 ][1 ] +gravity [2 ] *calibrationMatrix [2 ][2 ];
498545
499546mvGravity0 .loadSample (gravity_calibrated [0 ]);
500547mvGravity1 .loadSample (gravity_calibrated [1 ]);
@@ -590,7 +637,12 @@ public void onSensorChanged(SensorEvent event) {
590637
591638// You must put this setText here in order to force the re-layout also during the rotations.
592639// Without this, if you lock the measure during the rotation animation, the layout doesn't change correctly :(
593- mTextViewAngles .setText (String .format ("%1.1f° %1.1f° %1.1f°" ,angle [0 ],angle [1 ],angle [2 ]));
640+
641+ formattedAngle0 =dataFormatter .format (angle [0 ]);
642+ formattedAngle1 =dataFormatter .format (angle [1 ]);
643+ formattedAngle2 =dataFormatter .format (angle [2 ]);
644+ mTextViewAngles .setText (formattedAngle0 +" " +formattedAngle1 +" " +formattedAngle2 );
645+ // mTextViewAngles.setText(String.format("%1.1f° %1.1f° %1.1f°", angle[0], angle[1], angle[2]));
594646 }
595647
596648if (Math .abs (pid .getValue () -old_PIDValue ) >0.001 ) {
@@ -628,6 +680,7 @@ private void loadPreferences() {
628680else getWindow ().clearFlags (WindowManager .LayoutParams .FLAG_KEEP_SCREEN_ON );
629681
630682prefAutoLock =preferences .getBoolean (KEY_PREF_AUTOLOCK ,false );
683+ clinometerApplication .setPrefUM (Integer .parseInt (preferences .getString (KEY_PREF_UNIT_OF_MEASUREMENT , (getResources ().getStringArray (R .array .UMAnglesValues ))[0 ])));
631684prefAutoLockHorizonCheck =preferences .getBoolean (KEY_PREF_AUTOLOCK_HORIZON_CHECK ,true );
632685prefAutoLockTolerance =AUTOLOCK_MAX_TOLERANCE - (AUTOLOCK_MAX_TOLERANCE -AUTOLOCK_MIN_TOLERANCE ) *preferences .getInt (KEY_PREF_AUTOLOCK_PRECISION ,500 ) /1000 ;
633686Log .d ("Clinometer" ,String .format ("Auto Locking Tolerance = %1.3f" ,prefAutoLockTolerance ));
@@ -685,7 +738,11 @@ public void onAnimationUpdate(ValueAnimator updatedAnimation) {
685738 }
686739// You must put this setText here in order to force the re-layout also during the rotations.
687740// Without this, if you lock the measure during the rotation animation, the layout doesn't change correctly :(
688- mTextViewAngles .setText (String .format ("%1.1f° %1.1f° %1.1f°" ,angle [0 ],angle [1 ],angle [2 ]));
741+ formattedAngle0 =dataFormatter .format (angle [0 ]);
742+ formattedAngle1 =dataFormatter .format (angle [1 ]);
743+ formattedAngle2 =dataFormatter .format (angle [2 ]);
744+ mTextViewAngles .setText (formattedAngle0 +" " +formattedAngle1 +" " +formattedAngle2 );
745+ // mTextViewAngles.setText(String.format("%1.1f° %1.1f° %1.1f°", angle[0], angle[1], angle[2]));
689746 }
690747 });
691748animationR .start ();