Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to change transparency on TileOverlay on Android #565

Open
dlcole opened this issue Jan 18, 2024 · 2 comments
Open

Unable to change transparency on TileOverlay on Android #565

dlcole opened this issue Jan 18, 2024 · 2 comments

Comments

@dlcole
Copy link
Contributor

dlcole commented Jan 18, 2024

I'm migrating from the kefahB/nativescript-google-maps plugin to @nativescript/google-maps.
My app animates weather radar by composing an array of TileOverlays and then iteratively changing the TileOverlay's transparency to hide one overlay and display the next.

While transparency can be specified in the TileOverlayOptions when creating a TileOverlay, it can't be modified directly afterwards. Instead, you have to use native methods, such as on iOS:

tileOverlay.native.opacity = 1.0;  // display tileOverlay

On Android, there's:

tileOverlay.native.setTransparency(0.0);  // display tileOverlay

But this seems to have no effect. I can see in the debugger and via tileOverlay.native.getTransparency() that the native TileOverlay's transparency property has indeed been changed, but there is no change in the display.

@dlcole
Copy link
Contributor Author

dlcole commented Apr 9, 2024

I've had a chance to look at this further... setting the tileOverlay transparency via tileOverlay.native.setTransparency() does indeed work. The problem in my case is with the tileProvider. All the tiles were the same, thus alternating the transparencies of the tileOverlays had no visible effect, since there was no change in the image.

What I'm doing is animating weather radar on a map, getting the 6 most recent radar images and alternating the transparencies to create the animation. My code was based on this question - note the different tileProvider implementations between iOS and Android.

This code works just fine on iOS, and is similar to the code referenced above:

import { GoogleMap, MapView, MarkerOptions, CameraUpdate, UrlTileProvider } from '@nativescript/google-maps';

for (let timestamp of timestamps) {

      const tileProvider = new UrlTileProvider((x, y, z) => {
        return `https://tilecache.rainviewer.com/v2/radar/${timestamp}/256/${z}/${x}/${y}/4/1_0.png`;
      }, 256);

    ...
}

The same code on Android returns images that are all identical. I believe it has to do with how the URL is composed in the tileProvider callback, and that the same timestamp is used for all images. I suspect this because it would explain all the images being the same, and because the sample code for Android referenced above has a specific method for setting the url to be returned, setUrl() and which is then referenced by the getTileUrl(x,y,z) method.

When I try using this code with the @nativescript/google-maps plugin, I get the error

Error: java.lang.NullPointerException: tileProvider must not be null.

when I try to add the tileOverlay:

let newTileOverlay = map.addTileOverlay(tileOverlayOptions);

So, the question now becomes is there a way to modify the url returned by the tileProvider callback on Android?

@dlcole
Copy link
Contributor Author

dlcole commented Apr 10, 2024

In an effort to answer my question above, I'm attempting to patch the UrlTileProvider class in @nativescript/google-maps/index.android.js by adding a setUrl method and then referencing the specified url in the getTileUrl method, similar to what I was doing on Android with the prior plugin. Here's the code:

export class UrlTileProvider extends TileProvider {
  constructor(callback, size = 256) {
      super(null);
      this._callback = callback;
      this._url = "";
      const ref = new WeakRef(this);
      const provider = com.google.android.gms.maps.model.UrlTileProvider.extend({
          setUrl(url) {
              const owner = ref.get();  // returns undefined 
              owner._url = url;
            },
          getTileUrl(x, y, zoom) {
              const owner = ref.get();
              if (owner) {
                  if (owner._url.length > 0) {
                      var url = owner._url.replace('{x}', x).replace('{y}', y).replace('{z}', zoom);
                      return new java.net.URL(url);
                  }
                  else {
                      return new java.net.URL(owner._callback(x, y, zoom) || null);
                  }

              }
              return null;
          },
      });
      this._native = new provider(size, size);
  }
  get native() {
      return this._native;
  }
}

The problem is that in setUrl, ref.get() returns undefined, even though it resolves successfully in getTileUrl. I suspect this is simply a WeakRef issue, but I'm not sure how to proceed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant