Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AndroidRuntime: FATAL EXCEPTION: androidmapsapi-ZoomTableManager

Edit: following is the official solution from Google (link)

Summary

Google Maps SDK thread crashes App (ArrayIndexOutOfBoundsException) - Solution Offered

Description

On April 23 2020 starting at 11:30 PDT, Google served for 4 hours an update to the configuration of a Maps mobile component, triggering crashes in Maps SDKs for Android and iOS. Applications on devices that downloaded this version of the configuration (during the outage period) were vulnerable to the crash. Workaround solutions are offered for Maps SDKs for Android and iOS.

Maps SDK for Android

Maps SDK for Android v2 (included in Google Play Services)

The updates to Google Play Services to fix the crash has been published to all devices with Google Play Services version 17.4.55 and newer. There is no change to the version number of Google Play Services on the device after the update is installed. No action is required from developers or end users to receive the updated Maps module; however, developers can verify that the module is present on a given device with the following adb command:

adb shell dumpsys activity provider com.google.android.gms.chimera.container.GmsModuleProvider

You should see the line Module Set ID: maps listed in the Module Sets section.

Module Set ID: maps, Module Set Version: 2015120015120000

The crash rates of Maps SDK for Android v2 are back to normal.

As of now, if you have not updated your app with the client-side code workarounds mentioned below, you do not need to take further action.

If you have already updated your app with the workarounds, you can remove the workaround in a subsequent update of your app (but keeping the workaround is safe).

Premium Plan Maps SDK for Android v2 or Maps SDK for Android v3 beta (static libraries)

If your app uses the Premium Plan Maps SDK for Android v2 or Maps SDK for Android v3 beta (static libraries), and is still experiencing crashes, we still highly recommend you to roll out the workarounds below via an update to your app. As your application is loading a static version of the SDK which is vulnerable to the bad data being stored on some devices, only an update to your application can solve the problem.

Play Store review approvals

If you update your app but experience Play Store review approvals delays, please file a support case with your app’s Package ID: ⁠Contact the support team. Our Support Team will internally escalate your request and expedite the approval.

Negative reviews in the Google Play Store

Some application developers inquired about 1-star reviews in the Google Play Store left by end-users due to crashes. Only comments that violate Google Play's policy [ 1 ] can be removed. You can also flag abusive reviews in the Play Console [ 2 ]. Applications will not be automatically removed from the Google Play store due to negative reviews. It's also worth noting that the calculation of your overall app review rating favors recent reviews, which means that your rating will recover to pre-incident levels over time.

[ 1 ] ⁠Ratings & Review on the Play Store

[ 2 ] ⁠Report inappropriate reviews

Maps SDK for iOS

Crash rates on iOS are back to normal. If your application is still experiencing crashes, you need to update and publish your app with the code workarounds communicated here.

For questions about deploying or expediting your application in the Apple App Store, please contact Apple directly.


With this update, we are closing this issue. Thank you to everyone for your patience. Our team is performing an in-depth internal investigation of this incident; as soon as possible, we will publish our analysis (in approximately a week). In the meantime, if you have any questions, or are still experiencing problems, please ⁠file a support case.

Workarounds:

  • End users on Android can clear the affected app's data (not just the cache).

  • End users on iOS can uninstall then reinstall the affected app(s).

  • App Developers can apply the code workarounds below in order to solve the issue for all their end users.

Code workaround for iOS:

Recommended placement for the code is before GMSServices initialization in the application(_:didFinishLaunchingWithOptions:) (Swift) or application:didFinishLaunchingWithOptions: (Objective-C) method. Specifically:

Swift:

let key = "GoogleMapsServerControlledParamsKey_bug_154855417"
if !UserDefaults.standard.bool(forKey: key) {
    let urls = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)
    if urls.count > 0 {
        let paramUrl = urls[0].appendingPathComponent("com.google.GoogleMaps/ServerControlledParams", isDirectory: false)
        try? FileManager.default.removeItem(at: paramUrl)
    }
    UserDefaults.standard.set(true, forKey: key)
}

Objective-C:

