Click here to Skip to main content
15,893,564 members
Articles / Mobile Apps / Windows Mobile

Learn How to Find GPS Location on Any SmartPhone, and Then Make it Relevant

Rate me:
Please Sign up or sign in to vote.
4.94/5 (126 votes)
10 Feb 2009CPOL10 min read 775.3K   11.1K   381  
A step by step tutorial for getting GPS from any SmartPhone, even without GPS built in, and then making location useful.
using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Threading;
using DeepCast.Services;
using PhoneVoyage.Services;

namespace DeepCast.Location
{
    /// <summary>
    /// Location provider to get cell tower details from the Windows Mobile Radio Interface layer
    /// </summary>
    internal class CellTowerLocationProvider : ILocationProvider
    {
        #region pInvoke
        public delegate void RILRESULTCALLBACK(uint dwCode, IntPtr hrCmdID, IntPtr lpData, uint cbData, uint dwParam);
        public delegate void RILNOTIFYCALLBACK(uint dwCode, IntPtr lpData, uint cbData, uint dwParam);
        public static IntPtr hRil;
        [StructLayout(LayoutKind.Explicit)]
        class RILCELLTOWERINFO
        {
            [FieldOffset(0)]
            uint dwSize;
            [FieldOffset(4)]
            uint dwParams;
            [FieldOffset(8)]
            public uint dwMobileCountryCode;
            [FieldOffset(12)]
            public uint dwMobileNetworkCode;
            [FieldOffset(16)]
            public uint dwLocationAreaCode;
            [FieldOffset(20)]
            public uint dwCellID;
            [FieldOffset(24)]
            uint dwBaseStationID;
            [FieldOffset(28)]
            uint dwBroadcastControlChannel;
            [FieldOffset(32)]
            uint dwRxLevel;
            [FieldOffset(36)]
            uint dwRxLevelFull;
            [FieldOffset(40)]
            uint dwRxLevelSub;
            [FieldOffset(44)]
            uint dwRxQuality;
            [FieldOffset(48)]
            uint dwRxQualityFull;
            [FieldOffset(52)]
            uint dwRxQualitySub;
            /* More minor interesting fields below */
        }

        [DllImport("ril.dll")]
        private static extern IntPtr RIL_Initialize(uint dwIndex, RILRESULTCALLBACK pfnResult, RILNOTIFYCALLBACK pfnNotify, uint dwNotificationClasses, uint dwParam, out IntPtr lphRil);
        [DllImport("ril.dll", EntryPoint = "RIL_GetCellTowerInfo")]
        private static extern IntPtr RIL_GetCellTowerInfo(IntPtr hRil);
        [DllImport("ril.dll", EntryPoint = "RIL_Hangup")]
        private static extern IntPtr RIL_Hangup(IntPtr hRil);
        [DllImport("ril.dll")]
        private static extern IntPtr RIL_Deinitialize(IntPtr hRil);

        #endregion

        private static RILCELLTOWERINFO _towerDetails;
        private static AutoResetEvent waithandle = new AutoResetEvent(false);
        private System.Windows.Forms.Timer _timer = new System.Windows.Forms.Timer();
        private CellTower _currentTower;

        /// <summary>
        /// Initializes a new instance of the <see cref="CellTowerLocationProvider"/> class.
        /// </summary>
        public CellTowerLocationProvider()
        {
            _timer.Interval = 5000; // 5 seconds
            _timer.Tick += new EventHandler(_timer_Tick);
        }

        #region ILocationProvider Members

        /// <summary>
        /// Starts the timer.
        /// </summary>
        public void Start()
        {
            _timer.Enabled = true;
        }
        /// <summary>
        /// Stops the timer.
        /// </summary>
        public void Stop()
        {
            _timer.Enabled = false;
        }
        /// <summary>
        /// Gets the current location.
        /// </summary>
        /// <value>The current location.</value>
        public GeoLocation CurrentLocation
        {
            get
            {
                try
                {
                   
                    // If google didn't resolve location, try OpenCellID.org
                    OpenCellIdService cellService = new OpenCellIdService();
                    GeoLocation location = cellService.GetCellTowerLocation(_currentTower);
                    
                    if (location == GeoLocation.Empty)
                    {
                        // Try google first; their dataase seems to be the most comprehensive
                         location = GoogleMapsCellService.GetLocation(_currentTower);
                    }

                    return location;
                }
                catch // Not much else can be done
                {
                    return GeoLocation.Empty;
                }
            }
        }

        #endregion

        /// <summary>
        /// Handles the Tick event of the _timer control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void _timer_Tick(object sender, EventArgs e)
        {
            // Get the current cell tower every time the timer ticks
            _currentTower = GetCellTowerInfo();
        }

        /// <summary>
        /// Gets the cell tower info from the.
        /// </summary>
        /// <returns></returns>
        public static CellTower GetCellTowerInfo()
        {
            IntPtr radioInterfaceLayerHandle = IntPtr.Zero;
            IntPtr radioResponseHandle = IntPtr.Zero;

            // Initialize the radio layer with a result callback parameter.
            radioResponseHandle = RIL_Initialize(1, new RILRESULTCALLBACK(CellDataCallback), null, 0, 0, out radioInterfaceLayerHandle);

            // The initialize API call will always return 0 if initialization is successful.
            if (radioResponseHandle != IntPtr.Zero)
            {
                return null;
            }

            // Qusery for the current tower data.
            radioResponseHandle = RIL_GetCellTowerInfo(radioInterfaceLayerHandle);

            // Wait for cell tower info to be returned since RIL_GetCellTowerInfo invokes the 
            // callback method asynchronously.
            waithandle.WaitOne();

            // Release the RIL handle
            RIL_Deinitialize(radioInterfaceLayerHandle);

            // Convert the raw tower data structre data into a CellTower object
            return new CellTower()
            {
                TowerId = Convert.ToInt32(_towerDetails.dwCellID),
                LocationAreaCode = Convert.ToInt32(_towerDetails.dwLocationAreaCode),
                MobileCountryCode = Convert.ToInt32(_towerDetails.dwMobileCountryCode),
                MobileNetworkCode = Convert.ToInt32(_towerDetails.dwMobileNetworkCode),
            }; 
        }

        /// <summary>
        /// Responds to the RIL GetCellTowerInfo callback when data is available.
        /// </summary>
        public static void CellDataCallback(uint dwCode, IntPtr hrCmdID, IntPtr lpData, uint cbData, uint dwParam)
        {
            // Refresh the current tower details
            _towerDetails = new RILCELLTOWERINFO();

            // Copy result returned from RIL into structure
            Marshal.PtrToStructure(lpData, _towerDetails);

            // notify caller function that we have a result
            waithandle.Set();
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer PageLabs
United States United States
I'm the founder of PageLabs, a web-based performance and SEO optimization site.

Give your site a boost in performance, even take a free speed test!

http://www.pagelabs.com

Comments and Discussions