Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

Pretty basic MapView crashes on Android, glitches a little on Iphone
Started by henrik5 Jan 16 2014 06:19 AM

33 replies to this topic
[TOPIC CONTROLS]
Page 1 of 2 1 2
This topic has been archived. This means that you cannot reply to this topic.
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#1

henrik5

[GLOBAL: userInfoPane.html]
henrik5
  • Contributor

  • 251 posts
  • Corona SDK

I'm using graphics v1 compatibility mode and the scene is shown as an overlay.

 

Can you spot an error in my code? I have checked it against the example in docs. The only difference is that it has the newMapView outside createScene. I must, because it has a nav bar.

 

 

 

 

local storyboard=require("storyboard")
local scene=storyboard.newScene()


GEOADDR="Storgatan 1, Nassjo, Sweden"
local tfaddr
local myMap




local function onbback(e)
    native.setKeyboardFocus( nil )
    storyboard.hideOverlay("slideRight",400)
    return true
end 




local function fieldHandler( getObj )
    return function( event )    -- Use Lua closure in order to access the TextField object
        print( "TextField Object is: " .. tostring( getObj() ) )
        if ( "began" == event.phase ) then    --onfocus
        elseif ( "ended" == event.phase ) then    --onblur
        elseif ( "submitted" == event.phase ) then    --onenter
            native.setKeyboardFocus( nil )
        end
    end     -- "return function()"
end


local function onbaddr(e)
    GEOADDR=tostring( tfaddr.text)
    if GEOADDR:len()>0 then
        print( "Text entered = " .. GEOADDR )         -- display the text entered
        myMap:requestLocation( GEOADDR, mapLocationHandler )
        native.setKeyboardFocus( nil )
    end
    return true    
end 


local function onbpinme(e)
    pinlat=91        --flag  --pinlon=USERLON
    --'move' pin and zoom to it
    myMap:removeAllMarkers()
    local options={title="Selected location:",subtitle="Your phone's location"}
    myMap:addMarker(USERLAT,USERLON,options)
        
    myMap:setCenter(USERLAT,USERLON,true)
    myMap:nearestAddress(pinlat,pinlon,mapAddressHandler)        
        
    return true    
end 


local function tfaddrHandler( event )
    fieldHandler( function() return tfaddr end ) -- passes the text field object
end
-----------------------
local function mapLocationHandler( event )
    if event.isError then
        local alert=native.showAlert("Google can't find "..GEOADDR,event.errorMessage,{"OK"})
    else
        --'move' pin and zoom to it
        pinlat=event.latitude
        pinlon=event.longitude
        myMap:removeAllMarkers()
        local options={title="Selected location:",subtitle=GEOADDR}
        myMap:addMarker(pinlat,pinlon,options)
        myMap:setCenter(pinlat,pinlon,true)
    end
end


local function mapAddressHandler(e)
    if e.isError then
        tfaddr.text="Address not found"
    else
        tfaddr.text=e.city..", "..e.country
    end
end




local function getAddr()
    myMap:nearestAddress(pinlat,pinlon,mapAddressHandler)
end




local function callMap()
    local currloc=myMap:getUserLocation()
    if currloc then
        local currlat=currloc.latitude
        local currlon=currloc.longitude
        myMap:setCenter(currlat,currlon,true)    --,1.5,1.5,true)
        myMap:nearestAddress(currentLatitude,currentLongitude)
    end
end 


-- Called when the scene's view does not exist:
function scene:createScene(event)
    print("map createScene")
    bg=display.newImageRect("assets/black16x16.png",CW2,CH2-50-T)    --white bg
    bg.x=CW
    bg.y=T+(CH2-50-T)/2
    self.view:insert(bg)
    --navbar
    inavbar=display.newImageRect("assets/navbarbg.png",320,64)
    inavbar.x=CW
    inavbar.y=64/2    --incl shadow 
    self.view:insert(inavbar)
    
    bback=backbuttonarrow("Tillbaka","bback",onbback,14)
    self.view:insert(bback)
    
    tfaddr=native.newTextField( CW-106, 6, 172, 32 )


    tfaddr:addEventListener( "userInput", tfaddrHandler )
    tfaddr.isVisible=false


    baddr=imgbuttonr("search","baddr",CW2-40-4-44-6,0,44,44,onbaddr)
    self.view:insert(baddr)    
    bpinme=imgbuttonr("gps","bpinme",CW2-40-4-0,0,44,44,onbpinme)
    self.view:insert(bpinme)    
    --map--
    myMap=native.newMapView(0,0,CW2,CH2-T-50)
    myMap.mapType="hybrid" -- other mapType options are "satellite" or "hybrid"


    -- The MapView is just another Corona display object,and can be moved or rotated,etc.
    myMap.x=CW
    myMap.y=(CH2-50-T)/2+T
    self.view:insert(myMap)


    --Runtime:addEventListener("mapAddress",mapAddressHandler)


