mapsplugin / cordova-plugin-googlemaps

Google Maps plugin for Cordova
Apache License 2.0
1.66k stars 913 forks source link

Crash when setting icon on marker from file #537

Closed cosmith closed 8 years ago

cosmith commented 9 years ago

Hi, I get a crash when using a custom image as a marker on Android.

I'm using Cordova 5.0.0 so that may be part of the issue.

I've tried using file:///, using www/, and using cdvfile:// and it crashes every time. It works with http:// though.

Crash logs using www/

/AndroidRuntime(19049): FATAL EXCEPTION: AsyncTask #2
E/AndroidRuntime(19049): Process: com.example.example, PID: 19049
E/AndroidRuntime(19049): java.lang.RuntimeException: An error occured while executing doInBackground()
E/AndroidRuntime(19049):    at android.os.AsyncTask$3.done(AsyncTask.java:304)
E/AndroidRuntime(19049):    at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
E/AndroidRuntime(19049):    at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
E/AndroidRuntime(19049):    at java.util.concurrent.FutureTask.run(FutureTask.java:242)
E/AndroidRuntime(19049):    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
E/AndroidRuntime(19049):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
E/AndroidRuntime(19049):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
E/AndroidRuntime(19049):    at java.lang.Thread.run(Thread.java:818)
E/AndroidRuntime(19049): Caused by: java.lang.NullPointerException: Attempt to invoke interface method 'android.app.Activity org.apache.cordova.CordovaInterface.getActivity()' on a null object reference
E/AndroidRuntime(19049):    at plugin.google.maps.PluginMarker$7.doInBackground(PluginMarker.java:716)
E/AndroidRuntime(19049):    at plugin.google.maps.PluginMarker$7.doInBackground(PluginMarker.java:683)
E/AndroidRuntime(19049):    at android.os.AsyncTask$2.call(AsyncTask.java:292)
E/AndroidRuntime(19049):    at java.util.concurrent.FutureTask.run(FutureTask.java:237)
E/AndroidRuntime(19049):    ... 4 more

Crash logs using file:///:

E/AndroidRuntime(24243): FATAL EXCEPTION: AsyncTask #2
E/AndroidRuntime(24243): Process: com.example.example, PID: 24243
E/AndroidRuntime(24243): java.lang.RuntimeException: An error occured while executing doInBackground()
E/AndroidRuntime(24243):    at android.os.AsyncTask$3.done(AsyncTask.java:304)
E/AndroidRuntime(24243):    at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
E/AndroidRuntime(24243):    at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
E/AndroidRuntime(24243):    at java.util.concurrent.FutureTask.run(FutureTask.java:242)
E/AndroidRuntime(24243):    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
E/AndroidRuntime(24243):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
E/AndroidRuntime(24243):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
E/AndroidRuntime(24243):    at java.lang.Thread.run(Thread.java:818)
E/AndroidRuntime(24243): Caused by: java.lang.IllegalStateException: Not on the main thread
E/AndroidRuntime(24243):    at com.google.l.a.ce.b(Unknown Source)
E/AndroidRuntime(24243):    at com.google.maps.api.android.lib6.d.ct.a(Unknown Source)
E/AndroidRuntime(24243):    at com.google.maps.api.android.lib6.d.aq.b(Unknown Source)
E/AndroidRuntime(24243):    at com.google.android.gms.maps.model.internal.t.onTransact(SourceFile:169)
E/AndroidRuntime(24243):    at android.os.Binder.transact(Binder.java:380)
E/AndroidRuntime(24243):    at com.google.android.gms.maps.model.internal.zzl$zza$zza.setVisible(Unknown Source)
E/AndroidRuntime(24243):    at com.google.android.gms.maps.model.Marker.setVisible(Unknown Source)
E/AndroidRuntime(24243):    at plugin.google.maps.PluginMarker$1.onPostExecute(PluginMarker.java:161)
E/AndroidRuntime(24243):    at plugin.google.maps.PluginMarker$7.doInBackground(PluginMarker.java:728)
E/AndroidRuntime(24243):    at plugin.google.maps.PluginMarker$7.doInBackground(PluginMarker.java:683)
E/AndroidRuntime(24243):    at android.os.AsyncTask$2.call(AsyncTask.java:292)
E/AndroidRuntime(24243):    at java.util.concurrent.FutureTask.run(FutureTask.java:237)
E/AndroidRuntime(24243):    ... 4 more