NSString *key = @"GoogleMapsServerControlledParamsKey_bug_154855417";
BOOL keyExists = [[NSUserDefaults standardUserDefaults] boolForKey:key];
if (!keyExists) {
    NSArray<NSURL *> *array =
        [[NSFileManager defaultManager] URLsForDirectory:NSApplicationSupportDirectory
                                               inDomains:NSUserDomainMask];
    if (array.count > 0) {
        NSURL *url =
            [array[0] URLByAppendingPathComponent:@"com.google.GoogleMaps/ServerControlledParams"
                                      isDirectory:NO];
        if (url) {
            [[NSFileManager defaultManager] removeItemAtURL:url error:NULL];
        }
    }
    [[NSUserDefaults standardUserDefaults] setBool:YES forKey:key];
}

Code workaround for Android:

The recommended placement for the code is in Application.onCreate():

Java

try {
  SharedPreferences hasFixedGoogleBug154855417 = getSharedPreferences("google_bug_154855417", Context.MODE_PRIVATE);
  if (!hasFixedGoogleBug154855417.contains("fixed")) {
    File corruptedZoomTables = new File(getFilesDir(), "ZoomTables.data");
    File corruptedSavedClientParameters = new File(getFilesDir(), "SavedClientParameters.data.cs");
    File corruptedClientParametersData =
        new File(
          getFilesDir(),
          "DATA_ServerControlledParametersManager.data."
              + getBaseContext().getPackageName());
    File corruptedClientParametersDataV1 =
        new File(
          getFilesDir(),
          "DATA_ServerControlledParametersManager.data.v1."
              + getBaseContext().getPackageName());
    corruptedZoomTables.delete();
    corruptedSavedClientParameters.delete();
    corruptedClientParametersData.delete();
    corruptedClientParametersDataV1.delete();
    hasFixedGoogleBug154855417.edit().putBoolean("fixed", true).apply();
  }
} catch (Exception e) {

}

Kotlin

try {
    val sharedPreferences = getSharedPreferences("google_bug_154855417", Context.MODE_PRIVATE)
    if (!sharedPreferences.contains("fixed")) {
        val corruptedZoomTables = File(filesDir, "ZoomTables.data")
        val corruptedSavedClientParameters = File(filesDir, "SavedClientParameters.data.cs")
        val corruptedClientParametersData = File(filesDir, "DATA_ServerControlledParametersManager.data.${packageName}")
        val corruptedClientParametersDataV1 = File(filesDir, "DATA_ServerControlledParametersManager.data.v1.${packageName}")
        corruptedZoomTables.delete()
        corruptedSavedClientParameters.delete()
        corruptedClientParametersData.delete()
        corruptedClientParametersDataV1.delete()
        sharedPreferences.edit().putBoolean("fixed", true).apply()
    }
} catch (exception: Exception) {

}

The workarounds provided here covers all available flavors and versions of our SDKs for Android. To clarify further (in case you released an earlier version of the workaround that did not delete as many files):

  • Applications that use Maps Android SDK v2 should only need to delete one file: ZoomTables.data.
  • Applications that use Maps Android SDK v3 beta should only need to delete one file, either

    DATA_ServerControlledParametersManager.data.v1. + getBaseContext().getPackageName()) or

    DATA_ServerControlledParametersManager.data. + getBaseContext().getPackageName())


Seems in every app Google Map creates ZoomTables.data file.

enter image description here

This file was malformed, malformed version of it that could be downloaded from comment. To reproduce the issue remove ZoomTables.data from the app packages on the device and insert malformed one. The app should crash.

Currently, the issue was solved on google's side, but the apps still contain a cached version of that data file. To fix the issue we should remove that file right on the app start in Application onCreate Method.

private void fixGoogleMapBug() {
  try {
    SharedPreferences hasFixedGoogleBug154855417 = getSharedPreferences("google_bug_154855417", Context.MODE_PRIVATE);
    if (!hasFixedGoogleBug154855417.contains("fixed")) {
      File corruptedZoomTables = new File(getFilesDir(), "ZoomTables.data");
      File corruptedSavedClientParameters = new File(getFilesDir(), "SavedClientParameters.data.cs");
      File corruptedClientParametersData =
          new File(
            getFilesDir(),
            "DATA_ServerControlledParametersManager.data."
                + getBaseContext().getPackageName());
      File corruptedClientParametersDataV1 =
          new File(
            getFilesDir(),
            "DATA_ServerControlledParametersManager.data.v1."
                + getBaseContext().getPackageName());
      corruptedZoomTables.delete();
      corruptedSavedClientParameters.delete();
      corruptedClientParametersData.delete();
      corruptedClientParametersDataV1.delete();
      hasFixedGoogleBug154855417.edit().putBoolean("fixed", true).apply();
    }
  } catch (Exception e) {

  }
}

