Home > Android, Programming > Building an offline map app for Android

Building an offline map app for Android

Hello there :), this tutorial series is about building a very simple map application for Android from scratch and without using Google™ APIs

(Don’t get frightened by the scroll bar of your browser 😀 the comments made this post look long 😀 )

The main app features will be:

  1. Displaying a map stored in a database on the SDcard, in other words : offline* map, no internet connection is required (but easy to implement online functionality).
  2. User can touch control the map (Panning), zoom in\out using volume keys.
  3. A marker will be displayed on the map depending on the user’s GPS position.

*Update 16/8/2012: online maps are now supported in tutorial part 6

as mentioned before : we’re not going to use Google™ APIs.

As you can see the app will be simple, other more complex functions can be added later.

Q: Why not use Google™ maps APIs (eg: MapActivity)?
A: it requires a working internet connection.
A: you might want to write your own classes.
A: you might want to know how things work.

Q: Aren’t there free map apps on the Android Market?
A: Yes there are and they are really good ones, Locus Free, RMaps, Orux Maps, these apps can run with both online and offline modes, I mainly use Locus Free, but I like writing my own apps and learn new things.

before starting this tutorial I’ll show you the final result, so that you can decide whether  to continue reading or not

The app and the tutorials target API Level 7 as a minimum SDK (That’s Android 2.1 )

MapApp Screenshot

A screenshot from the emulator
(I’m not really in Madagascar, just picked a random point :P)

Here’s the source code (Eclipse Project) and the apk file, after you install it on your device\emulator, copy this map file world.sqlitedb to your /sdcard/mapapp/ (You’ll need to make the folder yourself).

Okay, Start the GPS and run the app, A red marker will be displayed to pinpoint your location when a GPS fix is available.

  • Use volume keys to zoom in\out.
  • Drag the map with your finger.
  • M\Menu to simulate being in Madagascar.
  • H\Camera focus button to center the marker in screen.

This map was downloaded from OpenStreetMap servers with only 4 levels of zoom, zooming more will only display a gray background with no map visible, the reason for this is the map file not the app itself, you can use a different map file or internet map source with more zoom levels (more on that later).

This app can be a skeleton for more exciting apps, once you’ve done this simple app you can add features like:

  1. Add a tracking feature which allows you to save and view your path on a map, it’s very simple once you have finished writing a class capable of rendering a map.
  2. Extract location data from photos to display thumbnails of the photos on a map, this way you can see where did you take your photos, there’s actually a cool app for Windows Phone 7 that does that, it’s called Where Did I Take That.
  3. Add proximity alerts, you might want to be notified when you get close to some places.
  4. Any other idea that requires a map :).

Although these tutorials are about creating an offline maps app, I’ll give some hints on how to easily make it work with online map services, with the proper app design it will be easy to switch between two modes.
After reading all this, I hope that I got your attention and you’re interested in this tutorial, if not it’s okay with me 🙂

I’ll try to keep each tutorial as short as possible.

Series outline:

Each tutorial title will start with the prefix “MapApp” :).

I really hope you’re still reading this :D…

Advertisements
Categories: Android, Programming Tags: , ,
  1. 10/03/2012 at 12:21 am

    This is an interesting approach, didn’t thought of an offline map.

    • Fuchs
      10/03/2012 at 10:27 am

      I had to use offline maps since I rarely have internet access on my phone :).

      • jaggy
        22/04/2014 at 8:27 am

        hi fush,i am very neew to this android apps.but i tried out some coding using eclipse.but failed to do it.as it shows redmark underlined to some java file.can you please tell how do step by step using eclipse for createing offline map.i followed Ghoshehsoft’s Blog. i coppied the TilesManager,TilesProvider. Creating MapView in XML .and created it.but it show cannot launch.can please guide me to make this apps.i am marineir you to create apps for my ships navigation.its should consist waypoint.heading cource,lat and long, bearing.i had download one apps marine navigator.i need to make same apps.can you please help me to do it.thanks in addvance
        and this is my mail id:poojary44@gmail.com

        • Fuchs
          23/04/2014 at 8:52 pm

          Hi Jaggy.
          Before jumping into creating a map app you should first know the basics of Android and an IDE like Eclipse.
          After that you can simply import a project and run it on your phone to see how it works.
          One good book is Beginning Android 4 Application Development, you might want to check it out.
          I can help you with specific questions but other than that it would be much efficient for both of us if you read a chapter from a book for example 🙂 .

  2. DSC
    23/03/2012 at 3:50 am

    This looks promising!
    I’m looking into using nautical maps with a GPS location marker – and at sea the only option is offline maps.

  3. harikrishna
    02/04/2012 at 12:21 am

    sir the code is not working for me. when i loaded the project into the eclipse, it does not show the layout. the app alse crashed when i installed it into my phone. so can you please help me with it.

    • Fuchs
      02/04/2012 at 11:55 pm

      Hi, you’re right about the layout,
      the reason for this is because the activity only contains one custom view called MapView and we create this view in the code.

      About the crash: did you copy the database provided with the app to the right location?
      If yes and the app still crashes you can debug the app and when it crashes check the LogCat in eclipse, it should provide the exception info and a stack trace.

      If it’s still crashing please send me the error you find in the LogCat.
      Please let me :).

  4. harikrishna
    03/04/2012 at 7:54 am

    ya i copied it.. i tried on many phones.im using a zte-blade 2.2 froyo phone. i dnt know watz wrong.can you please help me out dude. ma college project deadline is nearing…

    • Fuchs
      03/04/2012 at 10:09 am

      Did you try debugging the project?
      The LogCat should contain the exception details.
      I really want to help but without more information there’s nothing I can do from here.

  5. lsat
    16/04/2012 at 8:04 pm

    i was trying to test this app and could not find a way to copy the maps file to the sdcard. I dont have an external SD card. Is it possible to run this application on my Samsung Captivate ?

    • Fuchs
      16/04/2012 at 8:55 pm

      Wow! my bad!, a device without an SD card! never came to my mind :),
      Anyway, I assume that you can put files on your phone memory right? If you can then you only need to change the database path in the code, in the MapAppActivity.java/initViews()

      Please let me know.

  6. lsat
    16/04/2012 at 9:07 pm

    Thanks for the response .. However i figured out a way ..

    Try 1: I put the file in assets directory and modified your code to read from there .. for some reason it kept giving my FileNotFound exception on output steam.

    Try 2: I downloaded an app called AndroidCommander link:http://androidcommander.com/
    I could then manually create the folder and copy the file. This worked fine. I could see the Map view but was not able to zoom. when i click on the menu icon on the phone it displayed lat long values.

    Does the app allow you to zoom ?

    Also how did u create this file ? i plan to use OpenStreetMap too for my app and would like to know how to create such file with decent zoom levels.

    • Fuchs
      16/04/2012 at 9:15 pm

      You’re welcome :), glad it worked.
      This app is very very simple, no fancy controls or multi touch support
      -Use volume keys to zoom in\out.
      -Drag the map with your finger.
      -M\Menu to simulate being in Madagascar.
      -H\Camera focus button to center the marker in screen.

      The database was created using Mobile Atlas Creator, exported in RMaps format, using this atlas creator with OpenStreetMap will usually get the creator blocked from reaching the tiles servers, I downloaded the tiles very slowly and yet I got some blocked tiles!

      If you create an online map app then you only download the tiles you need, and hopefully you won’t get blocked.

  7. lsat
    16/04/2012 at 9:29 pm

    I didn’t know i could zoom .. after zooming the details are pretty neat .. i might just need to add 2 more level of zooms since you already have upto 4. This is an excellent article as first steps to offline maps app programming. I might need to look into Mobile Atlas Creator to see if i could download few more levels but this is good to begin with. I might need your help later with database creation. I guess will buzz you then. For now thanks a lot for your help.

    • Fuchs
      17/04/2012 at 4:50 am

      Pre-rendered tiles usually have zoom levels up to 18.
      If you need any help just tell me.

  8. lsat
    17/04/2012 at 7:30 pm

    i downloaded a map for a specific city and am plotting a point within that. I just downloaded tiles between zoom levels 10 -13. And in Tiles Manager am setting the min and max zoom levels after reading from the sqlitedb file accordingly so even if the user tries to go beyond the zoom levels, he cant. however when i do that, i loose the point. It shows me an area that is outside my image range. How can i follow a specific geopoint and make the default screen show the image at that zoom level by default ?

    • lsat
      17/04/2012 at 7:45 pm

      The values are:

      Tile Index: Point(484, 500)
      Rect(483, 498 – 485, 502)

      But i still see the screen as grey.

    • lsat
      17/04/2012 at 8:23 pm

      I commented the call to function restoreMapViewSettings(); in MapAppActivity.java – onResume() and it displayed the map at the right zoom level.

      I could see a lot of exception strack trace in logCat that was due to the cursor being open. I added the cursor.close in TilesProvider class and that resolved the exception.

      I also see that fetchTiles is getting called multiple times even before the app gets loaded. preferrably it should get called just once. I might look into this later but for now the code is working perfect. Thanks.

      • Fuchs
        18/04/2012 at 5:15 am

        Sorry I couldn’t help you in time, and thank you for the cursor note.

  9. lsat
    24/04/2012 at 10:03 pm

    I need to implement a feature where a user taps an area on the map and it splots a marker there. because tap was interferering when i would drag the map, i implemented double tap using gestures. Now its plotting the point. However when i drag the map, the point stays at the X,Y location of the screen rather than the lat long poistion of the map. On double tap i was fetching the lat long of the point using the method defined in TilesManager -> pixelXYToLonLat. However that doesn’t seem to be returning the correct value. Any idea how i can get this working ?

  10. lsat
    24/04/2012 at 10:33 pm

    Alright i got part 1 working: -> “However when i drag the map, the point stays at the X,Y location of the screen rather than the lat long poistion of the map”

    But i still think the lat long returned by pixelXYToLonLat is not accurate. or am missing something. It plots at a different position than where clicked. I have to zoom out a level to view that point. Not sure whats going on.

  11. lsat
    24/04/2012 at 11:14 pm

    Here’s the code:

    private PointD userLoc;
    .......
    
    
     public boolean onDoubleTap(MotionEvent e) {
            float x = e.getX();
            float y = e.getY();
            Point pixels1 = tileManager.lonLatToPixelXY(seekLocation.x, seekLocation.y);
    			
    	int markerX = (int)x;
    	int markerY = (int)y;
    	// Subtract diff from that position
    	Point pixels2 = new Point(pixels1.x - markerX, pixels1.y - markerY);
    			
    	userLoc = tileManager.pixelXYToLonLat(pixels2.x ,pixels2.y);
    			
    	invalidate();
            return true;
            }
    
    .....
    void drawMarker(Canvas canvas, Point offset)
    {
     .... 
    if(userLoc!=null)
    {
    				
    	// Add offset to the marker position
    	Point markerPos = tileManager.lonLatToPixelXY(userLoc.x, userLoc.y);
    				
    				
    	// Add offset to the marker position
    	int markerX = markerPos.x - offset.x;
    	int markerY = markerPos.y - offset.y;
    				
    	canvas.drawBitmap(positionMarker, markerX - positionMarker.getWidth() / 2, markerY - positionMarker.getHeight() / 2,bitmapPaint);
    }
    ....
    }
    
    • Fuchs
      25/04/2012 at 5:59 am

      Okay, I think I know what’s wrong here, you first took the touch position in screen coordinates
      [0,0]->[screenWidth-1 ,screenHeight-1]
      then subtracted it from pixels1 which is in world map coordinates
      [0,0]->[(2^zoom)*tileSize-1, (2^zoom)*tileSize-1]

      You’re not supposed to mix things like this, here’s a piece of my code (ignore the code that handles long touch):

      @Override
      public boolean onTouchEvent(MotionEvent event)
      {
      	int action = event.getAction();
      
      	if (action == MotionEvent.ACTION_UP)
      	{
      		if (System.currentTimeMillis() - touchStart > 500)
      		{
      			// Touch position (screen coordinates space)
      			Point click = new Point();
      			click.x = (int) event.getX();
      			click.y = (int) event.getY();
      
      			if (click.equals(touchPos.x, touchPos.y))
      			{
      				// Getting screen center (screen coordinates space)
      				Point center = new Point(getWidth() / 2, getHeight() / 2);
      				Point diff = new Point(center.x - click.x, center.y - click.y);
      
      				// Center of screen in world map coordinates
      				Point centerGlobal = tilesManager.lonLatToPixelXY(seekLocation.x, seekLocation.y);
      
      				// Now just subtract the difference vector (World map coordinates)
      				centerGlobal.x -= diff.x;
      				centerGlobal.y -= diff.y;
      
      				// Get the right longitude, latitude values
      				PointD geoPoint = tilesManager.pixelXYToLatLong((int) centerGlobal.x, (int) centerGlobal.y);
      
      				refresh();
      			}
      
      			return true;
      		}
      	}
      
      	...
      }
      

      I hope it’s clear now, we just needed the distance from screen center to click position (screen coordinates space) ,then we subtracted this distance value from the centerGlobal (which is the center of the view in world map coordinates space), now we have the touch position in pixels, as if the user has the full world map in front of him, we just need to calculate the longitude, latitude for this position using pixelXYToLatLong.

      The drawing code should remain the same.
      I hope this helps, if it doesn’t please let me know.

      • Fuchs
        25/04/2012 at 6:00 am

        And sorry about the code formatting in comments :)…

      • lsat
        25/04/2012 at 6:56 pm

        That worked like a charm. Awesome. Thanks a lot. This gets the ground kicking for me. I now have to build a heat map to show intensity points. If you know of any good article out there let me know.

        • Fuchs
          25/04/2012 at 7:26 pm

          That’s good news, I’m not sure about the heat map since I never tried anything like that.
          By the way, I think you should have posted your question in the part where MapView is explained.
          Questions and comments really enrich the content of the post :).

          • lsat
            25/04/2012 at 11:13 pm

            My bad!! Point noted. will be careful next time 🙂

      • 31/08/2012 at 2:54 pm

        I put this one in the class”mapview” and placed it under the whole statement “else if (action == MotionEvent.ACTION_MOVE)”. And eclipse hinted me that I haven’t created the variable “touchStart” and “touchPos”. So I created them as fields there but there were errors poped out and it said x, y cannot be resolved or they are not filed.. That’s kinda odd for me.
        error in this line:if (click.equals(touchPos.x, touchPos.y))

        • Fuchs
          31/08/2012 at 5:33 pm

          touchPos is an instance of the class Point.

          • 01/09/2012 at 12:44 am

            then can you tell me how to fix that?

          • Fuchs
            01/09/2012 at 8:05 pm

            I modified the MapView class, here’s the new one: MapView CLICK MARKER.java, just make sure to rename it to MapView.java before using it.
            The changes are mainly in the onTouchEvent method, I also added a few lines at the beginning of the drawMarker method to draw a circle where the user long-touches the map.

            MapView.java Line 272: geoPoint = tileManager.pixelXYToLonLat(centerGlobal.x, centerGlobal.y);
            This is where we get the gps coordinates of the click location.
            And in line 205 we draw a circle if a click location is available.
            I also changed lastTouchPos from PointD to Point.

            It’s better for you if you understand the tutorial and coordinates conversion and implement the functionality you want on your own :).

          • 02/09/2012 at 1:07 am

            LOL no reply button for your last comment. Think I gotta do it here 😀
            Yes I noticed and checked through all the changes.
            As you can see I am obviously a noob to programming. And I know that I should have got the idea about how do we get these methods and why(I\\’m working on it now). But I really have never programmed before unitl my college life starts. (probably playing some pc game is the closest touch between me and programming 😉 ) So I guess I need some more communication(for programming) and hints than the others. And also, the hard working time for sure.
            I can understand the theory in your tutorial. But I meet problems when it comes to the code. It usually takes some more time to comprehend. But I will still keep on trying 🙂 viva la programmer 😀

          • Fuchs
            02/09/2012 at 8:05 am

            That’s because comments went too deep :D.
            This whole tutorial is meant to explain the main ideas, after that you can start your own app from scratch 😀 with your own app design :D.

  12. mk
    08/06/2012 at 9:34 am

    I ran the code onto eclipse.
    I put the db file in the proper place.
    But when running the apk, it gives me following exception. How do I resolve it ?

    I/Database( 3189): sqlite returned: error code = 8, msg = prepared statement aborts at 4: [DELETE FROM android_metadata]
    E/Database( 3189): DELETE failed setting locale
    E/Database( 3189): Failed to setLocale() when constructing, closing the database
    E/Database( 3189): android.database.sqlite.SQLiteException: attempt to write a readonly database
    E/Database( 3189): at android.database.sqlite.SQLiteDatabase.native_setLocale(Native Method)
    E/Database( 3189): at android.database.sqlite.SQLiteDatabase.setLocale(SQLiteDatabase.java:2113)
    E/Database( 3189): at android.database.sqlite.SQLiteDatabase.(SQLiteDatabase.java:1966)
    E/Database( 3189): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:887)
    E/Database( 3189): at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:965)
    E/Database( 3189): at com.mapapp.tileManagement.TilesProvider.(TilesProvider.java:30)
    E/Database( 3189): at com.mapapp.main.MapAppActivity.initViews(MapAppActivity.java:89)
    E/Database( 3189): at com.mapapp.main.MapAppActivity.onResume(MapAppActivity.java:65)

    • Fuchs
      08/06/2012 at 5:35 pm

      I wasn’t able to produce the exception on my device or on the emulator.

      So I’ve done some searching online and found that some people are having the same exceptions in their apps, The thing is that Android is trying to make a metadata table inside the database, it’s not supposed to fail since you have the right permissions!.

      Anyway let’s try opening the database in readonly mode, in the constructor of the class TilesProvider.java (Line 30) try to replace this line:
      tilesDB = SQLiteDatabase.openOrCreateDatabase(dbPath, null);
      with this one:
      tilesDB = SQLiteDatabase.openDatabase(dbPath, null, SQLiteDatabase.NO_LOCALIZED_COLLATORS | SQLiteDatabase.OPEN_READONLY);

      This will insure that the database will be opened without modification.
      Please let me know of the results.

  13. mk
    11/06/2012 at 9:49 am

    Thanks a lot . That worked wonders.
    Also I modified the code, which has “world.sqlitedb” file in assets folder and copies this db file into app data folder. Hence , the question of external storage doesn’t arise and hence device related permission and other problems. Works like a charm on any device.

    // for opening file from with the application i.e assets folder

    String path = null;
    try {
    	InputStream is = getApplicationContext().getAssets().open("world.sqlitedb");
    	path = copyDataBase();
    	} catch (IOException e) {
    		// TODO Auto-generated catch block
    		e.printStackTrace();
    	}
    
    private String copyDataBase() throws IOException {
    		try {
    
    			File dbPath = Environment.getDataDirectory();
    			String dbName = "world.sqlitedb";
    
    			InputStream input = getApplicationContext().getAssets()
    					.open(dbName);
    			outPutFileName = getApplicationContext().getFilesDir()
    					.getAbsolutePath() + "/" + dbName;
    
    			OutputStream output = new FileOutputStream(outPutFileName);
    
    			byte[] buffer = new byte[1024];
    			int length;
    			while ((length = input.read(buffer)) > 0) {
    				output.write(buffer, 0, length);
    			}
    			output.flush();
    			output.close();
    			input.close();
    		} catch (IOException e) {
    		}
    		return outPutFileName;
    	}
    

    The output file created by above code is in “outputfilename = /data/data/com.mapapp.mapapp/files/world.sqlitedb”

    • Fuchs
      11/06/2012 at 12:38 pm

      Great job :D.
      The main purpose of putting the database file on sdcard is because usually it’s a very large file to be put in the phone memory, just keep that in mind :).

  14. mk
    11/06/2012 at 9:53 am

    When clicked anywhere on the map, I wanted to show that country’s timezone. Or highlight all the areas on maps, which have the same timezone.Something similar to samsung clock app, letting you select worldclock with a map. How do I modify your code to do that ? All my attempts were unsuccessful.

    • Fuchs
      11/06/2012 at 1:23 pm

      If you need something like that you probably don’t need an app this complex, you just need a single world image and not a database with tiles and complex calculations like in this app.

      As in this link bellow, the world map is divided into latitude ranges that specify the timezone
      http://www.timeanddate.com/time/map/
      So you can do a simple mapping from click position to timezone

      Depending on the features you want in your app you can make things far more complex (like highlighting countries), but you’ll need another data structure.

      If you still want to use something complex like this app I’ll try to provide some explanation and code modifications.
      Sorry for the little info in this comment but my knowledge of timezones is limited :).

      • mk
        12/06/2012 at 10:45 am

        Thanks for the info.
        I had tried and imageview and mapping from click position to timezone, but it didn’t give accurate info, moreover even if we get the timezone, finding the specific cityname or country is difficult. And hence I thought I should use a real map, which will give me all world city names,zoom and highlight options.

        Could you please guide me over how do I implement the required feature in android, with a imageview or a actual offline map ?

        • Fuchs
          13/06/2012 at 5:53 pm

          About getting the city\country name using GPS coordinates: Reverse GeoCoding does that easily, you send the server the longitude\latitude and the server sends you the name and other info.
          I haven’t tried it myself but it shouldn’t be that hard, the hard part is to know that such a service exists 🙂

          Anyway, once you have the coordinates you’ll need an internet connection, here’s a server that does reverse geocoding:
          http://www.geonames.org/export/reverse-geocoding.html

          and here’s a sample link where you put the coordinates in the URL and receive data in xml format
          http://api.geonames.org/findNearbyPlaceName?lat=47.3&lng=9&username=demo
          I’m not sure about the servers usage policy or limits though.

          One problem solved I guess, so if your app doesn’t require zooming much on the map it’s better to have a single image instead of database and tiles management.

          You just need a map that uses Mercator projection and when the user clicks you calculate the ratio for both x & y
          RatioXY

          float x=clickPosition.x/image.width;
          float y=clickPosition.y/image.height;

          Then you use this function:

          public PointD ratioXYToLonLat(float x, float y)
          {
          	double latitude = 90.0 - 360.0 * Math.atan(Math.exp(-y * 2.0 * Math.PI)) / Math.PI;
          	double longitude = 360.0 * x;
          
          	return new PointD(longitude, latitude);
          }
          

          PointD is a simple class with two double values.
          I hope this helps, Sorry for not providing more info but it’s college exams week 😦

  15. Niraj
    18/07/2012 at 10:59 am

    Hi All,
    I have created app for displaying offline map by using this tutorial but i am getting error
    “Unable to open database file ” .
    Please help me.

    Thanx in advanced

    • Fuchs
      20/07/2012 at 8:16 pm

      Sorry for the delay, Did you downloaded the sample or started building from scratch?
      It would really help if you attach the LogCat which contains the detailed exception.

  16. pewdur
    07/08/2012 at 6:07 pm

    we have to build it from scratch? Any other tools allowed? I am a noob and I am also trying to build an offline map too. So I am studying on this sample. However I got plenties of errors when i tried to run it in my eclipse indigo.
    these are the error messages from Logcat, hope you can have some time to check it out!

    08-07 15:21:45.494: D/AndroidRuntime(5135): Shutting down VM
    08-07 15:21:45.494: W/dalvikvm(5135): threadid=1: thread exiting with uncaught exception (group=0xb403a180)
    08-07 15:21:45.534: E/AndroidRuntime(5135): FATAL EXCEPTION: main
    08-07 15:21:45.534: E/AndroidRuntime(5135): java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.mapapp.main/com.mapapp.MapAppActivity}: java.lang.ClassNotFoundException: com.mapapp.MapAppActivity
    08-07 15:21:45.534: E/AndroidRuntime(5135): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1880)
    08-07 15:21:45.534: E/AndroidRuntime(5135): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1981)
    08-07 15:21:45.534: E/AndroidRuntime(5135): at android.app.ActivityThread.access$600(ActivityThread.java:123)
    08-07 15:21:45.534: E/AndroidRuntime(5135): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147)
    08-07 15:21:45.534: E/AndroidRuntime(5135): at android.os.Handler.dispatchMessage(Handler.java:99)
    08-07 15:21:45.534: E/AndroidRuntime(5135): at android.os.Looper.loop(Looper.java:137)
    08-07 15:21:45.534: E/AndroidRuntime(5135): at android.app.ActivityThread.main(ActivityThread.java:4424)
    08-07 15:21:45.534: E/AndroidRuntime(5135): at java.lang.reflect.Method.invokeNative(Native Method)
    08-07 15:21:45.534: E/AndroidRuntime(5135): at java.lang.reflect.Method.invoke(Method.java:511)
    08-07 15:21:45.534: E/AndroidRuntime(5135): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
    08-07 15:21:45.534: E/AndroidRuntime(5135): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
    08-07 15:21:45.534: E/AndroidRuntime(5135): at dalvik.system.NativeStart.main(Native Method)
    08-07 15:21:45.534: E/AndroidRuntime(5135): Caused by: java.lang.ClassNotFoundException: com.mapapp.MapAppActivity
    08-07 15:21:45.534: E/AndroidRuntime(5135): at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:61)
    08-07 15:21:45.534: E/AndroidRuntime(5135): at java.lang.ClassLoader.loadClass(ClassLoader.java:501)
    08-07 15:21:45.534: E/AndroidRuntime(5135): at java.lang.ClassLoader.loadClass(ClassLoader.java:461)
    08-07 15:21:45.534: E/AndroidRuntime(5135): at android.app.Instrumentation.newActivity(Instrumentation.java:1023)
    08-07 15:21:45.534: E/AndroidRuntime(5135): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1871)
    08-07 15:21:45.534: E/AndroidRuntime(5135): … 11 more

    • Fuchs
      09/08/2012 at 1:49 am

      That’s strange! This exception usually means one of two things:
      Either the activity MapAppActivity is not declared in AndroidManifest.xml or the activity class is marked as abstract.
      The code worked fine with me as well with other people without any modifications, which android version are you trying the app on?

      If you just want to build a maps app without Google API and you don’t want to mess with the details you probably should find a library that provides you with the necessary tools other than implementing them yourself.

      My implementation isn’t prefect, it’s just meant to explain the basics in case some one wants to save some time, that’s because once you understand the basics you can do your own implementation from scratch.

      I’ll search for libraries and post anything I find as soon as I can.

    • Fuchs
      • pewdur
        09/08/2012 at 9:16 pm

        Oh I just found my mistake. I declared the android name activity in the manifest as “com.mapapp.MapAppActivity”(with the package’s name). So guess that is the reason why android cannot find it. Now I removed the package’s name before the activity and it works! 😀
        So now I am able to see a little world map on my emulator screen and I can even drag it somewhere. The only problem is I just cannot see the location marker there.
        I am using the newest android 4.1 and the api lvl 16. There is one interesting thing is that it seems like I should set up my SDK version higher than 7? However I thought this tutorial was quite some time ago so I set my SDK version as 5. Oddly it still worked now.
        I really don’t intend to mess with the details because I heard it will just take quite some repeated work in implementing the map by myself.
        BTW i think your code is perfect for a beginner who starts to learn something 🙂 Especially you have comments there and it really helps me to understand. Thanks!

        • Fuchs
          10/08/2012 at 2:15 am

          I’m really happy it worked :D, as I wrote in the instructions you zoom in\out using the volume keys (Ctrl+F5/F6 on the emulator).
          About the marker it will only appear when there’s a gps fix available, you can press the Menu key to make a fake one just for testing :D.

          About the API levels, as it says here the Android API10 has about 60% of the market, and my mobile phone is also API level 10, so I tried to choose the lowest SDK version to make sure the app runs on most devices, and since I’m only using basic functions like Canvas.draw it should work on lower API levels as well. Thanks to backward compatibility it will run just fine on any Android device with higher API level :D.

          Thanks for your compliment about the code :D, If you have any questions I’m here to help ;).

  17. maoyi
    16/08/2012 at 8:42 pm

    Hey Fuchs!
    Now I am just trying to replace your map file “world.sqlitedb” with my own one.
    I generated it as the exactly same steps you mentioned above however I got quite some errors..
    The only difference between mine and yours is that I started the map level at 14 and I just selected 14 15 16 these three zoom levels to save. I dont really think this would matter though…
    Here is the logcat(quite a lot, hope you have the patience :D):

    08-16 17:44:50.317: I/dalvikvm(12343): threadid=3: reacting to signal 3
    08-16 17:44:50.416: I/dalvikvm(12343): Wrote stack traces to ‘/data/anr/traces.txt’
    08-16 17:44:50.436: I/SqliteDatabaseCpp(12343): sqlite returned: error code = 8, msg = statement aborts at 4: [DELETE FROM android_metadata] attempt to write a readonly database, db=/mnt/sdcard/mapapp/Custom lindholmen.sqlitedb
    08-16 17:44:50.436: E/SqliteDatabaseCpp(12343): DELETE failed setting locale
    08-16 17:44:50.467: E/SQLiteDatabase(12343): Failed to open the database. closing it.
    08-16 17:44:50.467: E/SQLiteDatabase(12343): android.database.sqlite.SQLiteReadOnlyDatabaseException: attempt to write a readonly database
    08-16 17:44:50.467: E/SQLiteDatabase(12343): at android.database.sqlite.SQLiteDatabase.native_setLocale(Native Method)
    08-16 17:44:50.467: E/SQLiteDatabase(12343): at android.database.sqlite.SQLiteDatabase.setLocale(SQLiteDatabase.java:2074)
    08-16 17:44:50.467: E/SQLiteDatabase(12343): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:1014)
    08-16 17:44:50.467: E/SQLiteDatabase(12343): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:986)
    08-16 17:44:50.467: E/SQLiteDatabase(12343): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:962)
    08-16 17:44:50.467: E/SQLiteDatabase(12343): at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:1043)
    08-16 17:44:50.467: E/SQLiteDatabase(12343): at com.mapapp.tileManagement.TilesProvider.(TilesProvider.java:30)
    08-16 17:44:50.467: E/SQLiteDatabase(12343): at com.mapapp.main.MapAppActivity.initViews(MapAppActivity.java:89)
    08-16 17:44:50.467: E/SQLiteDatabase(12343): at com.mapapp.main.MapAppActivity.onResume(MapAppActivity.java:65)
    08-16 17:44:50.467: E/SQLiteDatabase(12343): at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1154)
    08-16 17:44:50.467: E/SQLiteDatabase(12343): at android.app.Activity.performResume(Activity.java:4539)
    08-16 17:44:50.467: E/SQLiteDatabase(12343): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2434)
    08-16 17:44:50.467: E/SQLiteDatabase(12343): at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2472)
    08-16 17:44:50.467: E/SQLiteDatabase(12343): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1986)
    08-16 17:44:50.467: E/SQLiteDatabase(12343): at android.app.ActivityThread.access$600(ActivityThread.java:123)
    08-16 17:44:50.467: E/SQLiteDatabase(12343): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147)
    08-16 17:44:50.467: E/SQLiteDatabase(12343): at android.os.Handler.dispatchMessage(Handler.java:99)
    08-16 17:44:50.467: E/SQLiteDatabase(12343): at android.os.Looper.loop(Looper.java:137)
    08-16 17:44:50.467: E/SQLiteDatabase(12343): at android.app.ActivityThread.main(ActivityThread.java:4424)
    08-16 17:44:50.467: E/SQLiteDatabase(12343): at java.lang.reflect.Method.invokeNative(Native Method)
    08-16 17:44:50.467: E/SQLiteDatabase(12343): at java.lang.reflect.Method.invoke(Method.java:511)
    08-16 17:44:50.467: E/SQLiteDatabase(12343): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
    08-16 17:44:50.467: E/SQLiteDatabase(12343): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
    08-16 17:44:50.467: E/SQLiteDatabase(12343): at dalvik.system.NativeStart.main(Native Method)
    08-16 17:44:50.497: D/AndroidRuntime(12343): Shutting down VM
    08-16 17:44:50.497: W/dalvikvm(12343): threadid=1: thread exiting with uncaught exception (group=0xb4167180)
    08-16 17:44:50.537: E/AndroidRuntime(12343): FATAL EXCEPTION: main
    08-16 17:44:50.537: E/AndroidRuntime(12343): java.lang.RuntimeException: Unable to resume activity {com.mapapp.main/com.mapapp.main.MapAppActivity}: android.database.sqlite.SQLiteReadOnlyDatabaseException: attempt to write a readonly database
    08-16 17:44:50.537: E/AndroidRuntime(12343): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2444)
    08-16 17:44:50.537: E/AndroidRuntime(12343): at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2472)
    08-16 17:44:50.537: E/AndroidRuntime(12343): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1986)
    08-16 17:44:50.537: E/AndroidRuntime(12343): at android.app.ActivityThread.access$600(ActivityThread.java:123)
    08-16 17:44:50.537: E/AndroidRuntime(12343): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147)
    08-16 17:44:50.537: E/AndroidRuntime(12343): at android.os.Handler.dispatchMessage(Handler.java:99)
    08-16 17:44:50.537: E/AndroidRuntime(12343): at android.os.Looper.loop(Looper.java:137)
    08-16 17:44:50.537: E/AndroidRuntime(12343): at android.app.ActivityThread.main(ActivityThread.java:4424)
    08-16 17:44:50.537: E/AndroidRuntime(12343): at java.lang.reflect.Method.invokeNative(Native Method)
    08-16 17:44:50.537: E/AndroidRuntime(12343): at java.lang.reflect.Method.invoke(Method.java:511)
    08-16 17:44:50.537: E/AndroidRuntime(12343): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
    08-16 17:44:50.537: E/AndroidRuntime(12343): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
    08-16 17:44:50.537: E/AndroidRuntime(12343): at dalvik.system.NativeStart.main(Native Method)
    08-16 17:44:50.537: E/AndroidRuntime(12343): Caused by: android.database.sqlite.SQLiteReadOnlyDatabaseException: attempt to write a readonly database
    08-16 17:44:50.537: E/AndroidRuntime(12343): at android.database.sqlite.SQLiteDatabase.native_setLocale(Native Method)
    08-16 17:44:50.537: E/AndroidRuntime(12343): at android.database.sqlite.SQLiteDatabase.setLocale(SQLiteDatabase.java:2074)
    08-16 17:44:50.537: E/AndroidRuntime(12343): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:1014)
    08-16 17:44:50.537: E/AndroidRuntime(12343): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:986)
    08-16 17:44:50.537: E/AndroidRuntime(12343): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:962)
    08-16 17:44:50.537: E/AndroidRuntime(12343): at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:1043)
    08-16 17:44:50.537: E/AndroidRuntime(12343): at com.mapapp.tileManagement.TilesProvider.(TilesProvider.java:30)
    08-16 17:44:50.537: E/AndroidRuntime(12343): at com.mapapp.main.MapAppActivity.initViews(MapAppActivity.java:89)
    08-16 17:44:50.537: E/AndroidRuntime(12343): at com.mapapp.main.MapAppActivity.onResume(MapAppActivity.java:65)
    08-16 17:44:50.537: E/AndroidRuntime(12343): at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1154)
    08-16 17:44:50.537: E/AndroidRuntime(12343): at android.app.Activity.performResume(Activity.java:4539)
    08-16 17:44:50.537: E/AndroidRuntime(12343): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2434)
    08-16 17:44:50.537: E/AndroidRuntime(12343): … 12 more

    Well, I think mainly what’s going on there is that it says the db file I am using is read-only so the application could not get the access to the file. But I am positive about file is not read-only.
    Also on google they said we should use the syntax: ” Environment.getExternalStorageDirectory() ” but I think that is exactly what we are using there. So I just got confused and had no idea what is going wrong there..

    • Fuchs
      16/08/2012 at 10:05 pm

      I think this will help: link
      If it doesn’t please tell me, and thank you for posting the LogCat 😉

      • maoyi
        17/08/2012 at 6:47 pm

        Oops, what an omission there! 😀
        Yeah I did that and it seems okay now. But the new map is not showing. There is just a whole bunch of grey area displaying in the emulator. And nothing happens also if I click anywhere on it.
        So I am wonderring if it is because I started with the level 14 instead of level 1 when I was generating the map file? I tried to change the current zoom level into 14 in line 43 of the class “tilesManager” but it did not work…
        Or should I change the latitude or longitude or something?

        • Fuchs
          17/08/2012 at 8:30 pm

          One problem down :D! I really think I should modify the line that opens the database :D!.

          What I know about Mobile Atlas Creator is that it will download at least one tile from all the lower zoom levels, anyway, here’s what you can do:
          1) Don’t change the zoom level in the TilesManager, because after it’s created the zoom level is set again from the app preferences. The TilesManager is created in the MapView constructor then the zoom level gets changed in MapAppActivity.restoreMapViewSettings
          So try zooming in manually until you see something, on the emulator use the keys Ctrl+F5/F6 as volume buttons.
          2) If the database you’re using is small and easy for you to email me please send it and I’ll check it out, if it’s not small you can create a smaller version by choosing lesser tiles in Mobile Atlas Creator at the same zoom levels.

          • maoyi
            18/08/2012 at 5:32 pm

            lol, look how noob I am! 😀
            yes I tried to zoom level manually and it looked like something was changed when I zoomed in or out but there is still no map.
            Ok I think that will be good. The size of the db file is less than 1mb so if you think it is okay I will e-mail you.

          • Fuchs
            18/08/2012 at 7:19 pm

            The thing is that the app is just for tutorial purposes and it’s not a product :D, that’s why there’s no user interface other than the map :D.
            1MB is definitely fine :).

  18. maoyi
    18/08/2012 at 10:13 pm

    Yes I know that. And I think I am gonna add some interface on it! 😉
    so can I have your e-mail address then I can send you the file 🙂

    • Fuchs
      19/08/2012 at 12:29 pm

      Of course you can have it :D, it’s in the about page, here it is : ghoshehsoft@live.com :).

      • maoyi
        21/08/2012 at 9:18 pm

        e-mail has been sent, hope u got that 😀

        • Fuchs
          22/08/2012 at 9:42 am

          Okay I’ve checked the database and it looks that Mobile Atlas Creator didn’t automatically download the lower map levels, just check them yourself, from 0 to 13, the additional tiles size won’t be significant when compared to the ones you actually want (13,14,15). just download them to guide you when zooming.
          If you have a gps fix just press the Focus key and the marker will be brought to the center of the screen, just make sure you have the tiles at your zoom level.

          • maoyi
            22/08/2012 at 6:28 pm

            oh, yes. The tiles! How could I miss that?
            I think maybe it is because I created too less map tiles there. (coz I thought I just need the last zoom level so I just select less than 100 tiles at the last zoom level. No wander the Atlas generates the map file so fast.. 🙂
            However I think even though I dont have too many tiles on zoom level 13, 14, the application should still show something at zoom level 15, isn’t it?
            There may be nothing when I started the application, but the map should be seen after I click the Volume up button 15 times?
            Anyway now I created a new Atlas file with more tiles in it and somehow I get the desired map view finally! 😀
            And yes I have a GPS signal receiver but can you hint me where is the Focus Key?

          • Fuchs
            23/08/2012 at 3:57 am

            When you zoom with the map centered you’ll be zooming to the equator and you don’t have tiles there, to see tiles you have to drag the map (that’s not there) to make the tiles you have at the center of the screen!
            About the Focus key, it’s the same as the camera button but you have to press it slightly not fully, 2 buttons in 1 :D.

  19. maoyi
    23/08/2012 at 2:16 pm

    yep. So it is like the application actually shows the whole map still. The reason why I can’t see the center of the map is I do not have the tiles in that specific area?
    oh 2 buttons in 1, sounds tricky! 😀
    And I pressed the camera button, gentlely and strongly as well 😉 but it seems like there is nothing changed.
    Simply nothing showed on the map, but I think my gps receiver works fine.
    I am wonderring if I can change the “show my location” button to another one on the emulator? Coz the camera button seems not work there, you know I put my mouse upon any other button e.g volume up/down, the color of that button will turn to a bit darker and if I click on it. There is a sound.
    But nothing happens on the camera button…sorry for so manuy questions, I am a noob 🙂

    • Fuchs
      23/08/2012 at 2:25 pm

      Now I remember :D, the key “H” also should work for centering the location marker on screen! just make sure you have a GPS fix, you can tell by the satellite animation in the notifications bar, as long as the animation is running it means a gps fix isn’t yet available, when the animation stops try and press the “H” button or the Focus button.

      Unfortunately you won’t get a gps fix on the emulator!

      • maoyi
        23/08/2012 at 2:56 pm

        Oh, so what you are saying there is basiclally I cannot get a gps fix on the emulator coz there is always no signal on the emulator that is running by eclipse?
        So maybe I can put the app on an android cellphone and then try it out?

        • Fuchs
          23/08/2012 at 3:02 pm

          The emulator obviously doesn’t have gps device, but you can still emulate a gps, fix, this might be useful.

  20. maoyi
    23/08/2012 at 3:24 pm

    Yeah it explains how to emulate a gps fix.
    But can I get my gps location from a plug-in device(or somewhere else, but just my real current location) and keeps refreshing the new location maybe in every 20 seconds?
    I want to show my current location on the map (getting from a plug-in device or from the cellphone’s location service maybe?), and it will move when I move. Basically like tracking my real location. Is it possible in Android?

  21. maoyi
    23/08/2012 at 6:31 pm

    I found this might be helpful for me.
    http://stackoverflow.com/questions/5988681/i-want-to-use-gps-but-my-code-uses-wifi-why/5988838
    But it is actually in Java class, and I am not sure if they can be combined together?

    • Fuchs
      24/08/2012 at 8:12 am

      Did you check tutorial part6? it automatically downloads the missing tiles from the internet.
      About the gps fix issue, did the satellite animation stop?

      • maoyi
        24/08/2012 at 2:35 pm

        no, it didnt stop no matter how long I wait…. I am wonderring can I manully stop the satellite animation…?

        • Fuchs
          24/08/2012 at 2:47 pm

          We only care about the animation because when it stops it means that we have a gps fix and the device knows its location, getting a gps fix indoors really takes time (it might not even work), it took me about 25 minutes in my house near the window :P.
          So you might want to test the app outdoors!

          • maoyi
            24/08/2012 at 11:52 pm

            Yeah I have tried an afternoon with a plug-in gps device to get my current location showed up but unfortunately I did not get anything.. Can you just tell me some more details about how to check the animation? 🙂
            Is it on the emulator?
            I used to check the status from my GPS device(the light on that device will blink when it gets coordiantes from the satellite), But I was still not able to click the “Center/Camera” button or “H” on the emulator keyboard…. It drives me crazy

          • Fuchs
            25/08/2012 at 9:10 am

            I’m not sure how the plug-in gps device works!, here’s how the gps animation on the mobile looks like:
            Gps fix animation
            (Click on image to view original size)

            As long as it’s animated it means no gps fix available.
            Did you try your gps device on the official Maps app? if it worked there it has to work here!.
            Try zooming out as much as you can, maybe the marker is there but you can’t see it!.

  22. 28/08/2012 at 6:32 pm

    yes the gps device works fine there. Now I just figured maybe I can test it on an android cellphone. But I need to change the path to find the db file on a local place in the cellphone instead of the sd card. I guess the change will be made in this syntax
    “String path = Environment.getExternalStorageDirectory() + “/mapapp/123.sqlitedb”

    • 28/08/2012 at 11:45 pm

      Today I got the location on the cellphone and I think I did not click any buttons and that current location just poped out itself, cool stuff.
      the searching process about how to run this app on a cellphone is really really time-suming though:D

      • Fuchs
        29/08/2012 at 7:20 pm

        Good :D, the tutorial here is meant to be tested on a real physical phone not an emulator :).
        About not pressing any keys: the marker will be visible automatically, you press the Focus\H button only to center your position in screen if it’s not visible :).

        • 30/08/2012 at 12:50 am

          oh that is it! But too bad my Nexus only has the volume up/down and the power button. So I guess I will just do dragging all the time 😉
          And btw, I kinda want to add a marker which will show up on the map whenever I click my mouse on it. Do you have any ideas about thow to do that? 🙂

          • Fuchs
            30/08/2012 at 9:49 am

            You can add a Button or an ImageView on that does the job of the Focus key :).
            About touching the map check these comments here.

  23. gonesail
    30/08/2012 at 2:06 am

    thanks for posting the application. i was wondering if you had some guidelines on creating the map database? thanks.

    • Fuchs
      30/08/2012 at 9:38 am

      You can use Mobile Atlas Creator and export the map in RMaps format, you can also find tutorials there.

      • gonesail
        30/08/2012 at 11:43 pm

        thanks. i am trying to run this thing and looks like it cannot open the database. here is what the log is showing. i know the file is on the sd card.

        SqliteDatabaseCpp(4515): sqlite3_open_v2(“/mnt/sdcard/mapapp/world.sqlitedb”, &handle, 1, NULL) failed
        SQLiteDatabase(4515): Failed to open the database. closing it.
        SQLiteDatabase(4515): android.database.sqlite.SQLiteCantOpenDatabaseException: unable to open database file
        SQLiteDatabase(4515): at android.database.sqlite.SQLiteDatabase.dbopen(Native Method)
        SQLiteDatabase(4515): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:1048)
        SQLiteDatabase(4515): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:1001)
        SQLiteDatabase(4515): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:962)

        • Fuchs
          31/08/2012 at 5:43 pm

          I don’t know why this is happening!
          -What Android version are you trying the app on?
          -Is this database the same one I provided?
          -Are you trying it on an emulator or a real device?

  24. 16/09/2012 at 7:40 am

    hi where can i download my own city’s map in sqlitedb format ??
    tnx

  25. 18/09/2012 at 8:34 am

    hi again 😀
    how can i add zoom in button on map ?
    tnx

    • Fuchs
      18/09/2012 at 7:34 pm

      In MapAppActivity.java, onResume(), you need to create a new FrameLayout, add the map view to it then add the buttons you want to it.
      Something like this:

      @Override
      protected void onResume()
      {
      	// Create MapView
      	initViews();
      
      	// Restore zoom and location data for the MapView
      	restoreMapViewSettings();
      
      	// Creating and registering the location listener
      	locationListener = new MapViewLocationListener(mapView);
      	LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
      	locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
      
      	FrameLayout frm = new FrameLayout(this);
      
      	Button b1 = (Button) findViewById(R.id.btnZoomin);
      	Button b2 = (Button) findViewById(R.id.btnZoomout);
      
      	b1.setOnClickListener(new View.OnClickListener()
      	{
      		@Override
      		public void onClick(View v)
      		{
      			mapView.zoomIn();
      		}
      	});
      
      	b2.setOnClickListener(new View.OnClickListener()
      	{
      		@Override
      		public void onClick(View v)
      		{
      			mapView.zoomOut();
      		}
      	});
      
      	frm.addView(mapView);
      	frm.addView(b1);
      	frm.addView(b2);
      
      	setContentView(frm);
      
      	// Never ever forget this 🙂
      	super.onResume();
      }
      

      You just need to define the buttons in the layout xml file.

  26. migen
    07/02/2013 at 9:11 am

    Hi fuchs, we’re still students trying to learn android programming. we found your tutorial very helpful for our project yet we have some questions. How can we export or use openstreetmap and incorporate it with the world.sqlitedb that was given from this project.

  27. 19/02/2013 at 1:12 pm

    Hi again Fuchs
    we are able to use your codes, thank you so much. we’re moving forward on this android project now and yet we would still like to ask you some question, if that is okay.

    we’re currently making an app that may track dogs. the gsm attached/ device attached to the animal will send an sms to the android app and able to interpret the sms’s information as longitude and latitude and pin point it to the map as the device location. the device is already ready to be used and we are slowly trying to work it out with the android app but somehow we’re a bit lost. can you recommend us some example codes or anything alike that we may study to understand how it should work? we’re so grateful to read your reply.

  28. 19/02/2013 at 2:11 pm

    Hi again Fushs 🙂 LOL sorry for interrupting you again.

    we figured out already the gps codes 🙂 hweew.! we would like to add new spinner, buttons and edittext, but doesn’t have an idea how we’re suppose to do it.

    we’re used to create layout using xml and we’re amazed how you did your layout (hard coded).. 🙂

    • Fuchs
      20/02/2013 at 5:20 am

      Hi, I used the hard coding approach since I only had one view in the activity.
      There’s a simple way to achieve what you want, you first create your views using the usual XML approach but with one important note : make the most top view (parent of all other views) have the type of RelativeLayout, then in the activity code you create the MapView and add it as a child view to the RelativeLayout.
      Here’s an example code:

      res/layout/main.xml

      <?xml version="1.0" encoding="utf-8"?>
      <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:id="@+id/frame"
          android:layout_width="fill_parent"
          android:layout_height="fill_parent" >
      
          <ZoomControls
              android:id="@+id/zoom"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:layout_alignParentBottom="true"
              android:layout_alignParentLeft="true" />
      
          <ImageView
              android:id="@+id/imgSat"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:layout_alignParentRight="true"
              android:layout_alignParentTop="true" />
      </RelativeLayout>
      
      @Override
      protected void onResume()
      {
      	setContentView(R.layout.main);
      	mapView = new MapView(...
      	
      	// Add mapView as the first child, other views will be rendered after rendering the map
      	((RelativeLayout) findViewById(R.id.frame)).addView(mapView, 0);
      }
      

      Please let me know of the results.

  29. 22/02/2013 at 3:31 pm

    Hi fuchs. I’m the partner of bunnywants. As said earlier, we’re working on this offline dog tracker. I just wanna ask, what should I put exactly at this code? — mapView = new MapView(… — the dot dot dot thing? We’re having a hard time figuring it. Hoping for your reply. 🙂

    • Fuchs
      22/02/2013 at 10:24 pm

      I just meant creating the mapView using the constructor, just like explained in the tutorials and in the code :).
      The main idea was to create the views you want using XML and after that adding the mapView to the RelativeLayout containing your layout.

  30. 22/02/2013 at 3:37 pm

    The app crashes when we install it to the phone. 😦

    • Fuchs
      22/02/2013 at 10:26 pm

      Did you create a folder called mapapp on the sdcard and put the file World.sqlite in it?
      You can debug the code and see what’s casing the crash in the LogCat.

  31. 22/02/2013 at 4:32 pm

    Or I have this idea. I saw your canvas.drawtext code in the MapView java. Maybe that’s a good idea to write other texts aside from just the long and lat infos? I figured out that you have to make another class for it? Can you please teach us how to do it? Is it possible also that we can do the same thing for text fields, button and spinner? If not, then maybe you could teach us more bout the xml file you sent us earlier.

    Sorry for asking a lot of questions. Really, we’re newbies in the android programming field. Hope you understand. 🙂

    • Fuchs
      22/02/2013 at 11:11 pm

      For displaying texts over the map I think it’s better to just use the canvas drawing methods, for other stuff like buttons and spinners creating them from scratch is a little troubling,
      use the xml layout method, I’ll give you an example on how to add ZoomControls to the map:

      Create the following xml file res\layout\main.xml

      <?xml version="1.0" encoding="utf-8"?>
      <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:id="@+id/frame"
          android:layout_width="fill_parent"
          android:layout_height="fill_parent" >
      
          <!-- after creating this view, our mapView will be added here at position 0 -->
          <!-- Check MapAppActivity.onResume method -->
      
          <ZoomControls
              android:id="@+id/zoom"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:layout_alignParentBottom="true"
              android:layout_alignParentLeft="true" />
      </RelativeLayout>
      

      after that you just need to change the method MapAppActivity.onResume like the following:

      @Override
      protected void onResume()
      {
      	// Create MapView
      	initViews();
      
      	// Restore zoom and location data for the MapView
      	restoreMapViewSettings();
      
      	// Creating and registering the location listener
      	locationListener = new MapViewLocationListener(mapView);
      	LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
      	locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
      
      	// Create out view from XML file : re\layout\main.xml
      	setContentView(R.layout.main);
      		
      	// Get the RelativeLayout which is parent of all other views
      	RelativeLayout frame = (RelativeLayout) findViewById(R.id.frame);
      		
      	// Add the mapView at position 0 which means it'll be the first view to get rendered.
      	frame.addView(mapView, 0);
      
      	// Add events to the zoom controls
      	ZoomControls zoomControls = (ZoomControls) findViewById(R.id.zoom);
      	zoomControls.setOnZoomInClickListener(new OnClickListener()
      	{
      		@Override
      		public void onClick(View v)
      		{
      			mapView.zoomIn();
      		}
      	});
      	zoomControls.setOnZoomOutClickListener(new OnClickListener()
      	{
      		@Override
      		public void onClick(View v)
      		{
      			mapView.zoomOut();
      		}
      	});
      
      	// Never ever forget this 🙂
      	super.onResume();
      }
      

      In the java code above we created the mapView using the method initViews,
      we called setContentView(R.layout.main); to create the layout defined in xml
      finally we called frame.addView(mapView, 0); to insert the mapView to the RelativeLayout we defined in xml.
      So now we have a RelativeLayout that contains a MapView and ZoomControls.

      So if you compile and run you’ll get your usual mapView and a zoom control in the left-bottom corner.
      I know I should have provided a method to create the mapView in xml too, but I never tried that, not yet at least.
      Let me know if this works for you.

      • 23/02/2013 at 10:10 am

        THANK YOU SO MUCH! IT WORKED! now i can add spinners and buttons and text fields! we can finally proceed with our gsm step. THANK YOU SO MUCH again! and thanks for the zoom controls too. 🙂

        • Fuchs
          23/02/2013 at 5:35 pm

          Glad to help :).

  32. 02/03/2013 at 5:24 pm

    Hello fusch. I have a question again. I’m trying to add a function to a spinner and a button. I want the spinner to get contacts from my phone book and the button to locate the dog in our tracker. I just want to know how to do this? Where to put exactly in your MapAppActivity codes? I tried to make one but it doesnt work. The map disappears and the spinners and button do not do their function. Can you please show me the codes for the spinners? I’ll try making for the locate button. I will have your spinner codes as the guide. Thanks. 🙂

    • Fuchs
      03/03/2013 at 2:28 am

      What exactly didn’t work?
      Adding any other control should work fine just like the ZoomControls in the comment #95 above!

      You can also check the tutorial I wrote a few days ago: MapApp7 : Creating MapView in XML

      The tutorial shows how to create your views in xml the usual way and how to add functionality to the ZoomControls, you can do the same to any other controls you want 🙂 .

  33. 03/03/2013 at 10:13 am

    I have this button wherein if pressed, it will display another layout. But when i press it, the app crashes. I don’t know why that happens.

    • Fuchs
      04/03/2013 at 5:34 am

      You won’t know unless you check your LogCat and see what exception is produced 😉 .

  34. 03/03/2013 at 10:15 am

    Or maybe you could teach me how to get contacts from the phonebook and put in on a spinner? That would be a great help. 🙂

  35. 04/03/2013 at 10:44 am

    Hey there fuchs. We already modified our project. There are two text fields which the user will input the longitude and latitude he desires. And there’s the button which of course when pressed, will locate the entered values and the marker will go there at the same time. Could you help us with that? I already have ideas but I’m just not sure where exactly to put the codes in the main mapapp class. Thank you so much. 🙂

  36. 04/03/2013 at 11:10 am

    DIsregard my earlier comment. Sorry. 🙂 What we’re trying to do now is the user will input the longitude and latitude in one text field separated by commas. The button will still locate the entered values and the marker should follow as well. We’re trying to do the StringTokenize approach for it with a comma delimiter. I hope you can help us with this. 🙂

    • Fuchs
      04/03/2013 at 12:22 pm

      you can simply use String.split, something like this:

      String str = txtLocation.getText().toString();
      String[] vals = str.split(",");
      double lon = Double.parseDouble(vals[0]);
      double lat = Double.parseDouble(vals[1]);
      mapView.setGpsLocation(lon, lat, 0, 1);
      

      where txtLocation is the EditText the user inputs the location to, mapView.setGpsLocation will change the position of the marker displayed on the map, the first two parameters are straight forward, the third one is the altitude and you don’t care about it right now, the forth one is the accuracy and it’s okay to just pass 1
      you might also want to call mapView.setSeekLocation which centers the map to the given gps coordinates.

      I made the code above as simple as possible, you might want to check if the provided string is valid and it can be parsed as two doubles.

      And by the way, It’s okay with me to answer any of your questions using my email, especially when the question isn’t directly connected to the tutorial here :).

  37. shashank
    11/03/2013 at 11:00 am

    when i am trying to play the app in eclipse its give unfortunately, the map has stoped.
    plz solve this problem

    • Fuchs
      11/03/2013 at 1:46 pm

      Make sure you create a folder called mapapp on your sdcard and put the database file provided above in it.
      It also helps to check the error on LogCat, post it here and I’ll see what’s wrong.

  38. shashank
    11/03/2013 at 2:56 pm

    thanks for your response
    when i am running this app on eclipse, then we get this type of error

    03-11 12:52:58.281: E/SQLiteLog(821): (14) cannot open file at line 30176 of [00bb9c9ce4]
    03-11 12:52:58.281: E/SQLiteLog(821): (14) os_unix.c:30176: (2) open(/mnt/sdcard/mapapp/world.sqlitedb) –
    03-11 12:52:58.361: E/SQLiteDatabase(821): Failed to open database ‘/mnt/sdcard/mapapp/world.sqlitedb’.
    03-11 12:52:58.361: E/SQLiteDatabase(821): android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
    03-11 12:52:58.361: E/SQLiteDatabase(821): at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
    03-11 12:52:58.361: E/SQLiteDatabase(821): at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:209)
    03-11 12:52:58.361: E/SQLiteDatabase(821): at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193)
    03-11 12:52:58.361: E/SQLiteDatabase(821): at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463)
    03-11 12:52:58.361: E/SQLiteDatabase(821): at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185)
    03-11 12:52:58.361: E/SQLiteDatabase(821): at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177)
    03-11 12:52:58.361: E/SQLiteDatabase(821): at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:804)
    03-11 12:52:58.361: E/SQLiteDatabase(821): at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:789)
    03-11 12:52:58.361: E/SQLiteDatabase(821): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694)
    03-11 12:52:58.361: E/SQLiteDatabase(821): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:669)
    03-11 12:52:58.361: E/SQLiteDatabase(821): at com.mapapp.tileManagement.TilesProvider.(TilesProvider.java:19)
    03-11 12:52:58.361: E/SQLiteDatabase(821): at com.mapapp.main.MapAppActivity.initViews(MapAppActivity.java:67)
    03-11 12:52:58.361: E/SQLiteDatabase(821): at com.mapapp.main.MapAppActivity.onResume(MapAppActivity.java:49)
    03-11 12:52:58.361: E/SQLiteDatabase(821): at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1185)
    03-11 12:52:58.361: E/SQLiteDatabase(821): at android.app.Activity.performResume(Activity.java:5182)
    03-11 12:52:58.361: E/SQLiteDatabase(821): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2732)
    03-11 12:52:58.361: E/SQLiteDatabase(821): at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2771)
    03-11 12:52:58.361: E/SQLiteDatabase(821): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2235)
    03-11 12:52:58.361: E/SQLiteDatabase(821): at android.app.ActivityThread.access$600(ActivityThread.java:141)
    03-11 12:52:58.361: E/SQLiteDatabase(821): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
    03-11 12:52:58.361: E/SQLiteDatabase(821): at android.os.Handler.dispatchMessage(Handler.java:99)
    03-11 12:52:58.361: E/SQLiteDatabase(821): at android.os.Looper.loop(Looper.java:137)
    03-11 12:52:58.361: E/SQLiteDatabase(821): at android.app.ActivityThread.main(ActivityThread.java:5041)
    03-11 12:52:58.361: E/SQLiteDatabase(821): at java.lang.reflect.Method.invokeNative(Native Method)
    03-11 12:52:58.361: E/SQLiteDatabase(821): at java.lang.reflect.Method.invoke(Method.java:511)
    03-11 12:52:58.361: E/SQLiteDatabase(821): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
    03-11 12:52:58.361: E/SQLiteDatabase(821): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
    03-11 12:52:58.361: E/SQLiteDatabase(821): at dalvik.system.NativeStart.main(Native Method)
    03-11 12:52:58.411: D/AndroidRuntime(821): Shutting down VM
    03-11 12:52:58.411: W/dalvikvm(821): threadid=1: thread exiting with uncaught exception (group=0x40a71930)
    03-11 12:52:58.471: E/AndroidRuntime(821): FATAL EXCEPTION: main
    03-11 12:52:58.471: E/AndroidRuntime(821): java.lang.RuntimeException: Unable to resume activity {com.mapapp.mapapp/com.mapapp.main.MapAppActivity}: android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
    03-11 12:52:58.471: E/AndroidRuntime(821): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2742)
    03-11 12:52:58.471: E/AndroidRuntime(821): at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2771)
    03-11 12:52:58.471: E/AndroidRuntime(821): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2235)
    03-11 12:52:58.471: E/AndroidRuntime(821): at android.app.ActivityThread.access$600(ActivityThread.java:141)
    03-11 12:52:58.471: E/AndroidRuntime(821): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
    03-11 12:52:58.471: E/AndroidRuntime(821): at android.os.Handler.dispatchMessage(Handler.java:99)
    03-11 12:52:58.471: E/AndroidRuntime(821): at android.os.Looper.loop(Looper.java:137)
    03-11 12:52:58.471: E/AndroidRuntime(821): at android.app.ActivityThread.main(ActivityThread.java:5041)
    03-11 12:52:58.471: E/AndroidRuntime(821): at java.lang.reflect.Method.invokeNative(Native Method)
    03-11 12:52:58.471: E/AndroidRuntime(821): at java.lang.reflect.Method.invoke(Method.java:511)
    03-11 12:52:58.471: E/AndroidRuntime(821): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
    03-11 12:52:58.471: E/AndroidRuntime(821): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
    03-11 12:52:58.471: E/AndroidRuntime(821): at dalvik.system.NativeStart.main(Native Method)
    03-11 12:52:58.471: E/AndroidRuntime(821): Caused by: android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
    03-11 12:52:58.471: E/AndroidRuntime(821): at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
    03-11 12:52:58.471: E/AndroidRuntime(821): at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:209)
    03-11 12:52:58.471: E/AndroidRuntime(821): at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193)
    03-11 12:52:58.471: E/AndroidRuntime(821): at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463)
    03-11 12:52:58.471: E/AndroidRuntime(821): at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185)
    03-11 12:52:58.471: E/AndroidRuntime(821): at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177)
    03-11 12:52:58.471: E/AndroidRuntime(821): at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:804)
    03-11 12:52:58.471: E/AndroidRuntime(821): at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:789)
    03-11 12:52:58.471: E/AndroidRuntime(821): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694)
    03-11 12:52:58.471: E/AndroidRuntime(821): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:669)
    03-11 12:52:58.471: E/AndroidRuntime(821): at com.mapapp.tileManagement.TilesProvider.(TilesProvider.java:19)
    03-11 12:52:58.471: E/AndroidRuntime(821): at com.mapapp.main.MapAppActivity.initViews(MapAppActivity.java:67)
    03-11 12:52:58.471: E/AndroidRuntime(821): at com.mapapp.main.MapAppActivity.onResume(MapAppActivity.java:49)
    03-11 12:52:58.471: E/AndroidRuntime(821): at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1185)
    03-11 12:52:58.471: E/AndroidRuntime(821): at android.app.Activity.performResume(Activity.java:5182)
    03-11 12:52:58.471: E/AndroidRuntime(821): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2732)
    03-11 12:52:58.471: E/AndroidRuntime(821): … 12 more
    03-11 12:53:02.881: I/Process(821): Sending signal. PID: 821 SIG: 9

    so now what i do?

  39. shashank
    11/03/2013 at 4:17 pm

    i am getting these type of error
    03-11 14:15:15.864: E/Trace(873): error opening trace file: No such file or directory (2)
    03-11 14:15:16.214: E/SQLiteLog(873): (14) cannot open file at line 30176 of [00bb9c9ce4]
    03-11 14:15:16.214: E/SQLiteLog(873): (14) os_unix.c:30176: (2) open(/mnt/sdcard/mapapp/world.sqlitedb) –
    03-11 14:15:16.234: E/SQLiteDatabase(873): Failed to open database ‘/mnt/sdcard/mapapp/world.sqlitedb’.
    03-11 14:15:16.234: E/SQLiteDatabase(873): android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
    03-11 14:15:16.234: E/SQLiteDatabase(873): at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
    03-11 14:15:16.234: E/SQLiteDatabase(873): at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:209)
    03-11 14:15:16.234: E/SQLiteDatabase(873): at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193)
    03-11 14:15:16.234: E/SQLiteDatabase(873): at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463)
    03-11 14:15:16.234: E/SQLiteDatabase(873): at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185)
    03-11 14:15:16.234: E/SQLiteDatabase(873): at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177)
    03-11 14:15:16.234: E/SQLiteDatabase(873): at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:804)
    03-11 14:15:16.234: E/SQLiteDatabase(873): at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:789)
    03-11 14:15:16.234: E/SQLiteDatabase(873): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694)
    03-11 14:15:16.234: E/SQLiteDatabase(873): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:669)
    03-11 14:15:16.234: E/SQLiteDatabase(873): at com.mapapp.tileManagement.TilesProvider.(TilesProvider.java:19)
    03-11 14:15:16.234: E/SQLiteDatabase(873): at com.mapapp.main.MapAppActivity.initViews(MapAppActivity.java:66)
    03-11 14:15:16.234: E/SQLiteDatabase(873): at com.mapapp.main.MapAppActivity.onResume(MapAppActivity.java:47)
    03-11 14:15:16.234: E/SQLiteDatabase(873): at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1185)
    03-11 14:15:16.234: E/SQLiteDatabase(873): at android.app.Activity.performResume(Activity.java:5182)
    03-11 14:15:16.234: E/SQLiteDatabase(873): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2732)
    03-11 14:15:16.234: E/SQLiteDatabase(873): at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2771)
    03-11 14:15:16.234: E/SQLiteDatabase(873): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2235)
    03-11 14:15:16.234: E/SQLiteDatabase(873): at android.app.ActivityThread.access$600(ActivityThread.java:141)
    03-11 14:15:16.234: E/SQLiteDatabase(873): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
    03-11 14:15:16.234: E/SQLiteDatabase(873): at android.os.Handler.dispatchMessage(Handler.java:99)
    03-11 14:15:16.234: E/SQLiteDatabase(873): at android.os.Looper.loop(Looper.java:137)
    03-11 14:15:16.234: E/SQLiteDatabase(873): at android.app.ActivityThread.main(ActivityThread.java:5041)
    03-11 14:15:16.234: E/SQLiteDatabase(873): at java.lang.reflect.Method.invokeNative(Native Method)
    03-11 14:15:16.234: E/SQLiteDatabase(873): at java.lang.reflect.Method.invoke(Method.java:511)
    03-11 14:15:16.234: E/SQLiteDatabase(873): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
    03-11 14:15:16.234: E/SQLiteDatabase(873): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
    03-11 14:15:16.234: E/SQLiteDatabase(873): at dalvik.system.NativeStart.main(Native Method)
    03-11 14:15:16.234: D/AndroidRuntime(873): Shutting down VM
    03-11 14:15:16.245: W/dalvikvm(873): threadid=1: thread exiting with uncaught exception (group=0x40a71930)
    03-11 14:15:16.254: E/AndroidRuntime(873): FATAL EXCEPTION: main
    03-11 14:15:16.254: E/AndroidRuntime(873): java.lang.RuntimeException: Unable to resume activity {com.mapapp.mapapp/com.mapapp.main.MapAppActivity}: android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
    03-11 14:15:16.254: E/AndroidRuntime(873): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2742)
    03-11 14:15:16.254: E/AndroidRuntime(873): at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2771)
    03-11 14:15:16.254: E/AndroidRuntime(873): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2235)
    03-11 14:15:16.254: E/AndroidRuntime(873): at android.app.ActivityThread.access$600(ActivityThread.java:141)
    03-11 14:15:16.254: E/AndroidRuntime(873): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
    03-11 14:15:16.254: E/AndroidRuntime(873): at android.os.Handler.dispatchMessage(Handler.java:99)
    03-11 14:15:16.254: E/AndroidRuntime(873): at android.os.Looper.loop(Looper.java:137)
    03-11 14:15:16.254: E/AndroidRuntime(873): at android.app.ActivityThread.main(ActivityThread.java:5041)
    03-11 14:15:16.254: E/AndroidRuntime(873): at java.lang.reflect.Method.invokeNative(Native Method)
    03-11 14:15:16.254: E/AndroidRuntime(873): at java.lang.reflect.Method.invoke(Method.java:511)
    03-11 14:15:16.254: E/AndroidRuntime(873): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
    03-11 14:15:16.254: E/AndroidRuntime(873): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
    03-11 14:15:16.254: E/AndroidRuntime(873): at dalvik.system.NativeStart.main(Native Method)
    03-11 14:15:16.254: E/AndroidRuntime(873): Caused by: android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
    03-11 14:15:16.254: E/AndroidRuntime(873): at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
    03-11 14:15:16.254: E/AndroidRuntime(873): at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:209)
    03-11 14:15:16.254: E/AndroidRuntime(873): at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193)
    03-11 14:15:16.254: E/AndroidRuntime(873): at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463)
    03-11 14:15:16.254: E/AndroidRuntime(873): at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185)
    03-11 14:15:16.254: E/AndroidRuntime(873): at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177)
    03-11 14:15:16.254: E/AndroidRuntime(873): at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:804)
    03-11 14:15:16.254: E/AndroidRuntime(873): at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:789)
    03-11 14:15:16.254: E/AndroidRuntime(873): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694)
    03-11 14:15:16.254: E/AndroidRuntime(873): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:669)
    03-11 14:15:16.254: E/AndroidRuntime(873): at com.mapapp.tileManagement.TilesProvider.(TilesProvider.java:19)
    03-11 14:15:16.254: E/AndroidRuntime(873): at com.mapapp.main.MapAppActivity.initViews(MapAppActivity.java:66)
    03-11 14:15:16.254: E/AndroidRuntime(873): at com.mapapp.main.MapAppActivity.onResume(MapAppActivity.java:47)
    03-11 14:15:16.254: E/AndroidRuntime(873): at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1185)
    03-11 14:15:16.254: E/AndroidRuntime(873): at android.app.Activity.performResume(Activity.java:5182)
    03-11 14:15:16.254: E/AndroidRuntime(873): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2732)
    03-11 14:15:16.254: E/AndroidRuntime(873): … 12 more

    • Fuchs
      11/03/2013 at 4:19 pm

      That’s strange! what Android version do you have?

  40. shashank
    11/03/2013 at 4:32 pm

    plz help me its urgent

  41. shashank
    11/03/2013 at 4:33 pm

    4.2 jelly bean

    • Fuchs
      11/03/2013 at 4:37 pm

      The problem is new to me! usually copying the database file to /mapapp is enough!.
      I’m looking for a solution right now and I’ll tell you when I find a solution.

  42. shashank
    11/03/2013 at 4:50 pm

    ok thanku

  43. shashank
    11/03/2013 at 7:06 pm

    where can is save the sqllite in eclipse

  44. shashank
    12/03/2013 at 6:26 am

    where i save the db in eclipse
    plz help me quickly

    • Fuchs
      12/03/2013 at 6:28 am

      You can either download the map by scanning the qrcode above, or simple copy it to your phone like any other file.
      You can also use DDMS in eclipse (usually located in the upper right corner of eclipse) to send files to your phone and create folders.

    • Fuchs
      12/03/2013 at 7:01 am

      If you mean you’re working on an emulator you can do it using DDMS, please check this:
      http://developer.android.com/tools/debugging/ddms.html

      It explains how you can use DDMS to create folders on the emulator and how to copy a file from your computer to the emulator

  45. 21/03/2013 at 4:50 pm

    Hello Fuchs. We finished the first stage of our project. We’re currently working on its progress. Just wanna say thanks (from me and bunnywants) for all the help. We really appreciate it. Kudos to your generosity. May you never get tired of helping others (including us). Thanks again! 🙂

    • Fuchs
      21/03/2013 at 5:01 pm

      That’s very kind of you :), I’m glad I could help, wish you the best luck with your project :).

  46. naveen saini
    11/04/2013 at 2:59 pm

    04-11 12:47:06.372: W/dalvikvm(2503): threadid=1: thread exiting with uncaught exception (group=0x40a71930)
    04-11 12:47:06.622: E/AndroidRuntime(2503): FATAL EXCEPTION: main
    04-11 12:47:06.622: E/AndroidRuntime(2503): java.lang.RuntimeException: Unable to resume activity {com.mapapp.mapappweb/com.mapapp.main.MapAppActivity}: android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
    04-11 12:47:06.622: E/AndroidRuntime(2503): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2742)
    04-11 12:47:06.622: E/AndroidRuntime(2503): at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2771)
    04-11 12:47:06.622: E/AndroidRuntime(2503): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2235)
    04-11 12:47:06.622: E/AndroidRuntime(2503): at android.app.ActivityThread.access$600(ActivityThread.java:141)
    04-11 12:47:06.622: E/AndroidRuntime(2503): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
    04-11 12:47:06.622: E/AndroidRuntime(2503): at android.os.Handler.dispatchMessage(Handler.java:99)
    04-11 12:47:06.622: E/AndroidRuntime(2503): at android.os.Looper.loop(Looper.java:137)
    04-11 12:47:06.622: E/AndroidRuntime(2503): at android.app.ActivityThread.main(ActivityThread.java:5041)
    04-11 12:47:06.622: E/AndroidRuntime(2503): at java.lang.reflect.Method.invokeNative(Native Method)
    04-11 12:47:06.622: E/AndroidRuntime(2503): at java.lang.reflect.Method.invoke(Method.java:511)
    04-11 12:47:06.622: E/AndroidRuntime(2503): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
    04-11 12:47:06.622: E/AndroidRuntime(2503): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
    04-11 12:47:06.622: E/AndroidRuntime(2503): at dalvik.system.NativeStart.main(Native Method)
    04-11 12:47:06.622: E/AndroidRuntime(2503): Caused by: android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
    04-11 12:47:06.622: E/AndroidRuntime(2503): at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
    04-11 12:47:06.622: E/AndroidRuntime(2503): at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:209)
    04-11 12:47:06.622: E/AndroidRuntime(2503): at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193)
    04-11 12:47:06.622: E/AndroidRuntime(2503): at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463)
    04-11 12:47:06.622: E/AndroidRuntime(2503): at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185)
    04-11 12:47:06.622: E/AndroidRuntime(2503): at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177)
    04-11 12:47:06.622: E/AndroidRuntime(2503): at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:804)
    04-11 12:47:06.622: E/AndroidRuntime(2503): at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:789)
    04-11 12:47:06.622: E/AndroidRuntime(2503): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694)
    04-11 12:47:06.622: E/AndroidRuntime(2503): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:669)
    04-11 12:47:06.622: E/AndroidRuntime(2503): at com.mapapp.tileManagement.TilesProvider.(TilesProvider.java:55)
    04-11 12:47:06.622: E/AndroidRuntime(2503): at com.mapapp.main.MapAppActivity.initViews(MapAppActivity.java:90)
    04-11 12:47:06.622: E/AndroidRuntime(2503): at com.mapapp.main.MapAppActivity.onResume(MapAppActivity.java:72)
    04-11 12:47:06.622: E/AndroidRuntime(2503): at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1185)
    04-11 12:47:06.622: E/AndroidRuntime(2503): at android.app.Activity.performResume(Activity.java:5182)
    04-11 12:47:06.622: E/AndroidRuntime(2503): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2732)
    04-11 12:47:06.622: E/AndroidRuntime(2503): … 12 more
    04-11 12:47:10.753: I/Process(2503): Sending signal. PID: 2503 SIG: 9
    04-11 12:56:05.473: E/Trace(2627): error opening trace file: No such file or directory (2)
    04-11 12:56:06.233: E/SQLiteLog(2627): (14) cannot open file at line 30176 of [00bb9c9ce4]
    04-11 12:56:06.233: E/SQLiteLog(2627): (14) os_unix.c:30176: (2) open(/mnt/sdcard/mapapp/world.sqlitedb) –
    04-11 12:56:06.273: E/SQLiteDatabase(2627): Failed to open database ‘/mnt/sdcard/mapapp/world.sqlitedb’.
    04-11 12:56:06.273: E/SQLiteDatabase(2627): android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
    04-11 12:56:06.273: E/SQLiteDatabase(2627): at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
    04-11 12:56:06.273: E/SQLiteDatabase(2627): at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:209)
    04-11 12:56:06.273: E/SQLiteDatabase(2627): at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193)
    04-11 12:56:06.273: E/SQLiteDatabase(2627): at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463)
    04-11 12:56:06.273: E/SQLiteDatabase(2627): at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185)
    04-11 12:56:06.273: E/SQLiteDatabase(2627): at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177)
    04-11 12:56:06.273: E/SQLiteDatabase(2627): at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:804)
    04-11 12:56:06.273: E/SQLiteDatabase(2627): at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:789)
    04-11 12:56:06.273: E/SQLiteDatabase(2627): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694)
    04-11 12:56:06.273: E/SQLiteDatabase(2627): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:669)
    04-11 12:56:06.273: E/SQLiteDatabase(2627): at com.mapapp.tileManagement.TilesProvider.(TilesProvider.java:55)
    04-11 12:56:06.273: E/SQLiteDatabase(2627): at com.mapapp.main.MapAppActivity.initViews(MapAppActivity.java:90)
    04-11 12:56:06.273: E/SQLiteDatabase(2627): at com.mapapp.main.MapAppActivity.onResume(MapAppActivity.java:72)
    04-11 12:56:06.273: E/SQLiteDatabase(2627): at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1185)
    04-11 12:56:06.273: E/SQLiteDatabase(2627): at android.app.Activity.performResume(Activity.java:5182)
    04-11 12:56:06.273: E/SQLiteDatabase(2627): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2732)
    04-11 12:56:06.273: E/SQLiteDatabase(2627): at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2771)
    04-11 12:56:06.273: E/SQLiteDatabase(2627): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2235)
    04-11 12:56:06.273: E/SQLiteDatabase(2627): at android.app.ActivityThread.access$600(ActivityThread.java:141)
    04-11 12:56:06.273: E/SQLiteDatabase(2627): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
    04-11 12:56:06.273: E/SQLiteDatabase(2627): at android.os.Handler.dispatchMessage(Handler.java:99)
    04-11 12:56:06.273: E/SQLiteDatabase(2627): at android.os.Looper.loop(Looper.java:137)
    04-11 12:56:06.273: E/SQLiteDatabase(2627): at android.app.ActivityThread.main(ActivityThread.java:5041)
    04-11 12:56:06.273: E/SQLiteDatabase(2627): at java.lang.reflect.Method.invokeNative(Native Method)
    04-11 12:56:06.273: E/SQLiteDatabase(2627): at java.lang.reflect.Method.invoke(Method.java:511)
    04-11 12:56:06.273: E/SQLiteDatabase(2627): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
    04-11 12:56:06.273: E/SQLiteDatabase(2627): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
    04-11 12:56:06.273: E/SQLiteDatabase(2627): at dalvik.system.NativeStart.main(Native Method)
    04-11 12:56:06.273: D/AndroidRuntime(2627): Shutting down VM
    04-11 12:56:06.283: W/dalvikvm(2627): threadid=1: thread exiting with uncaught exception (group=0x40a71930)
    04-11 12:56:06.313: E/AndroidRuntime(2627): FATAL EXCEPTION: main
    04-11 12:56:06.313: E/AndroidRuntime(2627): java.lang.RuntimeException: Unable to resume activity {com.mapapp.mapappweb/com.mapapp.main.MapAppActivity}: android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
    04-11 12:56:06.313: E/AndroidRuntime(2627): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2742)
    04-11 12:56:06.313: E/AndroidRuntime(2627): at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2771)
    04-11 12:56:06.313: E/AndroidRuntime(2627): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2235)
    04-11 12:56:06.313: E/AndroidRuntime(2627): at android.app.ActivityThread.access$600(ActivityThread.java:141)
    04-11 12:56:06.313: E/AndroidRuntime(2627): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
    04-11 12:56:06.313: E/AndroidRuntime(2627): at android.os.Handler.dispatchMessage(Handler.java:99)
    04-11 12:56:06.313: E/AndroidRuntime(2627): at android.os.Looper.loop(Looper.java:137)
    04-11 12:56:06.313: E/AndroidRuntime(2627): at android.app.ActivityThread.main(ActivityThread.java:5041)
    04-11 12:56:06.313: E/AndroidRuntime(2627): at java.lang.reflect.Method.invokeNative(Native Method)
    04-11 12:56:06.313: E/AndroidRuntime(2627): at java.lang.reflect.Method.invoke(Method.java:511)
    04-11 12:56:06.313: E/AndroidRuntime(2627): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
    04-11 12:56:06.313: E/AndroidRuntime(2627): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
    04-11 12:56:06.313: E/AndroidRuntime(2627): at dalvik.system.NativeStart.main(Native Method)
    04-11 12:56:06.313: E/AndroidRuntime(2627): Caused by: android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
    04-11 12:56:06.313: E/AndroidRuntime(2627): at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
    04-11 12:56:06.313: E/AndroidRuntime(2627): at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:209)
    04-11 12:56:06.313: E/AndroidRuntime(2627): at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193)
    04-11 12:56:06.313: E/AndroidRuntime(2627): at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463)
    04-11 12:56:06.313: E/AndroidRuntime(2627): at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185)
    04-11 12:56:06.313: E/AndroidRuntime(2627): at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177)
    04-11 12:56:06.313: E/AndroidRuntime(2627): at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:804)
    04-11 12:56:06.313: E/AndroidRuntime(2627): at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:789)
    04-11 12:56:06.313: E/AndroidRuntime(2627): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694)
    04-11 12:56:06.313: E/AndroidRuntime(2627): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:669)
    04-11 12:56:06.313: E/AndroidRuntime(2627): at com.mapapp.tileManagement.TilesProvider.(TilesProvider.java:55)
    04-11 12:56:06.313: E/AndroidRuntime(2627): at com.mapapp.main.MapAppActivity.initViews(MapAppActivity.java:90)
    04-11 12:56:06.313: E/AndroidRuntime(2627): at com.mapapp.main.MapAppActivity.onResume(MapAppActivity.java:72)
    04-11 12:56:06.313: E/AndroidRuntime(2627): at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1185)
    04-11 12:56:06.313: E/AndroidRuntime(2627): at android.app.Activity.performResume(Activity.java:5182)
    04-11 12:56:06.313: E/AndroidRuntime(2627): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2732)
    04-11 12:56:06.313: E/AndroidRuntime(2627): … 12 more
    04-11 12:56:08.942: I/Process(2627): Sending signal. PID: 2627 SIG: 9

    hi fuch ,
    i am getting these errors
    pleasse help me its urgent

    • Fuchs
      11/04/2013 at 9:27 pm

      {com.mapapp.mapappweb/com.mapapp.main.MapAppActivity}: android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database

      The database file cannot be found, please make sure you have a folder on your sdcard named mapapp and copy the database provided in the post to it, that’s because the database path is hardcoded (for simplicity) as sdcard/mapapp/World.sqlite

      If this doesn’t help please reply with a comment containing the android version you have.

  47. naveen saini
    12/04/2013 at 10:05 am

    hi fuch,

    i am using android 2.3 gingerberd and tring to run this app on a eclipse .
    i am creating a virtual machine in eclipse project and this machine makes a sdcsrd folder name sdcard.img.lock.
    so in this folder how can i save world.sqlite

    reply uegent

    • Fuchs
      12/04/2013 at 1:32 pm

      Okay this can be solved easily I hope, in Eclipse you can use DDMS to manage folders and files on the device.
      Just make sure the emulator is running then in DDMS file explorer navigate to the sdcard path and create the folder mapapp and push the database file to it.
      Using DDMS is explained here in detail, you’re mostly interested in Working with an emulator or device’s file system.

  48. nishu
    16/04/2013 at 7:02 pm

    hi fuchs,
    how can i download the map for our street

    • Fuchs
      16/04/2013 at 9:02 pm

      Use Mobile Atlas Creator for that, just make sure you download a small amount of tiles or you’ll exhaust the servers and get blocked.

      • nishu
        17/04/2013 at 6:51 pm

        hi Fuchs,
        what value should i select for atlas format & map source in mobile atlas creator?

        • Fuchs
          17/04/2013 at 11:43 pm

          For the format you should select RMaps sqlite, for the map source you can choose the source you want.

  49. Kitsos
    27/04/2013 at 2:24 pm

    Fuchs so far your app has worked great for me. My problem is that I have a small map inserted and a sqlite databse with some coordinates and I want to add a clickable marker to each one of those coordinates. I don’t want the markers to be edible ,but i need them to be clickable. Is this possible?
    Thank you for your time.

    • Fuchs
      30/04/2013 at 7:37 pm

      Really sorry for the late response, kind of busy.
      You have a gps coordinate and a touch position, each one is in different coordinate space so we need to convert them both to something in between then compare them.
      We will convert them both to world map pixel coordinates where values go from zero to 2^(zoom-1)

      Somewhere inside your MapView.onTouch you check the event type then do something like the following:

      // Get center of mapView (pixels)
      Point center_local = new Point(getWidth() / 2, getHeight() / 2);
      // Get offset of touch position relative to center of mapView
      Point touchDiff_local = new Point(center_local.x - (int) event.getX(), center_local.y - (int) event.getY());
      
      // Get pixel coordinates of mapView center on world map (pixels)
      Point center_global = tileManager.lonLatToPixelXY(seekLocation.x, seekLocation.y);
      
      // Apply calculated offset to center_global
      Point touch_global = new Point(center_global.x - touchDiff_local.x, center_global.y - touchDiff_local.y);
      
      // Convert your point coordinates to pixel coordinates
      // coord is your point that has to methods to return the coordinates
      Point coord_global = tileManager.lonLatToPixelXY(coord.getLongitude(), coord.getLatitude());
      
      // Now both values are in the same coordinate system and we can compare them directly
      if (Math.abs(coord_global.x - touch_global.x) < 50 && Math.abs(coord_global.y - touch_global.y) < 50)
      {
      	// do something
      }
      

      You can also take a look at FuchsMaps, an app I built with many features, one of them is points of interest (POI).
      POIOverlay is the class that renders the points and handles the click events for each point.
      I hope this helps :).

  50. Isaac
    26/06/2013 at 1:53 am

    Hi, it’s a great project but I dont know if I’m doing it right, I just able to get zoom 4, when I get the zoom 5 there’s nothing, is that normal?? and if it does how can I improve it to get to see streets?? Thanks in advance.

    • Fuchs
      26/06/2013 at 6:58 am

      Hi,
      This is completely normal because the database I provided only contains tiles up to zoom level 4, I wanted to provide a database large enough to demonstrate the capabilities of the app.
      To have more zoom levels try Mobile Atlas Creator,it’s easy to use but if something is not clear you’ll find plenty of tutorials on the internet like this one.
      So just download Mobile Atlas Creator and export the map in RMaps sqlite format and replace the file I provided with the new one.

      One thing you might want to check out is the Part 6 of this tutorial : Web support, where missing tiles are downloaded only when needed and then kept in the local database for later usage, this way you reduce bandwidth and put less stress on the map tiles server.

      I hope this helps 🙂

  51. 14/09/2013 at 3:10 am

    The tutorials were amazing! But how would you implement map rotation?

    • Fuchs
      14/09/2013 at 3:44 pm

      Thanks :), Interesting question, my guess is that you’ll have to use the canvas.rotate in the MapView.onDraw.
      When map is rotated you’ll have to consider that touches on the map will also need to be rotated, I don’t have an implementation but it should be a simple 2D rotation using sin & cos.
      One last point, the names of the streets (and any other text printed on the map) will also be rotated since the map tiles are per-rendered images.
      I hope this helps 🙂 .

  52. 18/09/2013 at 8:28 am

    hi,i have put your World.sqlitedb file in right place but the app shows only a small picture of map.how i can fix it?

    • Fuchs
      18/09/2013 at 11:26 am

      You can zoom in\out using the volume keys, I hope you have those :).

      • 21/09/2013 at 12:12 am

        yes,it works.
        Now i want to put circle in different places.provide name to those circles and retrieve information (name and latitude,longitude)about places when clicking on it.
        how can i do it ?

        Thanks in advance

        • Fuchs
          23/09/2013 at 11:49 am

          You can check these comments here

          You can also take a look at source code of FuchsMaps which is closely related to the tutorials here:
          Fuchs Maps.
          In FuchsMaps what you want is implemented in classes as POI and POIOverlay.

  53. 03/12/2013 at 3:58 pm

    i am making a project of android map app as u have said on your blog that we can download a APK file and run it on emulator
    but i dont have a sdcard for storage of database sqllite file but i want to run it on my emulator is there any another way to run it on emulator.
    Actually the Icon of map App like T symbol is showing on my emulator(AVD) made through Eclipse but when i am clicking on it its showing an error:map app.com not found
    what should i do?

    • Fuchs
      04/12/2013 at 8:52 pm

      You can actually create a virtual SD Card for the emulator! have you tried that 🙂 ?

      • 05/12/2013 at 5:42 am

        can u tell me the process of making of virtual SD card how to make a virtual SD card for my emulator?

  54. 12/12/2013 at 8:27 am

    yes i have made vitual SDcard for my emulator but when i am trying to run this app on my emulator its shows icon with T symbol but when i clicked on it, its shows me error like:-“The application Map App(process.com.mapapp.mapapp) has stopped unexpectedly. please try again.” what should i do next to run this app?

    • Fuchs
      14/12/2013 at 10:53 am

      have you tried putting the database file on the sd card? the LogCat will help you to identify the error.
      In Eclipse, Go to Window-> Show View -> Other -> Android-> Logcat.

  55. ari
    18/01/2014 at 5:35 am

    it is possible to change the map in mapnik?

    • Fuchs
      18/01/2014 at 12:25 pm

      The app is mainly a client to display tile based maps, if you give it a mapnik map it should display it fine.
      So you should find a way to get the mapnik map. Mobile Atlas Creator can download the mapnik tiles but after a very short while all the tiles turn to big red X image.

  56. Ian
    28/01/2014 at 2:57 pm

    Thankyou so much for this tutorial. It has given me a place to start learning about mapping and gps. I put the app and database on my garmin nuvi phone and it works fine. Putting it on the samsung galaxy note it just displays a blank screen then says its stopped running. Is therea run time log I can look at to see why it wont run as I would like my target to be the tablet,
    Regards

    • Fuchs
      28/01/2014 at 6:59 pm

      Hi, maybe because in your Samsung the path /mnt/sdcard is NOT the external storage path returned by getExternalStorage() which is used to get the tiles database:

      String path = Environment.getExternalStorageDirectory() + "/mapapp/world.sqlitedb";
      

      Just open the MapAppActivity.java and place a breakpoint at that line and see what path it returns.
      In any case you can check the logcat to know the error.
      I hope this helps 🙂

  57. Ian
    29/01/2014 at 3:18 pm

    thanks will try that when I am able to view the code

  58. Kitti
    29/01/2014 at 3:57 pm

    Hello Hisham,

    I found the tutorial to be very useful. Thanks a ton for investing so much of time on these kind of projects. I love the tile rendering part. Quadkeys, indexing and all. Nice concept.

    I have a query, can i show google maps as base layer and overlay tiles on top of google maps. Can you give me an idea.

    • Fuchs
      29/01/2014 at 7:28 pm

      Hi, I’m glad you liked it.
      About the Google Maps layer: yes you can, you just need to get the tiles from Google and display them the same way done here, same calculations and same everything. The tricky part is getting the tiles. A previous version of Mobile Atlas Creator enabled the user to create maps using Google Maps but then Google (and other map providers) asked the developer to remove their servers from the map sources menu (link).
      I guess you can still get the tiles from Google but not for free.
      If you’re asking about how to display two layers then I can explain the basic idea to you.

      • kitti
        29/01/2014 at 8:47 pm

        yeah, would be of great help if you can provide basic idea in displaying two layers, Google maps as base layer and any other top layer.

        In the process of showing 2 layers, for Google maps, I think I can use Android Google Maps API. But in this case, I really have to think of supporting offline Google maps.

      • Kitti
        30/01/2014 at 4:40 am

        Yeah, m looking forward to hear from you for two layers. Something like Google maps being bottom most layer and some other layer on it’s top.

        I am thinking to use Android Google Maps API for showing google maps. Can you help me out.

        • Fuchs
          31/01/2014 at 11:09 pm

          You’re right, its better to use Google Maps and add a layer on top of it.
          You can get a working map in no time by following this tutorial step by step:
          https://developers.google.com/maps/documentation/android/intro
          after that you can check this tutorial which explains exactly what you want to do:
          https://developers.google.com/maps/documentation/android/tileoverlay

          • Kitti
            04/02/2014 at 12:47 pm

            Thanks for your urls. I have a doubt regarding how Google maps are getting cached? Any reference to rendering/caching mechanism, how it’s happening? as incase if I try to save Google maps onto SD card, would be definitely a data storage issue.

            When we use Google maps in Android, where do these tiles get saved? Can i re-use them? I think they get saved in data folder.

          • Fuchs
            05/02/2014 at 6:24 pm

            Don’t worry about caching the tiles for Google Maps as they automatically get cached and can be viewed even if the device s offline.

  59. 24/02/2014 at 2:28 pm

    dear Fuchs
    thank you for your excellent tutorial for android app
    i have question
    i have map in ArcGIS with geographical coordinate lat/long
    i do application android indoor localization
    for that i taked this layout geographical and put it in android app
    when i check coordinate in screen android it shifted about geographical coordite exported from GIS Software
    i know this distortion due to change coordinate from lat long to screen 2d coordinate
    i have code to solve problem with high accuracy because i need work with real coordinat to upload my work in next step in google API

    coordinate used

    Geographic Coordinate System: GCS_WGS_1984
    Datum: D_WGS_1984
    Prime Meridian: Greenwich
    Angular Unit: Degree

    i need your support
    thanks

  60. 24/02/2014 at 2:31 pm

    dear Fuchs
    thank you for your excellent tutorial for android app
    i have question
    i have map in ArcGIS with geographical coordinate lat/long
    i do application android indoor localization
    for that i taked this layout geographical and put it in android app
    when i check coordinate in screen android it shifted about geographical coordinate exported from GIS Software
    i know this distortion due to change coordinate from lat long to screen 2d coordinate
    i need code tried to solve problem with high accuracy because i need work in my project with real coordinate to upload my work in next step in google API

    coordinate used

    Geographic Coordinate System: GCS_WGS_1984
    Datum: D_WGS_1984
    Prime Meridian: Greenwich
    Angular Unit: Degree

    i need your support
    thanks

    • Fuchs
      24/02/2014 at 5:32 pm

      Hi Ashraf,
      Can you please try the coordinates you exported on Google Maps and see if they are displayed correctly?
      just open http:/maps.google.com and type the coordinates you have in the search bar like this: lat,lng then click search.

  61. Mostafa
    25/02/2014 at 9:36 am

    Thanks a lot.

  62. 25/02/2014 at 10:54 am

    yes but i have shift errors different in different location when convert output from android application into Google earth
    this shift because the geographical coordinate in Google
    depend on coordinate system and projection and work in 3d but in android app it work on 2d and no coordinate system
    i know some equation can used to convert the screen unit from mobile output into lat long accurate but i need your help

    link may explain may problem with source code

    https://github.com/karls/math-geographicpoint

    • Fuchs
      03/03/2014 at 5:40 pm

      Sorry it took me this long to respond.
      About converting between lat,lng and screen pixels this is done using a well known formula.
      Check the TilesManager class and look for those two methods:

      lonLatToPixelXY(double longitude, double latitude)
      pixelXYToLonLat(int pixelX, int pixelY)
      

      The first method returns the pixel coordinates on the flat map you’re displaying, you just need to add an offset (depending on the camera offset).
      If you try to use some linear methods to convert between the two spaces it just wont work (especially for latitude).

      Google Maps also uses the WGS84 datum by the way.

      You can check my other project called Fuchs Maps which displays multiple markers.

  63. mateus
    28/02/2014 at 2:38 pm

    hi. this looks very interesting and simple, but can you tell me if I can do a similar app, but only using a piece of the map, like a country or a city?

    • Fuchs
      03/03/2014 at 6:00 pm

      Hi, the app simply displays the tiles contained in the database you create.
      You can easily download the tiles of a city by creating a rectangle around it in Mobile Atlas Creator.

  64. sayam
    09/03/2014 at 11:45 am

    This is a very nice tutorial best we can find about offline map. I have a map in mbtiles format
    how can load this map can u please suggest me

    • Fuchs
      14/03/2014 at 6:58 pm

      Can you provide any documentation/specification about this format?

    • Mario
      24/04/2014 at 8:19 am

      Made the sqlite database with Mobile Atlas Creator (RMaps SQLite format)

  65. Mario
    24/04/2014 at 8:18 am

    Great. I made the sqlite database with Mobile Atlas Creator (RMaps SQLite format) and works perfectly. Great.

  66. 24/04/2014 at 7:59 pm

    Hi Fuchs,sorry if I am frustrating you.by asking you too many questions.actually I am very much interested in apps creating.Any books,YouTube, CDs which I can studdy from it.and after then I ask my dought from you.I hope u don’t mind.thanks in advance

  67. 25/04/2014 at 6:50 am

    Hi Fuchs, I followed your tutorial.And finally created the offline map.but after installing the apps its shows “unfortunately,the map had stopped”.in androidmainfest.XML.to warning sign shows(1. tag appears after tag.
    2.not targeting the latest versions of androids;compability modes apply.conserding testing and updating this version.consult the android.os.build.VERSION_CODES javadoc for details.)is this because the problem for not opening the apps my phone.thanks in advance.

    • Fuchs
      27/04/2014 at 8:17 pm

      Hi Jaggy, it appears that the tutorial code might need some update, I’ll make sure to check this issue when I have the time.
      You can learn about breakpoints and LogCat to get the reason of the crash.

  68. Altaf
    30/04/2014 at 8:23 am

    Very nice tutorial, this is working fine on samsung galaxy s2 and s4 but on s3 map is not showing on full screen, it has cutting edges from right or sometime on left when move (drag) the map. from top and bottom it is fine, Please guide me how i can resolve this, i tried this with android version 4.2 and then 4.3 on samsung galaxy s3 but issue not resolved, it works good with other mobiles, i think there is screen size issue not android version. Please guide.

  69. Antero
    12/06/2014 at 3:42 pm

    Exceptionally clear introduction for a beginner like me! Do you have any idea, how to put a separate piece of offroad or sea map (bitmap, calibrated) into this application.

  70. 09/08/2014 at 11:43 am

    hi again Fuchs!

    I wonder if i could embed my own location
    (made in OSM maybe?) to this offline map
    that you just made.

    How could we achieve that?

    So then I could track where i am using GPS and along with your offline map concept.

  71. al amin
    23/09/2014 at 10:44 pm

    Hi,i want to create an apk file which will run on other devices (they will download it from server ).This map will show the location’s maps with different zoom levels.It will show many location which button they select.Basically it will different university location and totally offline.

  72. supsabhi
    10/05/2016 at 10:27 am

    HI,thnx for the great tutorial…what attracte me to this is you have stored the map in sqlite database,what i am trying to do is,i want to store route of map in databse(offline)and want to display those routes too.problem here is ,to save series of geopoints there is no limit how many points i will need to draw a path on it.(i m trying to implement path of indoor navigation) so routes can be large also

    • Fuchs
      10/05/2016 at 12:43 pm

      Hi, You’ll need to use a second sqlite database for the routes. Each row will have the route id and the coordinates. Remember that databases are designed to store a large number of entries. I’ve done something similar here
      https://ghoscher.com/2013/03/05/fuchs-maps/

  1. 09/03/2014 at 2:20 am

What do you think?

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: