Android Google Maps Offline - my location is not shown - android

I am trying to use Google Maps for Android, offline (always and forever).
Surprisingly, I can't find any question here that asks or solves this issue specifically.
When I use a new offline phone, both my app and Google Maps show a blank map (dah, no map loaded) and 'my' location blue dot is not shown. Well, actually, no marker is shown.
To Reproduce
Restore any Android phone to its factory settings
Enable location services (GPS, without connecting to the internet at any stage)
Open the Google Maps app
--> See that there is no 'my location' blue marker, although when you long click on the screen, the app shows its coordinates (meaning, GPS does work, but the map doesn't show it)
Technical Symptoms
Even when I load offline maps (.mbtiles format, custom ones, not Google's) they're still not shown (nor the markers). It's like Google put some code like this:
if (no internet) hideAllViews().
Note that once I connect the phone to the internet, our custom tiles do work, even if I later turn the phone offline.
I can interact with the map (long click to view the clicked location, for example, which shows that my GPS location indeed works), but that's about it (until I connect the phone to the internet, from which point I can turn it offline again but with everything surprisingly working).
Code Example - a simplified version
//build.gradle:
implementation 'com.google.android.gms:play-services-maps:17.0.0'
//MapActivity.kt
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.MapView
import com.google.android.gms.maps.MapsInitializer
class MapActivity : AppCompatActivity {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.map_activity)
val mapFragment = supportFragmentManager.findFragmentByTag(MAP_FRAGMENT_TAG) as MapFragment?
?: MapFragment().also {
supportFragmentManager.beginTransaction().add(R.id.map, it, MAP_FRAGMENT_TAG).commit()
}
mapFragment.getMapAsync(::onMapReady)
mapFragment.retainInstance = true
}
private fun onMapReady(map: GoogleMap) {
map.isMyLocationEnabled = true
map.uiSettings.isMyLocationButtonEnabled = true
Log.d("GoogleMap", "Map should be ready and visible with my-location marker shown, if phone's GPS is enabled")
}
}
I hope someone here knows a trick or worked at Google and can shed some light on this.
Thank you!
As opposed to most similar questions, I do know how to make this work (internet...) but am asking specifically about a use case where a new phone can never be connected to the internet - not even one time for one second.
I am familiar with other offline maps services, but am trying to solve this with Google's maps, at least for now

