Some time ago, a netizen sent a private message to me (@ Wu Ge) and asked me if I had done magnetic field sensors and could I have done compass? As I have already said in the first section, the magnetic field sensor can be used, but the algorithm is troublesome. The simplest compass can be made using a direction sensor. However, due to work relations, it has never been time to help him, now, let's write a simple compass tutorial, first map:
The layout file is very simple, just a flat picture of the compass.
As mentioned in the first section of the algorithm, values [0]: indicates the orientation, that is, the angle from which the mobile phone rotates around the Z axis. 0 indicates North (North); 90 indicates East (East); 180 indicates South (South); 270 indicates West (West ). If the value of values [0] is exactly the four values, and the mobile phone is placed horizontally, it indicates that the front of the mobile phone is the four directions. This feature can be used to implement the electronic compass. For more information, see section 1.
Code
Public void onSensorChanged (SensorEvent event) {// if the sensor type of the event triggered on the real machine is level sensor type if (event. sensor. getType () = Sensor. TYPE_ORIENTATION) {// get the float degree = event. values [0]; // create a rotation Animation (reverse turn degree) RotateAnimation ra = new RotateAnimation (currentDegree,-degree, Animation. RELATIVE_TO_SELF, 0.5f, Animation. RELATIVE_TO_SELF, 0.5f); // sets the animation duration ra. setDuration (200); // sets the retained state ra after the animation ends. setFillAfter (true); // start the animated image. startAnimation (ra); currentDegree =-degree ;}}
The idea is to obtain values [0] and rotate the image according to the value of values [0. All code is as follows:
Public class OrientationActivity extends Activity implementsSensorEventListener {public static final String TAG = "OrientationActivity direction Sensor"; private TextView TV _context; private Sensor mAccelerometer; private SensorManager mSensorManager; // record the orientation of the compass image. private float currentDegree = 0f; private ImageView image; @ Overrideprotected void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceStat E); setContentView (R. layout. activity_main_orien); infoViews (); // initialization control} private void infoViews () {// btn = (Button) findViewById (R. id. btn_sensor); TV _context = (TextView) findViewById (R. id. TV _context); TV _context.setText ("Compass"); mSensorManager = (SensorManager) getSystemService (Context. SENSOR_SERVICE); mAccelerometer = mSensorManager. getdefasensensor (Sensor. TYPE_ORIENTATION); image = (ImageView) findViewB YId (R. id. main_iv) ;}@ Overrideprotected void onResume () {if (mAccelerometer! = Null) {mSensorManager. registerListener (this, mAccelerometer, SensorManager. SENSOR_DELAY_NORMAL); Toast. makeText (getApplicationContext (), "This device has a direction sensor", 0 ). show ();} else {Toast. makeText (getApplicationContext (), "This device has no direction sensor", 0 ). show ();} super. onResume ();} protected void onPause () {super. onPause (); mSensorManager. unregisterListener (this);} public void onAccuracyChanged (Sensor sensor, int accuracy) {} public void onSensorChanged (SensorEvent event) {// if the sensor type of the event triggered on the real machine is level sensor type if (event. sensor. getType () = Sensor. TYPE_ORIENTATION) {// get the float degree = event. values [0]; // create a rotation Animation (reverse turn degree) RotateAnimation ra = new RotateAnimation (currentDegree,-degree, Animation. RELATIVE_TO_SELF, 0.5f, Animation. RELATIVE_TO_SELF, 0.5f); // sets the animation duration ra. setDuration (200); // sets the retained state ra after the animation ends. setFillAfter (true); // start the animated image. startAnimation (ra); currentDegree =-degree ;}}}
It's easy, but if we need optimization, we need to call the Criteria class to load location information:
LocationManager locationManager = (LocationManager) getSystemService (Context. LOCATION_SERVICE );
Criteria criteria = new Criteria ();
Criteria. setAccuracy (Criteria. ACCURACY_FINE); // you can specify the maximum precision.
Criteria. setAltitudeRequired (false); // No elevation information is required.
Criteria. setBearingRequired (false); // The orientation information is not required.
Criteria. setCostAllowed (true); // whether to allow payment
Criteria. setPowerRequirement (Criteria. POWER_LOW); // power requirements
Location = locationManager. getLastKnownLocation (locationManager. getBestProvider (criteria, true ));
Then write the location:
- LocationListener location = new LocationListener (){
-
- @ Override
- Public void onStatusChanged (String provider, int status, Bundle extras ){
- If (status! = LocationProvider. OUT_OF_SERVICE ){
- UpdateLocation (mLocationManager
- . GetLastKnownLocation (mLocationProvider ));
- } Else {
- MLocationTextView. setText (R. string. cannot_get_location );
- }
- }
-
- @ Override
- Public void onProviderEnabled (String provider ){
- }
-
- @ Override
- Public void onProviderDisabled (String provider ){
- }
-
- @ Override
- Public void onLocationChanged (Location location ){
- UpdateLocation (location); // update location
- }
- };
- } In this way, the geographic location can be called more accurately, but I found a problem during the writing process. Is the value [0] bound to the southeast and northwest China from the very beginning, otherwise, how can I start to point to the north? Please explain...