end


-- Called immediately after scene has moved onscreen:
function scene:enterScene(event)
    print("enterScene view"..tabindex)    
    if pinlat>90 then
        pinlat=mylat
        pinlon=mylon
    end


    local options={title="Selected location:",subtitle="Your phone's location"}
    myMap:addMarker(pinlat,pinlon,options)
    tfaddr.isVisible=true


    --myMap:setCenter(pinlat,pinlon,true)


    timer.performWithDelay(1000,callMap) -- get current location after 1 second
    --timer.performWithDelay(2500,getAddr)


end 


-- Called when scene is about to move offscreen:
function scene:exitScene(event)
    print("exitScene view"..tabindex)    
    -- INSERT code here (e.g. stop timers,remove listeners,unload sounds,etc.)
    myMap:removeAllMarkers()
end


-- If scene's view is removed,scene:destroyScene() will be called just prior to:
function scene:destroyScene(event)
    -- INSERT code here (e.g. remove listeners,remove widgets,save state variables,etc.)
    if myMap then 
        --Runtime:removeEventListener("mapAddress",mapAddressHandler)
        myMap:removeSelf()
    end
    if tfaddr then
        tfaddr.isVisible=false
        tfaddr:removeEventListener("userInput",tfaddrHandler)
    end    
end


scene:addEventListener("createScene",scene)    -- "createScene" event is dispatched if scene's view does not exist
scene:addEventListener("enterScene",scene)    -- "enterScene" event is dispatched whenever scene transition has finished
scene:addEventListener("exitScene",scene)    -- "exitScene" event is dispatched whenever before next scene's transition begins
scene:addEventListener("destroyScene",scene)    -- "destroyScene" event is dispatched before view is unloaded,which can be
-- automatically unloaded in low memory situations,or explicitly via a call to
-- storyboard.purgeScene() or storyboard.removeScene().


return scene

 

 

 

 

Let me know any hints to get this working rock solid. Using Corona 2076.



[TOPIC: post.html]
#2

henrik5

[GLOBAL: userInfoPane.html]
henrik5
  • Contributor

  • 251 posts
  • Corona SDK

Managed to film the crash messages and pause the frame. The lesson learned was that handlers must be at the top of the source, so that functions that use them don't get a nil for the handler argument. In general you should define functions in load->use order.

 

You can store it in a variable to avoid this, and I suspect if they hadn't been local functions it would also have worked.

 

It crashed with and without v1 compatbility mode and now works in both, so that rules out any problems with build 2076.



[TOPIC: post.html]
#3

henrik5

[GLOBAL: userInfoPane.html]
henrik5
  • Contributor

  • 251 posts
  • Corona SDK

There seems to be a problem with re-adding markers with 2076, though. The first time a marker is added, it works properly. The following times a marker is added, that marker's coordinate system vs. the map scale is out of wack - as I zoom out, the marker is moved to another part of the country or outside the view...

 

 

 

 

local function onbpinme(event)
    myMap:setCenter(USERLAT,USERLON,true)
    myMap:nearestAddress(USERLAT,USERLON,mapAddressHandler)        


    myMap:removeAllMarkers()
    local options={title="Selected location:",subtitle="Your phone's location"}
    myMap:addMarker(USERLAT,USERLON,options)
    return true    
end
 

 

 

I will be very happy if you can locate any error in my code, or a workaround, such as "moving" a marker instead of deleting and re-adding it.

 

This happens with or without v1 compatibility mode. Help!!



[TOPIC: post.html]
#4

henrik5

[GLOBAL: userInfoPane.html]
henrik5
  • Contributor

  • 251 posts
  • Corona SDK

