Description:
Using our test app, I encountered a null pointer exception when using the removeAnnotations() method.
I was unable to find an injection point, but tested my version 2.1.0 (might have been version 2.1.1 and overwrote 2.1.0 due to previous bug)
Sample code:
Use this excerpt or module sample code
// Modified QE version of module sample code.
var MapModule = require('ti.map');
var win = Ti.UI.createWindow({backgroundColor:'black'});
var table = Ti.UI.createTableView();
var tableData = [];
var multiMapRow = Ti.UI.createTableViewRow({title: 'Multi Map'});
tableData.push(multiMapRow);
multiMapRow.addEventListener('click', function(e) {
multiMapTest();
});
var annotationRow = Ti.UI.createTableViewRow({title:'Annotation Test'});
tableData.push(annotationRow);
annotationRow.addEventListener('click', function(e) {
annotationTest();
});
table.setData(tableData);
win.add(table);
win.open();
/************************************************************************************/
/************************************************************************************/
//ANNOTATIONS
/************************************************************************************/
function annotationTest() {
var win = Ti.UI.createWindow({fullscreen: false});
var anno = MapModule.createAnnotation({latitude: -33.87365, image: 'map_pin.png', longitude: 151.20689, title: "Sydney", subtitle: "Sydney is quite chill", draggable: true});
var anno2 = MapModule.createAnnotation({latitude: -33.86365, pincolor: MapModule.ANNOTATION_BLUE, longitude: 151.21689, title: "Anno2", subtitle: "Blue Draggable", draggable: true});
var anno3 = MapModule.createAnnotation({latitude: -33.85365, longitude: 151.20689, title: "Anno3", subtitle: "Not Draggable", draggable: false});
var anno4 = MapModule.createAnnotation({latitude: -33.86365, longitude: 151.22689, title: "Anno4", subtitle: "Draggable", draggable: true});
Ti.API.info ("====> Latitude should be: -33.87365 and is: " + anno.latitude);
Ti.API.info ("====> Longitude should be: 151.20689 and is: " + anno.longitude);
Ti.API.info ("====> Title should be Sydney and is: " + anno.title);
Ti.API.info ("====> Draggable should be true and is: " + anno.draggable);
Ti.API.info ("====> Draggable should be true and is: " + anno.draggable);
var map = MapModule.createView({
userLocation: true,
mapType: MapModule.NORMAL_TYPE,
animate: true,
annotations: [anno, anno2, anno4],
region: {latitude: -33.87365, longitude: 151.20689, latitudeDelta: 0.1, longitudeDelta: 0.1 }, //Sydney
top: '30%'
});
Ti.API.info("====> userLocation: " + map.userLocation);
win.add(map);
var button = Ti.UI.createButton({top: 0, left: 0, title: "Go Mt. View"});
button.addEventListener('click', function(e) {
map.region = {latitude: 37.3689, longitude: -122.0353, latitudeDelta: 0.1, longitudeDelta: 0.1 }; //Mountain View
});
var button2 = Ti.UI.createButton({top: '10%', title: "add anno3"});
button2.addEventListener('click', function(e) {
map.addAnnotation(anno3);
});
var button3 = Ti.UI.createButton({top: 0, title: "rm anno3"});
button3.addEventListener('click', function(e) {
map.removeAnnotation(anno3);
});
var button4 = Ti.UI.createButton({top: '20%', title: "rm all"});
button4.addEventListener('click', function(e) {
map.removeAllAnnotations();
});
var button5 = Ti.UI.createButton({top: '10%', left: 0, title: "remove annos"});
button5.addEventListener('click', function(e) {
Ti.API.info(anno.getTitle());
map.removeAnnotations(["Sydney", anno2]);
});
var button6 = Ti.UI.createButton({top: 0, right: 0, title: "select anno2"});
button6.addEventListener('click', function(e) {
map.selectAnnotation(anno2);
});
var button7 = Ti.UI.createButton({top: '10%', right: 0, title: "desel anno2"});
button7.addEventListener('click', function(e) {
map.deselectAnnotation(anno2);
});
var button8 = Ti.UI.createButton({top: '20%', right: 0, title: "modify anno2"});
button8.addEventListener('click', function(e) {
anno2.title = "Hello";
anno2.subtitle = "Hi there.";
anno2.longitude = 151.27689;
});
var button9 = Ti.UI.createButton({top: '20%', left: 0, title: "Add all"});
button9.addEventListener('click', function(e) {
// this is currently broken TIMOB-12837
//map.addAnnotations([anno, anno2, anno3, anno4]);
});
win.add(button);
win.add(button2);
win.add(button3);
win.add(button4);
win.add(button5);
win.add(button6);
win.add(button7);
win.add(button8);
win.add(button9);
win.open();
}
Steps to reproduce:
1) Create app with google map key in tiapp, be sure to include module.
2) Run the app on device
3) On the annotation test page, click "remove annos" button
Result:
Null pointer exception as so:
E/TiApplication(11583): (main) [26120,26120] Sending event: exception on thread: main msg:java.lang.NullPointerException; Titanium 3.1.1,2013/06/15 16:10,f7592c1
E/TiApplication(11583): java.lang.NullPointerException
E/TiApplication(11583): at ti.map.TiUIMapView.findMarkerByTitle(TiUIMapView.java:304)
E/TiApplication(11583): at ti.map.ViewProxy.isAnnotationValid(ViewProxy.java:242)
E/TiApplication(11583): at ti.map.ViewProxy.removeAnnotation(ViewProxy.java:252)
E/TiApplication(11583): at ti.map.ViewProxy.handleRemoveAnnotations(ViewProxy.java:275)
E/TiApplication(11583): at ti.map.ViewProxy.handleMessage(ViewProxy.java:100)
E/TiApplication(11583): at android.os.Handler.dispatchMessage(Handler.java:95)
E/TiApplication(11583): at android.os.Looper.loop(Looper.java:137)
E/TiApplication(11583): at android.app.ActivityThread.main(ActivityThread.java:4898)
E/TiApplication(11583): at java.lang.reflect.Method.invokeNative(Native Method)
E/TiApplication(11583): at java.lang.reflect.Method.invoke(Method.java:511)
E/TiApplication(11583): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1008)
E/TiApplication(11583): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:775)
E/TiApplication(11583): at dalvik.system.NativeStart.main(Native Method)
I/AudioMixer( 1973): setParameter(TRACK, FORMAT, 0x1)
E/AudioMixer( 1973): MOON > checkSEC_PCM ++ 1
I/AudioHardwareTinyALSA( 1973): AudioStreamOutALSA::write setDevice
D/AudioHardwareTinyALSA( 1973): OutALSA::setDevice: mode = 0, newDevice=0x2, currentDevice=0x2 ,force= 0
D/AudioHardwareTinyALSA( 1973): OutALSA::setDevice: mDevice 0x2, newDevice = 0x2
D/AudioHardwareTinyALSA( 1973): setOutputVolume
D/TinyUCM ( 1973): setModifier Normal, en=1
I/AudioHardwareTinyALSA( 1973): OutALSA::setDevice: mHandle NULL mode[0], Device[00000002]
I/AudioHardwareTinyALSA( 1973): Open: mDefaults->direction=0 device=0
D/AudioHardwareTinyALSA( 1973): Channel: 2, Samplerate: 44100, Format: 0, Peroid Size: 1024, Period Count: 4
D/AudioHardwareTinyALSA( 1973): setPcmInterface: Stream=0x1, iSamplerate=16000++
D/AudioHardwareTinyALSA( 1973): setPcmInterface--
E/AndroidRuntime(11583): FATAL EXCEPTION: main
E/AndroidRuntime(11583): java.lang.NullPointerException
E/AndroidRuntime(11583): at ti.map.TiUIMapView.findMarkerByTitle(TiUIMapView.java:304)
E/AndroidRuntime(11583): at ti.map.ViewProxy.isAnnotationValid(ViewProxy.java:242)
E/AndroidRuntime(11583): at ti.map.ViewProxy.removeAnnotation(ViewProxy.java:252)
E/AndroidRuntime(11583): at ti.map.ViewProxy.handleRemoveAnnotations(ViewProxy.java:275)
E/AndroidRuntime(11583): at ti.map.ViewProxy.handleMessage(ViewProxy.java:100)
E/AndroidRuntime(11583): at android.os.Handler.dispatchMessage(Handler.java:95)
E/AndroidRuntime(11583): at android.os.Looper.loop(Looper.java:137)
E/AndroidRuntime(11583): at android.app.ActivityThread.main(ActivityThread.java:4898)
E/AndroidRuntime(11583): at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime(11583): at java.lang.reflect.Method.invoke(Method.java:511)
E/AndroidRuntime(11583): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1008)
E/AndroidRuntime(11583): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:775)
E/AndroidRuntime(11583): at dalvik.system.NativeStart.main(Native Method)
E/android.os.Debug( 2387): !@Dumpstate > dumpstate -k -t -z -d -o /data/log/dumpstate_app_error
I/dumpstate(11943): begin
Expected Result:
All annotations on screen removed
I went through the test case and Mapv2 application. Tried multiple scenarios and able to replicate this issue. Please find below the details about this issue - Scenario 1: Passing the array of Annotation reference to removeAnnotations() map.removeAnnotations([anno,anno4]); // It works perfectly fine and annotations are removed from MapVIew. Scenario 2: Passing the array of Annotation Title to removeAnnotations() map.removeAnnotations(["Sydney",anno4]); // It throws null pointer exception. java.lang.NullPointerException at ti.map.TiUIMapView.findMarkerByTitle(TiUIMapView.java:304) Scenario 3: Passing the array of Annotation Title using getTitle() method to removeAnnotations() var anno = MapModule.createAnnotation({latitude: -33.87365, image: 'map_pin.png', longitude: 151.20689, title: "Sydney", subtitle: "Sydney is quite chill", draggable: true}); map.removeAnnotations([anno.getTitle(),anno4]); // It throws error as E/MapViewProxy(1600): (main) [8707,8707] Unsupported argument type for removeAnnotation This issue has introduced on 3rd April with pull request 95. https://github.com/appcelerator/titanium_modules/pull/95/ Device : Google Nexus Phone , Android version : 4.0.4 SDK : 3.1.1.GA Appcelerator Studio, build: 3.1.1.201306131423 OS : MAC OSX 10.7.5 Map Module: 2.1.0
PR: https://github.com/appcelerator/titanium_modules/pull/122
Verified the fix.We do not get any NPE when using removeAnnotations(). Closing. Environment: Appcel Studio : 3.2.0.201311200357 Ti SDK : 3.2.0.v20131119142443 Mac OSX : 10.8.5 Alloy : 1.3.0 CLI - 3.2.0-alpha Device: Samsung Galaxy S4 running android 4.2.2