Access the expiration information of an expired mobile map package.

Use case
The data contained within a mobile map package (MMPK) may only be relevant for a fixed period of time. Using ArcGIS Pro, the author of an MMPK can set an expiration date to ensure the user is aware the data is out of date.
As long as the author of an MMPK has set an expiration date, the expiration date can be read even if the MMPK has not yet expired. For example, developers could also use this API to warn app users that an MMPK may be expiring soon.
How to use the sample
Launch the app. The author of the MMPK used in this sample chose to set the MMPK’s map as still readable, even if it’s expired. The app presents expiration information to the user.
How it works
- Create a
MobileMapPackageobject by providing a path to the local mobile map package file. - Load the
MobileMapPackage. - Present the mobile map package’s expiration information to the user:
- Use
Expiration.messageto get the expiration message set by the author of the MMPK. - Use
Expiration.dateTimeto get the expiration date set by the author of the MMPK. - Use
Expiration.isExpiredto determine whether the MMPK has expired.
- Use
Relevant API
- Expiration
- MobileMapPackage
Offline data
This sample uses the LothianRiversAnno - Expired mobile map package. It is downloaded from ArcGIS Online automatically.
Tags
expiration, mmpk
Sample Code
/* Copyright 2025 Esri * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */
package com.esri.arcgismaps.sample.showmobilemappackageexpirationdate
import android.content.Intentimport android.os.Bundleimport com.esri.arcgismaps.sample.sampleslib.DownloaderActivity
class DownloadActivity : DownloaderActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) downloadAndStartSample( Intent(this, MainActivity::class.java), getString(R.string.show_mobile_map_package_expiration_date_app_name), listOf( "https://www.arcgis.com/home/item.html?id=174150279af74a2ba6f8b87a567f480b" ) ) }}/* Copyright 2025 Esri * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */
package com.esri.arcgismaps.sample.showmobilemappackageexpirationdate
import android.os.Bundleimport androidx.activity.ComponentActivityimport androidx.activity.compose.setContentimport androidx.compose.material3.MaterialThemeimport androidx.compose.material3.Surfaceimport androidx.compose.runtime.Composableimport com.arcgismaps.ApiKeyimport com.arcgismaps.ArcGISEnvironmentimport com.esri.arcgismaps.sample.sampleslib.theme.SampleAppThemeimport com.esri.arcgismaps.sample.showmobilemappackageexpirationdate.screens.ShowMobileMapPackageExpirationDateScreen
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // authentication with an API key or named user is // required to access basemaps and other location services ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.ACCESS_TOKEN)
setContent { SampleAppTheme { ShowMobileMapPackageExpirationDateApp() } } }
@Composable private fun ShowMobileMapPackageExpirationDateApp() { Surface(color = MaterialTheme.colorScheme.background) { ShowMobileMapPackageExpirationDateScreen( sampleName = getString(R.string.show_mobile_map_package_expiration_date_app_name) ) } }}/* Copyright 2025 Esri * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */
package com.esri.arcgismaps.sample.showmobilemappackageexpirationdate.components
import android.app.Applicationimport androidx.compose.runtime.getValueimport androidx.compose.runtime.mutableStateOfimport androidx.compose.runtime.setValueimport androidx.lifecycle.AndroidViewModelimport androidx.lifecycle.viewModelScopeimport com.arcgismaps.mapping.ArcGISMapimport com.arcgismaps.mapping.MobileMapPackageimport com.esri.arcgismaps.sample.sampleslib.components.MessageDialogViewModelimport com.esri.arcgismaps.sample.showmobilemappackageexpirationdate.Rimport java.io.Fileimport java.time.ZoneIdimport java.time.format.DateTimeFormatterimport java.time.format.FormatStyleimport java.util.Localeimport kotlinx.coroutines.launch
class ShowMobileMapPackageExpirationDateViewModel(val app: Application) : AndroidViewModel(app) { // The map displayed on the MapView. Updated after loading the mobile map package var arcGISMap: ArcGISMap by mutableStateOf(ArcGISMap()) private set
// Message dialog view model for handling error messages val messageDialogVM = MessageDialogViewModel()
// Expiration UI states exposed to the screen var isExpired by mutableStateOf(false) private set
var expirationMessage by mutableStateOf("") private set
var expirationDateText by mutableStateOf("N/A") private set
// Build the provision path where offline resources are stored for the sample app private val provisionPath: String by lazy { val basePath = app.getExternalFilesDir(null)?.path.toString() val appFolderName = app.getString(R.string.show_mobile_map_package_expiration_date_app_name) basePath + File.separator + appFolderName }
init { // Load the mobile map package and update map/expiration info viewModelScope.launch { loadMobileMapPackageAndUpdateState() } }
// Loads the local mobile map package and updates the map and expiration states private suspend fun loadMobileMapPackageAndUpdateState() { // Locate the LothianRiversAnno.mmpk file in the provisioned path val mmpkFile = File(provisionPath, "LothianRiversAnno.mmpk") if (!mmpkFile.exists()) { messageDialogVM.showMessageDialog("Mobile map package file does not exist.") return }
// Create and load the mobile map package val mobileMapPackage = MobileMapPackage(mmpkFile.path) mobileMapPackage.load().onSuccess { // If the loaded mobile map package does not contain any maps val map = mobileMapPackage.maps.firstOrNull() if (map == null) { messageDialogVM.showMessageDialog("Mobile map package does not contain a map") return@onSuccess }
// Set the map to the first map in the mobile map package arcGISMap = map
// Read expiration information from the mobile map package mobileMapPackage.expiration?.let { expiration -> isExpired = expiration.isExpired expirationMessage = expiration.message
val formatter = DateTimeFormatter .ofLocalizedDateTime(FormatStyle.SHORT) .withLocale(Locale.getDefault()) .withZone(ZoneId.systemDefault())
expirationDateText = expiration.dateTime?.let { formatter.format(it) } ?: "N/A" } }.onFailure { error -> messageDialogVM.showMessageDialog( title = "Failed to load the mobile map package", description = error.message.toString() ) } }}/* Copyright 2025 Esri * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */
package com.esri.arcgismaps.sample.showmobilemappackageexpirationdate.screens
import androidx.compose.foundation.backgroundimport androidx.compose.foundation.layout.Boximport androidx.compose.foundation.layout.Columnimport androidx.compose.foundation.layout.Spacerimport androidx.compose.foundation.layout.fillMaxSizeimport androidx.compose.foundation.layout.paddingimport androidx.compose.material3.Cardimport androidx.compose.material3.MaterialThemeimport androidx.compose.material3.Scaffoldimport androidx.compose.material3.Textimport androidx.compose.runtime.Composableimport androidx.compose.ui.Alignmentimport androidx.compose.ui.Modifierimport androidx.compose.ui.text.style.TextAlignimport androidx.compose.ui.unit.dpimport androidx.lifecycle.viewmodel.compose.viewModelimport com.arcgismaps.toolkit.geoviewcompose.MapViewimport com.esri.arcgismaps.sample.sampleslib.components.MessageDialogimport com.esri.arcgismaps.sample.sampleslib.components.SampleTopAppBarimport com.esri.arcgismaps.sample.showmobilemappackageexpirationdate.components.ShowMobileMapPackageExpirationDateViewModel
/** * Main screen layout for the sample app which displays the map from a mobile map package * and shows expiration information if the mobile map package has expired. */@Composablefun ShowMobileMapPackageExpirationDateScreen(sampleName: String) { val mapViewModel: ShowMobileMapPackageExpirationDateViewModel = viewModel()
Scaffold( topBar = { SampleTopAppBar(title = sampleName) }, content = { paddingValues -> Box( modifier = Modifier .fillMaxSize() .padding(paddingValues) ) { MapView( modifier = Modifier.fillMaxSize(), arcGISMap = mapViewModel.arcGISMap )
// Display expiration information overlay if the mobile map package is expired if (mapViewModel.isExpired) { Card( modifier = Modifier .align(Alignment.Center) .padding(top = 16.dp, bottom = 16.dp) .background(MaterialTheme.colorScheme.surfaceVariant) ) { Column( modifier = Modifier.padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally ) { Text( text = mapViewModel.expirationMessage, style = MaterialTheme.typography.bodyMedium, textAlign = TextAlign.Center ) Spacer(modifier = Modifier.padding(8.dp)) Text( text = "Expiration date: ${mapViewModel.expirationDateText}", style = MaterialTheme.typography.bodySmall, textAlign = TextAlign.Center ) } } }
// Display error dialog when the sample encounters an error mapViewModel.messageDialogVM.apply { if (dialogStatus) { MessageDialog( title = messageTitle, description = messageDescription, onDismissRequest = ::dismissDialog ) } } } } )}