It is not possible to load the API without connecting to the internet first since it was designed to be used online(As of now), so this is Working As Intended.
Please note that using Maps SDK for android requires an internet connection first to load because it checks the API key. Then you can use the Map offline for a certain period of time(there's no definite period of time for offline functionality that requires you to be online again)
But there are customers who are also interested in this functionality, so there is an ongoing entry for it in the Google Issue Tracker that was created since 2013 to let the API users be aware of this feature request.
You can view and star the feature request here:
https://issuetracker.google.com/35823181
Please note that the Issue Tracker entry above is the authoritative source for public information regarding the aforementioned feature requests, and all publicly-relevant updates will be posted there.

Related

Flutter - Weird redrawing

I have a weird behavior in my app. I have the google_maps_flutter plugin with the flutter_typeahead plugin which is used as an autocomplete address search.
When the user login in the app, the app only stores the user data in the internal database and the map is loaded, the app gets the current user location and set the map in such location, and then the user can use the autocomplete address search to type any address and load the results coming from Google Api Directions.
The strange thing here is, when I tap in the autocomplete, the page or the map is redrawn/reloaded and I can't do anything as you can see in this link:
App after just login.
But the most weird is, if I just exit from the app (no logout) with SystemNavigator.pop(animated: true);, and after that I open again the app, this behavior is gone and the app works, like this video: App reopened.
I don't have a clue why, and I can't post the code here, first, because it's a production app and second, because the minimal code is so extense to publish it here.
It's a little similar to my Github issue: https://github.com/flutter/flutter/issues/78638 but here, although I'm getting in realtime the user location, the map isn't moving because I'm in the same place al the time.
EDIT: In the dispose method for the StatefulWidget I set a debug print to check when this is disposed and when I tap on the typeahead plugin, I see the StatefulWidget (where is the map and the typeahead) is disposed, when I just login, but it isn't present when I reopen the app.

How to use Google Maps API offline in Angular/Ionic App

I have an Angular 12 Ionic app that is using the Google Maps API via #angular/google-maps package (https://github.com/angular/components/tree/master/src/google-maps#readme). The application we are building will be used in areas where internet access can be spotty at best. We are attempting to maintain functionality of the map when internet is lost. IE, potentially cache or store the loaded map locally to reference should we go offline.
We are expecting the user to be online when we initialize the map and load any polylines & markers
Should the user then go offline, and navigate around the app, when coming back to the map we would like to show the map, polylines and markers that were previously loaded.
What currently is happening is the the component is being destroyed and then reloaded when navigated back causing a reload of the map which cannot happen because we are offline. However, if we were able to cache or locally store that map, then we can load it from the cache/local until the user comes back online.
Using the package described above we are looking at trying to serialize the google.maps object to json for storage, however it is causing an issue.
let mapTest: google.maps.Map;
const center: google.maps.LatLngLiteral = { lat: centerPoint.lat, lng: centerPoint.lng };
mapTest = new google.maps.Map(document.getElementById('map') as HTMLElement, {
center,
zoom: 11
});
This is a basic typescript implementation as provided by the Google API Documentation (https://developers.google.com/maps/documentation/javascript/using-typescript). When we attempt to stringify the map we get the following error
Same error shows if we stringify mapTest.data.
Question is, is there anything we can do to locally store the google.map object or the google.map.data object? This ultimately will be put onto an Android device using Ionic, is something like this possible with Native Android maps? Or is this just not a feasible task at all
The Google Maps JavaScript API cannot be used offline.
See feature request: API feature to download a map for offline use.

React native queries GPS coordinates and gives timeout

We have the next problem:
We are consulting the gps location in order to get a list that contains only those that are close in a radius, but when consulting the GPS it gives us timeout after at leat 40 seconds of waiting.
The problem especially occurs in Android with a Xiaomi Redmi 8 in industrial environments, with less connection than usual or on the move, they donĀ“t have access to LTE all the time.
We use the library # react-native-community / geolocation or navigation.position
Can you help us with any other library or strategy to obtain GPS position that does not consists in the gps wacthing changes on its position all the time? something like getting it on the background..
Code
Geolocation.getCurrentPosition(
position => {
// process the position
},
error => {
console.log(error);
}, {
timeout: 40000,
maximumAge: 0
}
);
As cited from library's github page:
Currently, on Android, this uses the android.location API. This API is not recommended by Google because it is less accurate and slower than the recommended Google Location Services API. This is something that we want to change in the near future https://github.com/react-native-community/react-native-geolocation/issues/6.
There also are some library suggestions in the readme, that actually use Google Location Services API. I've used react-native-location, but this package isn't actively maintained anymore, so I switched to react-native-geolocation-service, which has a very similar API to what you're already using, more specifically the getCurrentPosition.
Perhaps you should give it a try.
react-native-community/geolocation does not utilize the more accurate Google Location Services API, as stated in readme
The recommended library for GPS location (and the one I used) for RN Android is react-native-geolocation-service. Its Readme also mentions a timeout issue which makes me wonder if it is the same as yours:
This library is created in an attempt to fix the location timeout
issue on android with the react-native's current implementation of
Geolocation API. This library tries to solve the issue by using Google
Play Service's new FusedLocationProviderClient API, which Google
strongly recommends over android's default framework location API. It
automatically decides which provider to use based on your request
configuration and also prompts you to change the location mode if it
doesn't satisfy your current request configuration.
So if I were you I would give it a go. The API is meant to be a drop-in replacement for the library you used so migrating should be just a matter of changing packages.

Maps Android API doesn't work offline without online initialization

I'm using Maps Android API in the offline mode extensively in travel apps I build. On the first app launch, I download all the tiles I need so that they're available later in the field without the Internet. Everything works great, but I noticed that the Maps API does require Internet connection on its first use after app installation. The framework probably performs API key validation to make sure it's legit.
Since my fragments containing com.google.android.gms.maps.MapView are not displayed on the first screen, there's a risk a user downloads the map for offline use in a hotel, goes into the wild, and... kaboom! - map is not displayed.
How to initialize Android Map framework so that maps are available later when there's no connection? Is there a way to skip online key validation?
After some experimenting I found out a simple solution.
So, first, in my first activity layout (it's a host activity for all my fragments) I added the following zero-sized invisible MapView:
<com.google.android.gms.maps.MapView
android:id="#+id/dummyMapViewToInitForOfflineUse"
android:layout_width="0dp"
android:layout_height="0dp"
android:visibility="invisible"
/>
Then, in the activity code, I added the following method:
private void initGoogleMapFrameworkToMakeItUsableOfflineLater() {
dummyMapViewToInitForOfflineUse.onCreate(new Bundle());
dummyMapViewToInitForOfflineUse.getMapAsync(ignored -> {
Timber.d("GoogleMap framework initialized and ready to use offline later");
});
}
You can call it in onCreate as well as at any other reasonable moment (I use AndroidAnnotations, so I called it from my init method annotated with #AfterViews). Obvoiusly, if you don't use AndroidAnnotations or other view binding framework, you need to perform findViewById(R.id.dummyMapViewToInitForOfflineUse).
If you are aiming at caching google map's tiles for offline use then you may be violating their terms,You are first required to purchase their enterprise Maps API Premier, check this link How to cache Google map tiles for offline usage?

Awareness API - Place type home

On google awareness API Guides page there is mention about Context types.
Contextual data includes sensor-derived data such as location
(lat/lng), place (home, work, coffee shop)
However, on reference page with Places type Place reference, there is no mention about Home type. Is there a way to find out if user is at home (of course if he has it set up in his google settings)?
A bit late to the party, but now that Google's Awareness API has deprecated Places, you can use the NumberEight SDK as an alternative. One bonus is that it works on iOS too.
It performs a wide variety of context recognition tasks including:
Real-time physical activity detection
Current place categories (including Work and Home, which can trigger even without GPS)
Motion detection
Reachability
Local weather
It can also record user context for reports and analysis via the online portal.
To quickly check when a user is at home in Kotlin, you would write:
val ne = NumberEight()
ne.onPlaceUpdated { glimpse ->
val place = glimpse.mostProbable
if (place.context.home == Knowledge.AtPlaceContext) {
Log.d("MyApp", "User is at home!")
}
}
Here are some iOS and Android example projects.
Disclosure: I'm one of the developers.

Categories

Resources