My directory structure is:

main-app/
    platform/
    plugins/
    www/
        js/
        img/
            marker.png

Relevant js code:

        var div = this.refs.mapCanvas.getDOMNode();

        // Initialize the map view
        var mapObj = plugin.google.maps.Map.getMap(div);
        mapObj.addEventListener(plugin.google.maps.event.MAP_READY, (map) => {
            Server.get("/markers")
                .then((res) => {
                    for (let marker of res.results) {
                        var [lat, lng] = $.map(marker.position.split(","), parseFloat);
                        var position = new plugin.google.maps.LatLng(lat, lng);
                        map.addMarker({
                            position: position,
                            title: marker.name,
                            icon: "file:///img/marker.png"
                        });
                    }
                });
        });

Any ideas on what might be causing this?

cosmith commented 9 years ago

The app doesn't crash if I use icon: "img/marker.png" but the marker icon does not appear either.

thim81 commented 8 years ago

+1 We have identical the same behaviour.

The app crashes when using the real path to the icon. The behavior only happens with Android, on iOS the icon image is shown.

We have same folder structure for the image location, same JS and same issue.

Code:

map.addMarker({
                            position: position,
                            title: 'Welcome,
                            icon: "www/img/marker.png"
                        });

Environment: Ionic 1.0, Cordova 5.0.0.

Correction: We tried with HTTP and this seems to work perfectly. So we will use this for now.

@cosmith thanks for the issue and the suggestion for using HTTP

BlueFyre commented 8 years ago

I am having this same issue using addKmlOverlay

leandro-shifteight commented 8 years ago

I am getting the same error.

FATAL EXCEPTION: AsyncTask #1 Process:, PID: 7935 java.lang.RuntimeException: An error occured while executing doInBackground() at android.os.AsyncTask$3.done(AsyncTask.java:300) at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355) at java.util.concurrent.FutureTask.setException(FutureTask.java:222) at java.util.concurrent.FutureTask.run(FutureTask.java:242) at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) at java.lang.Thread.run(Thread.java:818) Caused by: java.lang.NullPointerException: Attempt to invoke interface method 'android.app.Activity org.apache.cordova.CordovaInterface.getActivity()' on a null object reference at plugin.google.maps.PluginMarker$7.doInBackground(PluginMarker.java:716) at plugin.google.maps.PluginMarker$7.doInBackground(PluginMarker.java:683) at android.os.AsyncTask$2.call(AsyncTask.java:288) at java.util.concurrent.FutureTask.run(FutureTask.java:237) ... 4 more

Any idea? I am using Cordova 5 too with https://github.com/Nipher/phonegap-googlemaps-plugin fork, It was working ok with the master branch here but is probably something with Cordova Android new version.

ghost commented 8 years ago

The error log obviously says org.apache.cordova.CordovaInterface.getActivity()' on a null object reference at line 716 in PluginMarker.java.

It means PluginMarker.this.cordova.getActivity() is null, but the code uses this value.

leandroz commented 8 years ago

@masashiGMS yep, the problem is why. I am not familiar with Java, but for what I saw in other plugins and the classes in the new Android version it should be working. I am thinking that the problem is with AsyncTask but I really don't know. Someone?

cosmith commented 8 years ago

I took some time to look into this this morning and it is related to the privateInitialize method that was not called properly (the signature changed in Cordova 4.0x adding the service name argument, see https://github.com/apache/cordova-android/blob/4.0.x/framework/src/org/apache/cordova/CordovaPlugin.java#L48)

You can find a fix here: https://github.com/cosmith/phonegap-googlemaps-plugin/commit/900951bd524b91ed85d53d072764c056131d85a7

I'm not sure how I can get this merged though, what branch should I submit a pull request to?

leandroz commented 8 years ago

Great work!! How did you find it? I will test it tomorrow morning to check if is ok with files. I think you can pull to Nipher repo that has the changes for working with Cordova 5.x.

cosmith commented 8 years ago

Lots of print statements everywhere ;) It was tricky because hidden in a try/catch block that was swallowing everything...

I made a branch here that you can test with

cordova plugin add https://github.com/cosmith/phonegap-googlemaps-plugin#bugfix/icon-crash-cordova-5 --variable API_KEY_FOR_ANDROID="API_KEY" --variable API_KEY_FOR_IOS="API_KEY"
leandroz commented 8 years ago

It worked perfect! Could be great to have the branch cordova 5 with all this changes.

joewoodhouse commented 8 years ago

Yea +1 for getting this onto the cordova 5 branch, really need this.

andresigualada commented 8 years ago

Works for me, too! Thanks!

Luukschoen commented 8 years ago

@wf9a5m75 could this be pulled in to a new build, whenever you have time off course! Good Job @cosmith

dubcanada commented 8 years ago

I merged this with the cordova 5 fixes https://github.com/dubcanada/phonegap-googlemaps-plugin

roberthovhannisyan commented 8 years ago

Great to see this solved! @Menusito could this be merged with your plugin to make it available in PGB

Slavrix commented 8 years ago

+1 for getting this merged into the Menusito build on PGB Or approx eta on the 1.2.6 (if possible)

jheissat commented 8 years ago

Faced the same issue today. Thanks a lot for this. Do you guys know what is the latest / most updated branch of the project ?

hirbod commented 8 years ago

I've just bumped the master to 1.2.7 - it also supports Cordova 5 on android now. Could you give it a try?

Slavrix commented 8 years ago

has the version on the registries been updated to the 1.2.7 version also? I've been using the nipher/phenome/dubcanada fork for the past few months and that's been working well, so if you have those changes in there, it should be working awesomely :D

~edit Whilst it now does work for cordova 5+ on the master, custom icons for markers dont load in (im testing on android), this was solved in the dubcanada build, have a look at it to apply the fixes.

hirbod commented 8 years ago

No, I did not update the registries, you have to pick it from github. Could you send me some diffs, I will update the master.

jvence commented 8 years ago

+1 Thanks that worked great

hirbod commented 8 years ago

Fix is included in the current master. (Tag 1.2.7 and up) This plugin has some more improvements now and fixed deprecated lib support.

You guys should not rely to the forks anymore, as there are not working fine with Cordova 5.2.0 The current version also works perfectly with crosswalk.

lengoyvaerts commented 8 years ago

I still got the crash using the latest version (1.3.2):

java.lang.RuntimeException: An error occured while executing doInBackground()
            at android.os.AsyncTask$3.done(AsyncTask.java:300)
            at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
            at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
            at java.util.concurrent.FutureTask.run(FutureTask.java:242)
            at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
            at java.lang.Thread.run(Thread.java:818)
     Caused by: java.lang.IllegalStateException: Not on the main thread
            at com.google.a.a.ab.b(Unknown Source)
            at com.google.maps.api.android.lib6.c.c.a(Unknown Source)
            at com.google.maps.api.android.lib6.d.af.b(Unknown Source)
            at com.google.android.gms.maps.model.a.p.onTransact(SourceFile:169)
            at android.os.Binder.transact(Binder.java:380)
            at com.google.android.gms.maps.model.internal.zzf$zza$zza.setVisible(Unknown Source)
            at com.google.android.gms.maps.model.Marker.setVisible(Unknown Source)
            at plugin.google.maps.PluginMarker$1.onPostExecute(PluginMarker.java:161)
            at plugin.google.maps.PluginMarker$7.doInBackground(PluginMarker.java:728)
            at plugin.google.maps.PluginMarker$7.doInBackground(PluginMarker.java:683)
            at android.os.AsyncTask$2.call(AsyncTask.java:288)
            at java.util.concurrent.FutureTask.run(FutureTask.java:237)
            at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
            at java.lang.Thread.run(Thread.java:818)

This is the relevant code:

    function onMapReady() {
        $("#map").html(html);
        map.refreshLayout();
        isEnablingLocation = true;
        isLocationEnabled()
    }
    function isLocationEnabled() {
        map.getMyLocation(onLocationSuccess, onLocationError);
    }
    function onLocationSuccess(result) {
        map.animateCamera({
            target: result.latLng,
            zoom: 17
        }, function () {
            map.addMarker({
            position: result.latLng,
            icon: "www/marker.svg"
        });
        })
    }
hirbod commented 8 years ago

Did you install cordova-plugin-file and cordova-plugin-file-transfer ?

lengoyvaerts commented 8 years ago

I don't have the cordova-plugin-file so I'll try installing that one. But I don't know if that's the problem because when I set the icon afterwards using setIcon, it works.

hirbod commented 8 years ago

As far as I know (irc), the file plugin is important (but maybe this is only iOS related), cause we're using class-functions, to retrieve the file

hirbod commented 8 years ago

https://github.com/wf9a5m75/phonegap-googlemaps-plugin/search?utf8=%E2%9C%93&q=CDV

Should be important for both iOS and Android, but I guess only when using cdvfile://

lengoyvaerts commented 8 years ago

Actually I do have it installed, but I looked over it. Also when running without the icon property, it works.

hirbod commented 8 years ago

Could you try setting the Icon with cdvfile:// path? Or file:/// ?

lengoyvaerts commented 8 years ago

The file is in the www folder (for testing purposes) but cdvfile://www/marker.svg is not working. But I get a different error now:

java.lang.RuntimeException: An error occured while executing doInBackground()
            at android.os.AsyncTask$3.done(AsyncTask.java:300)
            at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
            at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
            at java.util.concurrent.FutureTask.run(FutureTask.java:242)
            at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
            at java.lang.Thread.run(Thread.java:818)
     Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.io.File.getAbsolutePath()' on a null object reference
            at plugin.google.maps.PluginUtil.getAbsolutePathFromCDVFilePath(PluginUtil.java:46)
            at plugin.google.maps.PluginMarker$7.doInBackground(PluginMarker.java:692)
            at plugin.google.maps.PluginMarker$7.doInBackground(PluginMarker.java:683)
            at android.os.AsyncTask$2.call(AsyncTask.java:288)
            at java.util.concurrent.FutureTask.run(FutureTask.java:237)
            at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
            at java.lang.Thread.run(Thread.java:818)
hirbod commented 8 years ago

try cdvfile://marker.svg

lengoyvaerts commented 8 years ago

Same error

hirbod commented 8 years ago

please try file:/// syntax or just "marker.svg".

hirbod commented 8 years ago

Ah... I see. You're trying to use a .svg file. I think that is the root problem. You need to pass a png file (just a guess..)

lengoyvaerts commented 8 years ago

I have already tried with a png file but that didn't work either

hirbod commented 8 years ago

Than someone else with more java experience need to dig into this. I'm sorry.

@cosmith any guess?

Slavrix commented 8 years ago

Here what I am doing currently that works fine for me on Android and iOS. and I DONT have cordova-plugin-file installed and it works also.

I have an array in my service predefined so I can keep track of my markers easily (I have around 1000 on the map at a time service is called mapIcons

var icons = {
  car1:'www/img/car1.png',
  car2:'www/img/car2.png',
  car3:'www/img/car3.png'
};
return icons;

To add a marker I use this

    map.addMarker({
      'icon': {
        'url': mapIcons.car1,
        'size': {
          'width': 32,
          'height': 32
        }
      },
      'position': position
    }

rather than just setting the icon to an image. You can get much higher resolution images as your icons this way also.

Also, I've never been able to get an svg to work through the plugin.

cosmith commented 8 years ago

That's how I use it too, with icon: {url, size}. I don't really remember if it was different when setting icon directly.

lengoyvaerts commented 8 years ago

It works now, thanks people!

hirbod commented 8 years ago

Thanks, I really missed that. He just did not provide an appropriate icon object, missing url (and maybe size).

I will reopen this to fix the JS part, maybe I could add more checks before passing to native.

hirbod commented 8 years ago

Just rechecked the docs. Actually, it is correct to set the marker icon as a string, it shouldn't crash. So this is a bug. I'll try to dig this down. Maybe I find a way to fix this or I will change the documentation

hirbod commented 8 years ago

Just checked the code (Android and iOS) https://github.com/wf9a5m75/phonegap-googlemaps-plugin/blob/2d8bd040e7ae9caf7c6a201d172b4f3a9d5aa322/src/android/plugin/google/maps/PluginMarker.java#L663

Seems like "icon" always have to be an object, with url-key. So the documentation is wrong or the codebase changed somewhere. I did not try to debug this, but from what I can see, I need to add some more checks and change the documentation.

@cosmith would you confirm?

cosmith commented 8 years ago

I agree, the docs are outdated. It's not very useful to be able to set the icon url directly anyway.

hirbod commented 8 years ago

Yes. So I will change the documentation, maybe I'll add some extra checks on js-side, to prevent crashes

hirbod commented 8 years ago

changed documentation.

abuinitski commented 8 years ago

The crash happens when you try to assign relative file icon (i.e. 'www/img/map/icon.png') which does not exist.

It calls async task's onPostExecute (PluginMarker.java:738) directly – breaking it's "will execute on main thread" contract – causing a crash.

inplamba commented 7 years ago

Hi All, @Hirbod @wf9a5m75 When i use Icon which is not an image but created with options like Path ,stroke color,offset fill Color,Icon not appeared in this case` $scope.yellowCarIcon = { path:"M17.402,0H5.643C2.526,0,0,3.467,0,6.584v34.804c0,3.116,2.526,5.644,5.643,5.644h11.759c3.116,0,5.644-2.527,5.644-5.644 V6.584C23.044,3.467,20.518,0,17.402,0z M22.057,14.188v11.665l-2.729,0.351v-4.806L22.057,14.188z M20.625,10.773 c-1.016,3.9-2.219,8.51-2.219,8.51H4.638l-2.222-8.51C2.417,10.773,11.3,7.755,20.625,10.773z M3.748,21.713v4.492l-2.73-0.349 V14.502L3.748,21.713z M1.018,37.938V27.579l2.73,0.343v8.196L1.018,37.938z M2.575,40.882l2.218-3.336h13.771l2.219,3.336H2.575z M19.328,35.805v-7.872l2.729-0.355v10.048L19.328,35.805z", scale: .6, strokeColor: '#9c9c9c', strokeWeight: .10, fillOpacity: 1, fillColor: '#000', offset: '100%', rotation: 0, anchor: new google.maps.Point(10, 25) };

map.addMarker({ position: {lat: $scope.carLat, lng: $scope.carLong}, title: "Welecome to \n" + "Cordova GoogleMaps plugin for iOS and Android", snippet: "This plugin is awesome!", // animation: plugin.google.maps.Animation.BOUNCE, // icon: 'www/templates/yellow_car.svg' icon: $scope.yellowCarIcon } })`

Please can anbody help

wf9a5m75 commented 7 years ago

This plugin does not support SVG path.