Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Venkata/display scene from mobile scene package #127

Merged
merged 14 commits into from
Jul 28, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
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
1 change: 1 addition & 0 deletions display-scene-from-mobile-scene-package/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
32 changes: 32 additions & 0 deletions display-scene-from-mobile-scene-package/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Display scene from mobile scene package

Display a scene from a mobile scene package (.mspk)

![Image of display scene from mobile scene package](display-scene-from-mobile-scene-package.png)

## Use case

An .mspk file is an archive containing the data (specifically, basemaps and features), used to display an offline 3D scene.

## How to use the sample

When the sample opens, it will automatically display the Scene in the mobile scene package. Since this sample works with a local .mspk, you may initially need to download the file to your device. Pan and zoom to observe the scene from the mobile scene package.

## How it works

This sample takes a mobile scene package that was created in ArcGIS Pro, and displays a `Scene` from within the package in a `SceneView`.

1. Create a `MobileScenePackage` using the path to the local .mspk file.
2. Call `MobileScenePackage::load` and check for any errors.
3. When the `MobileScenePackage` is loaded, obtain the first `Scene` from the `MobileScenePackage::scenes` property.
4. Create a `SceneView` and call `SceneView::setView` to display the scene from the package.
vbharath98 marked this conversation as resolved.
Show resolved Hide resolved

## Relevant API

* SceneView
* MobileScenePackage
* ArcGISScene

## Tags

mspk, mobile scene package, offline, 3d, scene
36 changes: 36 additions & 0 deletions display-scene-from-mobile-scene-package/README.metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"category": "TODO",
vbharath98 marked this conversation as resolved.
Show resolved Hide resolved
"description": "Display a scene from a mobile scene package (.mspk)",
"formal_name": "DisplaySceneFromMobileScenePackage",
"ignore": false,
"images": [
"display-scene-from-mobile-scene-package.png"
],
"keywords": [
"3d",
"mobile scene package",
"mspk",
"offline",
"scene",
"ArcGISScene",
"MobileScenePackage",
"SceneView"
],
"language": "kotlin",
"provision_from": "TODO",
"provision_to": "TODO",
"redirect_from": "TODO",
shubham7109 marked this conversation as resolved.
Show resolved Hide resolved
"relevant_apis": [
"ArcGISScene",
"MobileScenePackage",
"SceneView"
],
"snippets": [
"/src/main/java/com/esri/arcgismaps/sample/displayscenefrommobilescenepackage/DownloadActivity.kt",
"/src/main/java/com/esri/arcgismaps/sample/displayscenefrommobilescenepackage/MainActivity.kt",
"/src/main/java/com/esri/arcgismaps/sample/displayscenefrommobilescenepackage/components/ComposeSceneView.kt",
"/src/main/java/com/esri/arcgismaps/sample/displayscenefrommobilescenepackage/components/SceneViewModel.kt",
"/src/main/java/com/esri/arcgismaps/sample/displayscenefrommobilescenepackage/screens/MainScreen.kt"
vbharath98 marked this conversation as resolved.
Show resolved Hide resolved
],
"title": "Display scene from mobile scene package"
}
47 changes: 47 additions & 0 deletions display-scene-from-mobile-scene-package/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
apply plugin: 'com.android.application'
apply plugin: 'org.jetbrains.kotlin.android'

android {
compileSdkVersion rootProject.ext.compileSdkVersion

defaultConfig {
applicationId "com.esri.arcgismaps.sample.displayscenefrommobilescenepackage"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode rootProject.ext.versionCode
versionName rootProject.ext.versionName
buildConfigField("String", "API_KEY", API_KEY)
}

buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}

buildFeatures {
compose = true
}
composeOptions {
kotlinCompilerExtensionVersion = "$kotlinCompilerExt"
}

namespace 'com.esri.arcgismaps.sample.displayscenefrommobilescenepackage'
}

dependencies {
// lib dependencies from rootProject build.gradle
implementation "androidx.core:core-ktx:$ktxAndroidCore"
implementation "androidx.lifecycle:lifecycle-runtime-ktx:$ktxLifecycle"
implementation "androidx.lifecycle:lifecycle-viewmodel-compose:$ktxLifecycle"
implementation "androidx.activity:activity-compose:$composeActivityVersion"
// Jetpack Compose Bill of Materials
implementation platform("androidx.compose:compose-bom:$composeBOM")
// Jetpack Compose dependencies
implementation "androidx.compose.ui:ui"
implementation "androidx.compose.material3:material3"
implementation "androidx.compose.ui:ui-tooling"
implementation "androidx.compose.ui:ui-tooling-preview"
implementation project(path: ':samples-lib')
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 21 additions & 0 deletions display-scene-from-mobile-scene-package/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?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
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".DownloadActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
</activity>
</application>

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.esri.arcgismaps.sample.displayscenefrommobilescenepackage
vbharath98 marked this conversation as resolved.
Show resolved Hide resolved

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),
// get the app name of the sample
getString(R.string.app_name),
listOf(
// ArcGIS Portal item containing the .mspk mobile scene package
"https://www.arcgis.com/home/item.html?id=7dd2f97bb007466ea939160d0de96a9d"
)
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/* Copyright 2023 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.displayscenefrommobilescenepackage

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.displayscenefrommobilescenepackage.screens.MainScreen
import com.esri.arcgismaps.sample.sampleslib.theme.SampleAppTheme

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.API_KEY)

setContent {
SampleAppTheme {
SampleApp()
}
}
}

@Composable
private fun SampleApp() {
vbharath98 marked this conversation as resolved.
Show resolved Hide resolved
Surface(
color = MaterialTheme.colorScheme.background
) {
MainScreen(
sampleName = getString(R.string.app_name),
application = application
)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/* Copyright 2023 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.displayscenefrommobilescenepackage.components

import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.compose.ui.viewinterop.AndroidView
import androidx.lifecycle.LifecycleOwner
import com.arcgismaps.mapping.view.SceneView
import com.arcgismaps.mapping.view.SingleTapConfirmedEvent
import kotlinx.coroutines.launch

/**
* Wraps the SceneView in a Composable function.
*/
@Composable
fun ComposeSceneView(
modifier: Modifier = Modifier,
sceneViewModel: SceneViewModel,
onSingleTap: (SingleTapConfirmedEvent) -> Unit = {}
) {
// get an instance of the current lifecycle owner
val lifecycleOwner = LocalLifecycleOwner.current

// collect the latest state of the SceneView from the package
val sceneViewState by sceneViewModel.firstScene.collectAsState()

// create and add SceneView to the activity lifecycle
val sceneView = createSceneViewInstance(lifecycleOwner)

// wrap the SceneView as an AndroidView
AndroidView(
modifier = modifier,
factory = { sceneView },
// recomposes the SceneView on changes in sceneViewState
update = { sceneView ->
sceneView.scene = sceneViewState
}
)

// launch coroutine functions in the composition's CoroutineContext
LaunchedEffect(Unit) {
launch {
sceneView.onSingleTapConfirmed.collect {
onSingleTap(it)
}
}
}
vbharath98 marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* Create the SceneView instance and add it to the Activity lifecycle
*/
@Composable
fun createSceneViewInstance(lifecycleOwner: LifecycleOwner): SceneView {
// create the SceneView
val sceneView = SceneView(LocalContext.current)
// add the side effects for SceneView composition
DisposableEffect(lifecycleOwner) {
lifecycleOwner.lifecycle.addObserver(sceneView)
onDispose {
lifecycleOwner.lifecycle.removeObserver(sceneView)
}
}
return sceneView
}
Loading
Loading