Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
/* 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.addelevationsourcefromtilepackage

import android.content.Intent
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
/* 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.applydictionaryrenderertographicsoverlay

import android.content.Intent
Expand Down
37 changes: 37 additions & 0 deletions samples/show-mobile-map-package-expiration-date/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Show mobile map package expiration date

Access the expiration information of an expired mobile map package.

![Image of Show mobile map package expiration date](show-mobile-map-package-expiration-date.png)

## 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

1. Create a `MobileMapPackage` object by providing a path to the local mobile map package file.
2. Load the `MobileMapPackage`.
3. Present the mobile map package's expiration information to the user:
* Use `Expiration.message` to get the expiration message set by the author of the MMPK.
* Use `Expiration.dateTime` to get the expiration date set by the author of the MMPK.
* Use `Expiration.isExpired` to determine whether the MMPK has expired.

## Relevant API

* Expiration
* MobileMapPackage

## Offline data

This sample uses the [LothianRiversAnno - Expired](https://www.arcgis.com/home/item.html?id=174150279af74a2ba6f8b87a567f480b) mobile map package. It is downloaded from ArcGIS Online automatically.

## Tags

expiration, mmpk
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"category": "Maps",
"description": "Access the expiration information of an expired mobile map package.",
"formal_name": "ShowMobileMapPackageExpirationDate",
"ignore": false,
"images": [
"show-mobile-map-package-expiration-date.png"
],
"keywords": [
"expiration",
"mmpk",
"Expiration",
"MobileMapPackage"
],
"language": "kotlin",
"provision_from": [
"https://www.arcgis.com/home/item.html?id=174150279af74a2ba6f8b87a567f480b"
],
"provision_to": [],
"redirect_from": "",
"relevant_apis": [
"Expiration",
"MobileMapPackage"
],
"snippets": [
"src/main/java/com/esri/arcgismaps/sample/showmobilemappackageexpirationdate/components/ShowMobileMapPackageExpirationDateViewModel.kt",
"src/main/java/com/esri/arcgismaps/sample/showmobilemappackageexpirationdate/MainActivity.kt",
"src/main/java/com/esri/arcgismaps/sample/showmobilemappackageexpirationdate/DownloadActivity.kt",
"src/main/java/com/esri/arcgismaps/sample/showmobilemappackageexpirationdate/screens/ShowMobileMapPackageExpirationDateScreen.kt"
],
"title": "Show mobile map package expiration date"
}
22 changes: 22 additions & 0 deletions samples/show-mobile-map-package-expiration-date/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
plugins {
alias(libs.plugins.arcgismaps.android.library)
alias(libs.plugins.arcgismaps.android.library.compose)
alias(libs.plugins.arcgismaps.kotlin.sample)
alias(libs.plugins.gradle.secrets)
}

secrets {
// this file doesn't contain secrets, it just provides defaults which can be committed into git.
defaultPropertiesFileName = "secrets.defaults.properties"
}

android {
namespace = "com.esri.arcgismaps.sample.showmobilemappackageexpirationdate"
buildFeatures {
buildConfig = true
}
}

dependencies {
// Only module specific dependencies needed here
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

<uses-permission android:name="android.permission.INTERNET" />

<application><activity
android:exported="true"
android:name=".MainActivity"
android:label="@string/show_mobile_map_package_expiration_date_app_name">

</activity>
<activity
android:name=".DownloadActivity"
android:exported="true"
android:label="@string/show_mobile_map_package_expiration_date_app_name" />
</application>

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/* 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
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing copyright block


import android.content.Intent
import android.os.Bundle
import 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"
)
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/* 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.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import com.arcgismaps.ApiKey
import com.arcgismaps.ArcGISEnvironment
import com.esri.arcgismaps.sample.sampleslib.theme.SampleAppTheme
import 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)
)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/* 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.Application
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
import com.arcgismaps.mapping.ArcGISMap
import com.arcgismaps.mapping.MobileMapPackage
import com.esri.arcgismaps.sample.sampleslib.components.MessageDialogViewModel
import com.esri.arcgismaps.sample.showmobilemappackageexpirationdate.R
import java.io.File
import java.time.ZoneId
import java.time.format.DateTimeFormatter
import java.time.format.FormatStyle
import java.util.Locale
import 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()
)
}
}
}
Loading
Loading