Saving the marker ID and removing just that if it's set, doesn't fix it. (I'm not editing my previous post since editing posts breaks the code formatting.)

Edit: I've now put the map creation code at the top of the source outside any function, instead of in createScene, and I don't self.view:insert() it anymore. I also don't removeSelf() on exit. Still doesn't work for the subsequent removeMarker()+addMarker().

If I don't use removeAllMarkers() or removeMarker() at all, it works. But I'd need some way of hiding them then, or access some table that I can empty manually with some magic code.

 

Edit 2: Also tried using gotoScene() rather than showOverlay() for the map scene, but of course having moved newMapView outside createScene() means I have no way of removing the mapView, so it stay on-screen when the main view slides in.

 

There's just no way I can seem to solve this and make a functioning app, because removing markers places the new ones in some unrelated co-ordinate system.



[TOPIC: post.html]
#5

Rob Miracle

[GLOBAL: userInfoPane.html]
Rob Miracle
  • Moderator

  • 25,895 posts
  • Enterprise

I would recommend updating Corona SDK to the latest public build 2100. and give that a go. If you are still having problems you will need to examine your console logs on your device and see if any errors are being generated.

 

Rob



[TOPIC: post.html]
#6

henrik5

[GLOBAL: userInfoPane.html]
henrik5
  • Contributor

  • 251 posts
  • Corona SDK

Yes, docs made me think I was using the latest SDK. 2013.2100 fixed this map pin error as well, so my app is hunky dory at the moment. This thread could be deleted to not confuse a visitor who has a genuine problem with the map view. Edit: nope, I judged too quickly.



[TOPIC: post.html]
#7

Rob Miracle

[GLOBAL: userInfoPane.html]
Rob Miracle
  • Moderator

  • 25,895 posts
  • Enterprise

When you start Corona SDK, it should provide  you the build number on the welcome screen as well as Under the About menu item.

 

Rob



[TOPIC: post.html]
#8

henrik5

[GLOBAL: userInfoPane.html]
henrik5
  • Contributor

  • 251 posts
  • Corona SDK

Yes, I was a bit too quick about it and compared that to the online docs, which say the current version is 2013.2076.

 

 

Looking at the logs I suspect some nil checks are to blame. How would I check a returned timer handle, whether it has been set or not, and how do I check a returned marker id whether a marker has been placed or not?



[TOPIC: post.html]
#9

henrik5

[GLOBAL: userInfoPane.html]
henrik5
  • Contributor

  • 251 posts
  • Corona SDK

No, my code checks out. The marker bug is still there in 2013.2100, and it's a bug. I just discovered that when this marker position goes off, the hitbox for the touch event is still in the correct place and triggers a callout correctly which "points" to the co-ordinates supplied it. I've filed the bug.



[TOPIC: post.html]
#10

nmichaud

[GLOBAL: userInfoPane.html]
nmichaud
  • Contributor

  • 492 posts
  • Corona SDK

@henrik 5, do you have the bug number ? This bug is also killing us. RemovingAllMarker and adding new one is bogus and even on the latest build .2156



[TOPIC: post.html]
#11

nmichaud

[GLOBAL: userInfoPane.html]
nmichaud
  • Contributor

  • 492 posts
  • Corona SDK

After looking on FogBugz we did not see any bugs relate to our problem. We have open a bug as the removeAllMarker and addMarker is currently unreliable.



[TOPIC: post.html]
#12

Bladko

[GLOBAL: userInfoPane.html]
Bladko
  • Contributor

  • 342 posts
  • Enterprise

Btw what is limit to add markers to map ?


I load marker data from my server on load (just json data), then create it 

 

local idd = myMap:addMarker( x, y, options )
 
After approximately 100 or 150 markers my iOS devices crushes 
 
I run publish starter version 2100


[TOPIC: post.html]
#13

ksan

[GLOBAL: userInfoPane.html]
ksan
  • Corona Geek

  • 2,795 posts
  • Corona SDK

Oops. I was just about to start a project where I will need to put in 100+ markers. I hope there is no such limitation at all. 



[TOPIC: post.html]
#14

nmichaud

[GLOBAL: userInfoPane.html]
nmichaud
  • Contributor

  • 492 posts
  • Corona SDK

@Bladko, so far we did not see any limit on the number of marker you can add. One of our thematic in our tourism app currently display 205 markers on iOS devices without any trouble.

 

On Android it is another story, we are working with the dev team to narrow down some unpredictable result when you addmarker after operations like removeAllMarker/SetRegion/SetCenter. 



[TOPIC: post.html]
#15

ksan

[GLOBAL: userInfoPane.html]
ksan
  • Corona Geek

  • 2,795 posts
  • Corona SDK

@nmichaud, I think I'm walking in your footsteps. Would love to hear if you were able to overcome the Android challenges and also how you handle the marker tap events. Thanks for anything and everything you might be able to share. 



[TOPIC: post.html]
#16

nmichaud

[GLOBAL: userInfoPane.html]
nmichaud
  • Contributor

  • 492 posts
  • Corona SDK

@Ksan, it seems that on Android, we need to use some timer before calling some of the map api. As for pin that sometime were offset, this is a bug with some Android version only. Corona was never able to replicate this on their side. On our Galaxy s3 we can reproduce any time bad marker position.

 

I have remove useless code from our app and show you how we deal with marker. I don't know if this what you are looking for. If not, ask, we have been working with map forever ;)

 

 
 
-- ************************************************************************
-- Update all pins in our map
-- ************************************************************************
local function _updatePins()
    if scene.googleMap then
        
        -- We always center the map based on our first visible pin in our table
        scene.googleMap:setCenter( .latitude, .longitude )
        
        -- our temporary marker lookup table
        scene.googleMarkerTable = {}
        
        -- method called when a marker is click on
        local function markerListener(event)          
            classStoryboard.gotoScene( "viewMarkerItem", { params = { markerItem = scene.googleMarkerTable[event.markerId] } } )
        end
 
        -- Iterate the tabledata
        for itrMarker = 1, #tableData do
                         
            local markerOptTbl = {
                listener = markerListener, 
                }
                
            local item = tableData[itrMarker]
            local result, errorMessage = scene.googleMap:addMarker( item.latitude, item.longitude, markerOptTbl )
            if result then
                scene.googleMarkerTable[result] = tableData[itrMarker]
            end
 
        end
 
    end
    
end
 
-- ************************************************************************
-- Dispatch the update all pins
-- ************************************************************************
function scene:updatePins()
    if scene.googleMap then
        scene.googleMap:removeAllMarkers()
        scene.googleMarkerTable = nil
        
        -- On Androit only, it seems that we must introduce a delay between
        -- calling removeAllMarkers and adding new one.
        timer.performWithDelay( gGlobalVar.addMarkerDelay, _updatePins )
    end
end
 
 
-- ************************************************************************
-- Create the map view, center the map and adjust the zoom
-- ************************************************************************
function scene:createMapView()
    
    scene.googleMap = native.newMapView( x, y, w, h )
  
    if scene.googleMap then
        scene.googleMap.anchorX = 0
        scene.googleMap.anchorY = 0
        scene.googleMap.mapType = "standard"
        
        local gpsMap = gGps
        scene.googleMap:setCenter( gpsMap.regCenterLat, gpsMap.regCenterLon )
        scene.googleMap:setRegion( gpsMap.regCenterLat, gpsMap.regCenterLon, 0.1, 0.1, false)
    end
 
end


[TOPIC: post.html]
#17

ksan

[GLOBAL: userInfoPane.html]
ksan
  • Corona Geek

  • 2,795 posts
  • Corona SDK

Hi @nmichaud, thank you so much for sharing your code. 

 

I am particularly interested in your marker touch listener 

 

        -- method called when a marker is click on
        local function markerListener(event)          
            classStoryboard.gotoScene( "viewMarkerItem", { params = { markerItem = scene.googleMarkerTable[event.markerId] } } )
        end

 

I am doing something very similar but noticing a lot of irregular behavior. Please see my thread on this for more detail : 

 

http://forums.coronalabs.com/topic/44906-mapview-marker-listener-is-very-inconsistent-and-un-reliable-any-ways-to-improve-this/?hl=mapview

 

Particularly, I see that sometimes you get the listener trigger on first tap, especially if you tap on the lower part of the marker and sometimes first tap brings the bubble and you need to tap the bubble to get the listener triggered (preferred behavior). I don't see any precaution against this in your listener. Do you have another alternate solution or did this issue not surface during your testing?

 

Thanks once again for sharing and apologies for taking this thread offtopic



[TOPIC: post.html]
#18

nmichaud

[GLOBAL: userInfoPane.html]
nmichaud
  • Contributor

  • 492 posts
  • Corona SDK

You are bringing something that hurt us badly. The Corona implementation of Google marker is quite weak in my opinion. What you are expecting cannot be done unfortunately. Here is what we discover during our initial implementation.

 

case 1: If in the option table you only define a callback. It will work as expected. Corona will call your callback when you tap the pin. Which is expected.

 

case 2: If you want to display the Google bubble, you must add the Title/Subtitle in the option table. In this case, we would expect that our callback is only called when we click on the bubble! but NO :( The callback is always called when you click on the marker. Clicking on the bubble has no effect in our test. 

 

This is why that in our code, when a marker is click on we directly go to another page. It is not nice and it is not the best workflow but we had no choice for the time being. We have asked for a better implementation and we are waiting from them to enhance this feature to match a normal workflow and user expectation. We should be able to customize the bubble and put a nice button into it.

 

We should unite to have Corona fix this as in my opinion this is not good at all.



[TOPIC: post.html]
#19

ksan

[GLOBAL: userInfoPane.html]
ksan
  • Corona Geek

  • 2,795 posts
  • Corona SDK

I completely agree with you. As expressed in my other thread the implementation is very weak and inconsistent to the point that the bubbles are not usable as they are.

 

In my implementation the bubbles are essential. There are 100+ markers which are all points of interest and people will go tapping on the markers at first to see the bubbles and if they wish to explore further they will tap on the bubbles to get to the detail. Going from marker direct to detail is not that usable. Just to let you know I managed to get this behavior in a little convoluted way. Counting taps and ignoring first tap but going to the detail on second tap does the trick although in a very crude way. Let me know if you wish to see this code although I warn you it is pretty silly.

 

Meanwhile the IOS and Android behavior is not consistent in how the taps in empty spots are handled. On IOS a tap in empty spot of the map closes all bubbles which is a good outcome for me. On Android when you tap on an empty spot nothing happens. The bubbles are not closed until you tap the X on them. The X is an Android only feature... 

 

I sincerely hope that Corona Labs does improve the mapView in future updates. Currently it is feature incomplete and buggy. 



[TOPIC: post.html]
#20

nmichaud

[GLOBAL: userInfoPane.html]
nmichaud
  • Contributor

  • 492 posts
  • Corona SDK

I would be very interested to see how you did manage to do that if you are willing to share that code. 



[TOPIC: post.html]
#21

ksan

[GLOBAL: userInfoPane.html]
ksan
  • Corona Geek

  • 2,795 posts
  • Corona SDK

Sure. Here it is. Basically I keep track of which marker is tapped last and how many times it was tapped in 2 global variables. If the same marker is tapped 2 times (or more) I jump to the detail view. This way I find that I can show the bubble but there are inconsistencies in this implementation as well. Maybe you can improve it if you like it. Good luck. 

 

PS. Ignore some additional / unused variables. I've been trying lots of things in there. 

 

local markerTapped = false
local markerId
local markersTable = {}
local chosenMarker
local markerTapCount = 0
local currentMarkerID = nil


local function markerListener(event)
    
    markerId = event.markerId
    
    if currentMarkerID ~= markerId then
        currentMarkerID = markerId
        markerTapCount = 0
    end
    
    markerTapCount = markerTapCount + 1
          
    if markersTable[markerId] and markerTapCount >= 2 then

        chosenMarker = markersTable[markerId].landmarkID

            local options =
            {
                effect = "slideLeft",
                isModal=true,
                params = { var1 = chosenMarker }          
            }
            storyboard.gotoScene( "scn_landmark_details", options )          
    end
end


[TOPIC: post.html]
#22

nmichaud

[GLOBAL: userInfoPane.html]
nmichaud
  • Contributor

  • 492 posts
  • Corona SDK

Thanks we will give it a try and give you some feedback. But quick question. By looking at the code, it is when you click a second time on the same marker that you will go to your scene ? Clicking on the bubble itself as no effect, right ?



[TOPIC: post.html]
#23

ksan

[GLOBAL: userInfoPane.html]
ksan
  • Corona Geek

  • 2,795 posts
  • Corona SDK

Clicking the bubble triggers the listener for me. At least on IOS. This is on 2187 as of today. No guarantees what tomorrow might hold for us!   ;)

 

Edit : cleaned up the code a little above.

 

Edit 2 : the length of the tap on bubble and the marker seem to have a different effect on the listener. A quick peck vs a longer tap and release. Experiment to see how it works on your side. 



[TOPIC: post.html]
#24

nmichaud

[GLOBAL: userInfoPane.html]
nmichaud
  • Contributor

  • 492 posts
  • Corona SDK

Ok, we will try it under iOS and will get back to you soon



[TOPIC: post.html]
#25

henrik5

[GLOBAL: userInfoPane.html]
henrik5
  • Contributor

  • 251 posts
  • Corona SDK

No, I don't make notes manually when filing a bug. I trust the team got the bug. (Or a lot of time and my test info has been lost.)

It would be great if you have found a workaround, but I think you have to set it up to work repeatedly and I suspect you may find that waiting doesn't remove the bug. At least when I tested I would have it working for a few taps and thinking I fixed it. You need to zoom in/out to see the coordinate systems mismatch.




[topic_controls]
Page 1 of 2 1 2
 
[/topic_controls]