Update 1

I've updated workaround, base on the latest google developers comment:

The workarounds provided here covers all available flavors and versions of our SDKs for Android. To clarify further (in case you released an earlier version of the workaround that did not delete as many files):

Applications that use Maps Android SDK v2 should only need to delete one file: ZoomTables.data. Applications that use Maps Android SDK v3 beta should only need to delete one file, either DATA_ServerControlledParametersManager.data.v1. + getBaseContext().getPackageName()) or DATA_ServerControlledParametersManager.data. + getBaseContext().getPackageName())


This solution worked for me

  1. First open "App Info"

  2. Choose "Storage"

  3. Click "Clear data"

  4. Open app again and check if the issue fixed.

    Below are suggestions just to help your customers.

  5. Send an email to your all users for the inconvenience and describe them the issue they faced and give them above mentioned steps to resolve their issue.

  6. You can also send Push Notification to all your users with Firebase Push Notifications, if your app have the push notifications service.

Screenshots demonstration:

enter image description here

enter image description here

enter image description here


Drawbacks of solutions above:

  • ZoomTables.data is deleted on every device, regardless of whether the device is affected by the crash or not
  • Workaround only works once, is it sure that this problem never happens again?

Drawbacks of my solution:

  • on first execution of maps activity on affected device map is empty. After rotation of device or second execution map is shown up

My solution catches the Exception thrown by the Maps SDK, call this in onCreate of the Application class:

public static void catchGoogleMapsException(final Context context)
{
  final Thread.UncaughtExceptionHandler defaultHandler =
    Thread.getDefaultUncaughtExceptionHandler();
  Thread.setDefaultUncaughtExceptionHandler(
    (@NonNull final Thread thread, @NonNull final Throwable ex) ->
    {
      if (thread.getName().contains("ZoomTableManager"))
      {
        new File(context.getFilesDir(), "ZoomTables.data").delete();
        Log.w("Maps Bug 154855417", "Caught exception and deleted ZoomTables.data");
      }
      else
        if (defaultHandler!=null)
          defaultHandler.uncaughtException(thread, ex);
        else
          throw new RuntimeException(
            "No default uncaught exception handler.", ex);
    });
}

For Android, multiple developers mentioned a workaround consisting in deleting the ZoomTable.data file directly from their application. After review, this fix seems safe, and you could try it in your application.

Please refer to https://issuetracker.google.com/154855417#comment179

If you want your users to continue using your app without re-installing, The sample code is copy-pasted here for your convenience. In Application.onCreate():

SharedPreferences googleBug = getSharedPreferences("google_bug_154855417", Context.MODE_PRIVATE);
if (!googleBug.contains("fixed")) {
        File corruptedZoomTables = new File(getFilesDir(), "ZoomTables.data");
        corruptedZoomTables.delete();
        googleBug.edit().putBoolean("fixed", true).apply();
}

reference: Google Maps SDK is crashing -- partially resolved


Solution Offered for iOS & Android:

https://issuetracker.google.com/issues/154855417#comment509

Maps SDK for Android v2 (included in Google Play Services)

The updates to Google Play Services to fix the crash has been published to all devices with Google Play Services version 17.4.55 and newer. There is no change to the version number of Google Play Services on the device after the update is installed. No action is required from developers or end users to receive the updated Maps module; however, developers can verify that the module is present on a given device with the following adb command:

adb shell dumpsys activity provider com.google.android.gms.chimera.container.GmsModuleProvider

You should see the line Module Set ID: maps listed in the Module Sets section.

Module Set ID: maps, Module Set Version: 2015120015120000

The crash rates of Maps SDK for Android v2 are back to normal.

As of now, if you have not updated your app with the client-side code workarounds mentioned below, you do not need to take further action.

If you have already updated your app with the workarounds, you can remove the workaround in a subsequent update of your app (but keeping the workaround is safe).


Code workaround for Android:

The productive version was fixed (on google's side) but if you still have problems with your emulator you have to run the following code only once.

The recommended placement for the code is in Application.onCreate():

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    fixGoogleMapBugTemp()   //TODO: Then clean this line

//  ...  

}

