androidfilesystemsmvvmcrossactivity-lifecyclecarto-mobile

Why does Carto Package Manager can't connect to it's database after resuming?


We are using Carto Xamarin Mobile SDK to develop app with offline maps support. It works fine until user does not try to resume application after it has been disposed. Activity creation (activity uses carto package manager) crashes with exception:

Carto.PackageManager.CartoPackageManager.CartoPackageManager(string source, string dataFolder)<01980a2dae7148abb92e6b982667f448>:0
App.Droid.OfflineMaps.AndroidMapPackageManager.AndroidMapPackageManager()<76ae23b9271c407d865ebb6162639870>:0
App.Droid.Plugins.MapDownloader.Plugin.<>c.<Load>b__0_0()<76ae23b9271c407d865ebb6162639870>:0
MvvmCross.Platform.IoC.MvxSimpleIoCContainer.<>c__DisplayClass33_0<TInterface>.<RegisterSingleton>b__0()<4ddde23419c5494288c799fcdbb0f189>:0
MvvmCross.Platform.IoC.MvxSimpleIoCContainer.ConstructingSingletonResolver.Resolve()<4ddde23419c5494288c799fcdbb0f189>:0
MvvmCross.Platform.IoC.MvxSimpleIoCContainer.InternalTryResolve(Type type, MvxSimpleIoCContainer.IResolver resolver, ref object resolved
App.Core.ViewModels.Blocks.Maps.Offline.MapDownloaderOwnerViewModel.EnableMapDownloader(City city)<d6cca792b401420d922bc024

Here on line 105 you can see where exception is originally thrown.

In the regular entering page it works fine. PackageManager request is happening in the ctor of the page ViewModel via:

 Mvx.Resolve<MapDownloadsManager>(); // It receivs as injection platform-dependent packageManager

It seems that the problem is in the database path. We are generating the folder name that then passed to the CartoPackageManager constructor in the following way:

 private static string CreateFolder(string folderPath)
        {

        var folder = GetDocumentDirectory(folderPath);

        if (!Directory.Exists(folder))
        {
            Directory.CreateDirectory(folder);
        }

        return folder;
    }

    private static string GetDocumentDirectory(string withFolder = null)
    {
        var documents = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);

        return withFolder == null ? documents : Path.Combine(documents, withFolder + "/");
    }

Do you have any ideas where the source of the problem could be?

P.S.: Carto SDK v 4.0.2, MvvmCross 4.4.0, unfortunately can't update to the newer now.

After some research I have spotted that task queue is reset, now supposing that app actually crashes here in source code:

 std::string taskDbFileName = "tasks_v1.sqlite";
        try {
            _taskQueue = std::make_shared<PersistentTaskQueue>(createLocalFilePath(taskDbFileName));
        }
        catch (const std::exception& ex) {
            //This looks like: Error while constructing PackageManager: Package encryption keys do not match, trying to remove
            Log::Errorf("PackageManager: Error while constructing PackageManager::PersistentTaskQueue: %s, trying to remove...", ex.what());
            _taskQueue.reset();
            utf8_filesystem::unlink(taskDbFileName.c_str());
            try {
                _taskQueue = std::make_shared<PersistentTaskQueue>(createLocalFilePath(taskDbFileName));
            }
            catch (const std::exception& ex) {
                **throw FileException("Failed to create/open package manager task queue database", taskDbFileName); //App gets here.**
            }
        }

Initialization of package manager:

 public class AndroidMapPackageManager : PackageManagerListener, IPackageManger
    {
        private readonly CartoPackageManager _packageManager;

        public AndroidMapPackageManager()
        {
            var folder = CreateFolder(OfflineMapStrings.MapsFolderName); // /data/user/0/com.app.cityguide/files/mapmap2/

 _packageManager =
                    new CartoPackageManager(OfflineMapsStrings.PackageManagerSource, folder)
                    {
                        PackageManagerListener = this
                    };
       }
}

I am starting it just after the constructor worked after subscription to the listener events by other class. And, frankly saying, I never stop it. Do I need it?

With FIllRam Repoductivity is 100%. I used debug mode with no background allowed and now I tryed Ram Filler and result is same.

License issues:

05-25 12:41:41.091 26101 26101 E carto-mobile-sdk: CartoPackageManager: RegisterLicense not called, using random key for package encryption!
05-25 12:41:41.094 26101 26101 E carto-mobile-sdk: PackageManager: Error while constructing PackageManager: Package encryption keys do not match, trying to remove

Solution

  • The problem was that I was registering license key in SplashActivity. But, after resuming splash activity is not shown and, obviously, Registering of the license key was not performed. I have moved it to the custom application class and it worked:

    public class CustomApplication : Application
    {
            public override void OnCreate()
            {
                base.OnCreate();
                MapView.RegisterLicense(CartoApiKey, this);
            }
    }