Today I’m going to share a very simple compass in android code that you can use whenever you are creating an application with a compass feature.
It’s good to see the most devices nowadays has a motion sensor capability to make a compass run.
Unfortunately, there are still some android devices (like Huawei Y300 and Lenovo P700i) does not have full support of motions sensors so this code will not work for them.
We will cover the following in this post:
1.0 Android Compass Video Demo
2.0 Compass App Needed Files
3.0 Complete Compass in Android Code
3.1 MainActivity.java
3.2 activity_main.xml
3.3 Some Notes
4.0 Download Source Code
5.0 Further Readings
1.0 Compass in Android Code Video Demo
Our code for today will run just like the following video.
2.0 Compass App Needed Files
You need to create your own compass image. For this example, I’m using a stock photo. Your image must be a PNG with transparent background, do not use this jpg file I used. Please note that the “north” must be at the top part of the image.
We will also need the two main code files seen in the complete code below.
3.0 Complete Android Compass Code
3.1 MainActivity.java where all the magic happens. The SensorManager was initialized in the onCreate() method and it was being moved or animated using the onSensorChanged() method.
package com.example.compassapp; import android.app.Activity; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.os.Bundle; import android.view.animation.Animation; import android.view.animation.RotateAnimation; import android.widget.ImageView; import android.widget.TextView; public class MainActivity extends Activity implements SensorEventListener { // define the display assembly compass picture private ImageView image; // record the compass picture angle turned private float currentDegree = 0f; // device sensor manager private SensorManager mSensorManager; TextView tvHeading; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // our compass image image = (ImageView) findViewById(R.id.imageViewCompass); // TextView that will tell the user what degree is he heading tvHeading = (TextView) findViewById(R.id.tvHeading); // initialize your android device sensor capabilities mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE); } @Override protected void onResume() { super.onResume(); // for the system's orientation sensor registered listeners mSensorManager.registerListener(this, mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION), SensorManager.SENSOR_DELAY_GAME); } @Override protected void onPause() { super.onPause(); // to stop the listener and save battery mSensorManager.unregisterListener(this); } @Override public void onSensorChanged(SensorEvent event) { // get the angle around the z-axis rotated float degree = Math.round(event.values[0]); tvHeading.setText("Heading: " + Float.toString(degree) + " degrees"); // create a rotation animation (reverse turn degree degrees) RotateAnimation ra = new RotateAnimation( currentDegree, -degree, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); // how long the animation will take place ra.setDuration(210); // set the animation after the end of the reservation status ra.setFillAfter(true); // Start the animation image.startAnimation(ra); currentDegree = -degree; } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { // not in use } }
3.2 activity_main.xml – Our layout file. Wrapped in RelativeLayout, the TextView is used to display the user’s current heading. The ImageView contains the compass image which is being animated like a compass using the code in our MainActivity.java
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#fff" > <TextView android:id="@+id/tvHeading" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_marginBottom="40dp" android:layout_marginTop="20dp" android:text="Heading: 0.0" /> <ImageView android:id="@+id/imageViewCompass" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/tvHeading" android:layout_centerHorizontal="true" android:src="@drawable/img_compass" /> </RelativeLayout>
3.3 Some notes
1. My app orientation is locked to portrait mode.
2. There are no special permissions in the Manifest file.
3. North Magnetic Pole is the point on the surface of Earth’s
Northern Hemisphere.
4. True north, or the geodetic north, is the direction along the earth’s surface towards the geographic North Pole.
5. Android SensorManager uses the magnetic North Pole.
5.0 Download Source Code
You can get the source code by following the whole, well detailed and free tutorial above. But isn’t it more convenient if you can just download the complete source code we used, and play around it?
There’s a small fee in getting the complete source code, it is small compared to the:
✔ Value or skill upgrade it can bring you, or | YES |
✔ Income you can get from your website project or business. | YES |
✔ Precious time you save. | YES |
5.0 Further Readings
This can help you learn more about creating compass in android code. You can visit them and do more customizations!
1. Android SensorManager
2. Android RotateAnimation
3. Android Motion Sensors
4. Magnetic North Pole vs. Geographic North Pole
55 responses to “How to Create a Compass in Android Code – Tutorial and Source Code”
Nice tutorial! Thank you!
You’re welcome @Alfred, thanks and keep on visiting!
Hai Mike, I have tried your tutorial.. it’s nice,,,, Thanks!
Hi @VENGATESAN, thanks for giving your feedback, glad to know it works for you! :)
Hi, sir Mike. I’m having problems in the MainActivity code. I keep on getting an error on “image = (ImageView) findViewById(R.id.imageViewCompass);” that says “imageViewCompass cannot be resolved or is not a field” I tried every solutions out there but everytime I apply them there’s sorta new problem coming out. Thanks in advance! :)
Hey @japethpoyaoan:disqus, are you sure you set up your xml layout properly? scan your xml tag names..
Hi, It is not working, the compass is not moving. Pls help.
Hi @bhushanpant:disqus, what do you see in your logcat?
08-04 23:36:43.494: E/Trace(6020): error opening trace file: No such file or directory (2)
08-04 23:36:43.634: I/Adreno200-EGL(6020): : EGL 1.4 QUALCOMM build: AU_LINUX_ANDROID_JB_REL_2.0.3.04.01.02.21.099_msm7627a_JB_REL_2.0.3_CL3357771_release_AU (CL3357771)
08-04 23:36:43.634: I/Adreno200-EGL(6020): Build Date: 02/19/13 Tue
08-04 23:36:43.634: I/Adreno200-EGL(6020): Local Branch:
08-04 23:36:43.634: I/Adreno200-EGL(6020): Remote Branch: quic/jb_rel_2.0.3
08-04 23:36:43.634: I/Adreno200-EGL(6020): Local Patches: NONE
08-04 23:36:43.634: I/Adreno200-EGL(6020): Reconstruct Branch: AU_LINUX_ANDROID_JB_REL_2.0.3.04.01.02.21.099 + NOTHING
08-04 23:36:43.664: D/memalloc(6020): ion: Mapped buffer base:0x53d9e000 size:1536000 offset:0 fd:61
08-04 23:36:43.664: D/memalloc(6020): ion: Mapped buffer base:0x4d778000 size:4096 offset:0 fd:63
08-04 23:36:43.764: D/memalloc(6020): ion: Mapped buffer base:0x542f0000 size:1536000 offset:0 fd:66
08-04 23:36:43.764: D/memalloc(6020): ion: Mapped buffer base:0x4d78f000 size:4096 offset:0 fd:68
You have to register the listener ,
mSensorManager.registerListener(this, mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION),
SensorManager.SENSOR_DELAY_GAME);
Hey thanks for that tutorial its working really nice. Is there a way to rotate the compass to a specific point if i get the coordinates from google maps?
Hi @YSN, what do you mean by the “specific point”? I think the compass always point to the north…
Hello, nice and easy to implement your code. I have the same need as YSN. I need the compass to point to a specific coordinate. NOT to the north. Maybe we can´t call it a compass, but I need an arrow pointing to a specific coordinate. Is there a way to achieve that?
NOT WORKING MEANS NO ROTATION ABOVE WORDS .
ANY INTERNET PREMISSION NEEDED OR WHAT HAPPPENED SIR G?
I notice that your video carefully avoids pointing the compass North. The animation breaks when passing from 359 degrees to 360/0 degrees. It’s an obvious problem that should have been fixed. Hiding this bug is just not right.
Hi @smb, thanks for you comment! For me it works just fine, and I’m not hiding any bugs. Please let us know if you have a better solution, or fixes maybe?
I solved this issue using a method. This method is also used to smooth the glitches of values.
You can see the method named “filter3D()” in the code
https://github.com/yasiralijaved/GenRadar/blob/master/src/com/yasiralijaved/genradar/utils/LowPassFilter.java
It shows angle from geographic north or from magnet north?
Hey @nurzhandyussenaliyev:disqus , I think it shows the magnetic north because the device uses a magnetic sensor?
Hi, I’ve a question, is that “degree” that set the orientation of the north ? If yes, how can I modified it to make the compass pointing specifics geographic coordinates (like telling the apps that the north is in (x,y) and not 82.7° N 114.4° W (which are the north coordinates (geographics)) ?
Hey @Cromm, yes, maybe these formulas can help you with that http://www.sunearthtools.com/dp/tools/conversion.php#contents
thanks man, gonna try this app asap
@gideonsteventobing:disqus, sure man! Please let us know what happened in your tests!
Hi, thanks for the code, it works like a charm! But I really do not understand how to use this app. I thought it shows the magnetic north, o the app tells me which direction is north. but -as you do in the video- every time I rotate my phone the north sign on the image (N sign) points to a different direction for north!
I tried it its not working please help
Hello @gauravbadarkhe:disqus, what error message do you encounter?
Thank you for your tutorial, Mike!
I’m trying to customize your code and have one question.
Is there any way to blend compass image and background image with Multiply-like blending mode??
Thank you for your tutorial, Mike!
I’m trying to customize your code and have one question.
Is there any way to blend compass image and background image with Multiply-like blending mode??
Thank you for nice tutorial!
I’m trying to customize little bit and have one question.
Is there any way to blend compass image and background image with Multiply-like blending mode??
You’re welcome @junekenya:disqus! You certainly can change the compass and background image, but what do you mean by “Multiply-like blending mode”? Would you attach a photo here so that we can see what it looks like? Thanks..
Thank you for your fast reply!
Please refer attached photo. like blend mode of photoshop.
Thank you!
thanks for fast reply!
please refer attached pic, multiply like photoshop blend mode.
Thank you!
@junekenya:disqus, you can achieve this by using a transparent background PNG image as the compass image..
Sorry example picture was not good..
Is it possible to do it by using PorterDuff.Mode??
If it is possible, how to do it?
Thank you!
thank you for fast reply!
please refer attached picture!
how can i do permissions in the Manifest file
Image is rotating along with the mobile orientation as it wants . but its not showing the correct direction as in compass..anyone has solved this issue??
Hi I noticed running this app that it doesn’t seem to start point to north. Is there anyway to make it start at how ever many degrees it’s pointing away from true north?
Hello @wilsonwillson:disqus, this app should point to the magnetic north pole. Did you achieve the same output as our video demo above?
hi sir after running this …..the image is not moving?
Hello @disqus_kJrCRn5FvP:disqus, let us know what your logcat says. That’s how we can obtain a clue about what’s wrong. Thanks!
02-04 10:30:03.889 2398-2398/? D/dalvikvm﹕ Not late-enabling CheckJNI (already on)
02-04 10:30:03.909 2398-2398/? I/dalvikvm﹕ Could not find method android.app.Notification$Builder.setLocalOnly, referenced from method com.google.android.gms.common.GooglePlayServicesUtil.zza
02-04 10:30:03.909 2398-2398/? W/dalvikvm﹕ VFY: unable to resolve virtual method 244: Landroid/app/Notification$Builder;.setLocalOnly (Z)Landroid/app/Notification$Builder;
02-04 10:30:03.909 2398-2398/? D/dalvikvm﹕ VFY: replacing opcode 0x6e at 0x00c8
02-04 10:30:03.909 2398-2398/? I/dalvikvm﹕ Could not find method android.content.pm.PackageManager.getPackageInstaller, referenced from method com.google.android.gms.common.GooglePlayServicesUtil.zzh
02-04 10:30:03.909 2398-2398/? W/dalvikvm﹕ VFY: unable to resolve virtual method 547: Landroid/content/pm/PackageManager;.getPackageInstaller ()Landroid/content/pm/PackageInstaller;
02-04 10:30:03.909 2398-2398/? D/dalvikvm﹕ VFY: replacing opcode 0x6e at 0x000b
02-04 10:30:03.929 2398-2404/? D/dalvikvm﹕ Debugger has detached; object registry had 1 entries
02-04 10:30:03.959 2398-2414/? I/GMPM﹕ App measurement is starting up
02-04 10:30:03.969 2398-2402/? D/dalvikvm﹕ GC_CONCURRENT freed 250K, 10% free 2765K/3068K, paused 10ms+0ms, total 12ms
02-04 10:30:04.069 2398-2398/? D/﹕ HostConnection::get() New Host Connection established 0xb86cb9f0, tid 2398
02-04 10:30:04.259 2398-2398/? W/EGL_emulation﹕ eglSurfaceAttrib not implemented
02-04 10:30:04.269 2398-2398/? D/OpenGLRenderer﹕ Enabling debug mode 0
02-04 10:30:05.839 2398-2404/? I/jdwp﹕ Ignoring second debugger — accepting and dropping
02-04 10:30:22.889 2398-2398/? V/GCMRegistrar﹕ Registering receiver
02-04 10:30:22.889 2398-2398/? D/GCMRegistrar﹕ resetting backoff for com.androidhive.pushnotifications
02-04 10:30:22.889 2398-2398/? V/GCMRegistrar﹕ Registering app com.androidhive.pushnotifications of senders 1002468668191
02-04 10:30:22.909 2398-2398/? D/dalvikvm﹕ GC_FOR_ALLOC freed 245K, 9% free 3033K/3328K, paused 14ms, total 14ms
02-04 10:30:22.979 2398-2398/? W/EGL_emulation﹕ eglSurfaceAttrib not implemented
02-04 10:30:27.369 2398-2398/? V/GCMBroadcastReceiver﹕ onReceive: com.google.android.c2dm.intent.REGISTRATION
02-04 10:30:27.369 2398-2398/? V/GCMBroadcastReceiver﹕ GCM IntentService class: com.androidhive.pushnotifications.GCMIntentService
02-04 10:30:27.369 2398-2398/? V/GCMBaseIntentService﹕ Acquiring wakelock
Nice and simple tutorial, but the animation to the compass can be a little choppy because of the unfiltered parsing and apply the data to the animation.
Hello @Phouthasak, thanks for the kind words! Do you have any tip on how to solve that little animation choppiness?
How to test the app on the hts phone
hey,
i am getting this error….
Error:Execution failed for task ‘:app:mergeDebugResources’.
> Some file crunching failed, see logs for details
can you please help me out.
question, why is it locked in portrait mode? is the value different when the configuration layout changes?
Not working. The wont even rotate.
The compass image wont rotate.
Would you tell us any error message you see in your console?
Compass image is not rotating smoothly and not showing north direction. It will stop any where .
i have use your tutorial but its not working in API level > 23 marshmallow
hello mam prachi here
In compass andriod application how we major the height and actual real postion .suppose i m in building 1st floor and my frd 8 th foor so how compass major the height? plz mam help
Your tutorial does not work, I can’t run it. Also there is only picture of compass nothing else, it does’t move….
How to add a declination to this code