/**
 * Observation: Invoke this method only once
 */
private fun fixGoogleMapBugTemp() {
    val googleBug = getSharedPreferences("google_bug_154855417", Context.MODE_PRIVATE)
    if (!googleBug.contains("fixed")) {
        val corruptedZoomTables = File(filesDir, "ZoomTables.data");
        corruptedZoomTables.delete();
        googleBug.edit().putBoolean("fixed", true).apply();
    }
}

Workaround: Clear application data (not just the cache).

Note: A copy of the problematic file from the app packages on the device if anyone needs it for repro.

Block

Source

GL


Complete & official answer for all :

Diagnosis: Crash of the Google Maps Platform mobile SDKs (iOS & Android) at load.

Workaround: * Clear the affected app's data (not just the cache), or uninstall then reinstall the affected app(s).

  • Code workaround for iOS:

Recommended placement for the code is before GMSServices initialization in the application(_:didFinishLaunchingWithOptions:) (Swift) or application:didFinishLaunchingWithOptions: (Objective-C) method. Specifically:

Swift:

let key = "GoogleMapsServerControlledParamsKey_bug_154855417"
if !UserDefaults.standard.bool(forKey: key) {
    let urls = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)
    if urls.count > 0 {
        let paramUrl = urls[0].appendingPathComponent("com.google.GoogleMaps/ServerControlledParams", isDirectory: false)
        try? FileManager.default.removeItem(at: paramUrl)
    }
    UserDefaults.standard.set(true, forKey: key)
}

Objective-C:

NSString *key = @"GoogleMapsServerControlledParamsKey_bug_154855417";
BOOL keyExists = [[NSUserDefaults standardUserDefaults] boolForKey:key];
if (!keyExists) {
    NSArray<NSURL *> *array =
        [[NSFileManager defaultManager] URLsForDirectory:NSApplicationSupportDirectory
                                               inDomains:NSUserDomainMask];
    if (array.count > 0) {
        NSURL *url =
            [array[0] URLByAppendingPathComponent:@"com.google.GoogleMaps/ServerControlledParams"
                                      isDirectory:NO];
        if (url) {
            [[NSFileManager defaultManager] removeItemAtURL:url error:NULL]);
        }
    }
    [[NSUserDefaults standardUserDefaults] setBool:YES forKey:key];
}

Once you have deployed it in your app, you can file a Maps Support case if you would like us to help expedite its approval. Please make sure to include your application's ID, Bundle ID, and the version you want reviewed in your case.

  • Code workaround for Android:

    The recommended placement for the code is in Application.onCreate():

    Java

    try {
      SharedPreferences hasFixedGoogleBug154855417 = getSharedPreferences("google_bug_154855417", Context.MODE_PRIVATE);
      if (!hasFixedGoogleBug154855417.contains("fixed")) {
        File corruptedZoomTables = new File(getFilesDir(), "ZoomTables.data");
        File corruptedSavedClientParameters = new File(getFilesDir(), "SavedClientParameters.data.cs");
        File corruptedClientParametersData =
            new File(
              getFilesDir(),
              "DATA_ServerControlledParametersManager.data.v1."
                  + getBaseContext().getPackageName());
        corruptedZoomTables.delete();
        corruptedSavedClientParameters.delete();
        corruptedClientParametersData.delete();
        hasFixedGoogleBug154855417.edit().putBoolean("fixed", true).apply();
      }
    } catch (Exception e) {
    
    }
    

    Kotlin

    try {
        val sharedPreferences = getSharedPreferences("google_bug_154855417", Context.MODE_PRIVATE)
        if (!sharedPreferences.contains("fixed")) {
            val corruptedZoomTables = File(filesDir, "ZoomTables.data")
            val corruptedSavedClientParameters = File(filesDir, "SavedClientParameters.data.cs")
            val corruptedClientParametersData = File(filesDir, "DATA_ServerControlledParametersManager.data.v1.${packageName}")
            corruptedZoomTables.delete()
            corruptedSavedClientParameters.delete()
            corruptedClientParametersData.delete()
            sharedPreferences.edit().putBoolean("fixed", true).apply()
        }
    } catch (exception: Exception) {
    
    }
    

Source : https://issuetracker.google.com/issues/1548554