How to Create a Compass in Android Code – Tutorial and Source Code

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 Further Readings

android compass code example

1.0 Compass in Android Code Video Demo

Our code for today will run just like the following video.

DOWNLOAD SOURCE CODE

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.

compass in android code example

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.

Further Readings

This can help you learn more about creating compass in android code. You can visit them and do more customizations!

Android SensorManager
Android RotateAnimation
Android Motion Sensors

The Code of a Ninja Resources

  • Alfred

    Nice tutorial! Thank you!

    • ninjazhai

      You’re welcome @Alfred, thanks and keep on visiting!

  • VENGATESAN A

    Hai Mike, I have tried your tutorial.. it’s nice,,,, Thanks!

    • ninjazhai

      Hi @VENGATESAN, thanks for giving your feedback, glad to know it works for you! :)

  • ninjazhai

    Hey @japethpoyaoan:disqus, are you sure you set up your xml layout properly? scan your xml tag names..

  • Bhushan Pant

    Hi, It is not working, the compass is not moving. Pls help.

    • ninjazhai

      Hi @bhushanpant:disqus, what do you see in your logcat?

      • kris

        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

  • YSN

    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?

    • ninjazhai

      Hi @YSN, what do you mean by the “specific point”? I think the compass always point to the north…

  • smb

    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.

    • ninjazhai

      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?

  • Nurzhan Dyussenaliyev

    It shows angle from geographic north or from magnet north?

    • ninjazhai

      Hey @nurzhandyussenaliyev:disqus , I think it shows the magnetic north because the device uses a magnetic sensor?

  • Cromm

    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)) ?

  • Gideon Steven Tobing

    thanks man, gonna try this app asap

    • ninjazhai

      @gideonsteventobing:disqus, sure man! Please let us know what happened in your tests!

  • Vahid

    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!

  • Gaurav Badarkhe

    I tried it its not working please help

    • ninjazhai

      Hello @gauravbadarkhe:disqus, what error message do you encounter?

  • June

    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??

  • June Kenya

    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??

  • June Kenya

    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??

    • ninjazhai

      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..

      • June Kenya

        thanks for fast reply!
        please refer attached pic, multiply like photoshop blend mode.
        Thank you!

        • ninjazhai

          @junekenya:disqus, you can achieve this by using a transparent background PNG image as the compass image..

          • June Kenya

            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!

      • June Kenya

        thank you for fast reply!
        please refer attached picture!