Display a scene
Learn how to create and display a scene with a basemap layer and an elevation layer. Set properties of the scene's camera to control the 3D perspective.
Like a map, a scene contains layers of geographic data. It contains a basemap layer and, optionally, one or more data layers. To provide a realistic view of the terrain, you can also add elevation layers to define the height of the surface across the scene. The 3D perspective of the scene is controlled by the scene's camera, which defines the position of the scene observer in 3D space.
In this tutorial, you create and display a scene using the imagery basemap layer. The surface of the scene is defined with an elevation layer and the camera is positioned to display an area of the Santa Monica Mountains in the scene view.
The scene and code will be used as the starting point for other 3D tutorials.
Prerequisites
The following are required for this tutorial:
- An ArcGIS account to access API keys. If you don't have an account, sign up for free.
- Confirm that your system meets the system requirements.
- An IDE for Android development in Kotlin.
Steps
Create a new Android Studio project
Use Android Studio to create an app and configure it to reference the API.
Open Android Studio.
In the menu bar, click File > New > New Project....
In the Create New Project window, make sure Phone and Tablet tab is selected, and then select Empty Activity. Click Next.
Gradle is the default build tool in Android Studio. If you are unable to use Gradle, see Getting the API Manually.
In the Configure your project window, set the following configuration options:
- Name:
Display a scene
. - Package name: Change to
com.example.app
. Or change to match your organization. - Save location: Set to a new folder.
- Language: Kotlin
- Minimum SDK: API 23: Android 6.0 (Marshmallow)
- Name:
In the Project tool window, make sure that your current view is Android. These tutorial instructions refer to that view.
If your view name is something other than Android (such as Project or Packages), click on the leftmost control in the title bar of the Project tool window, and select Android from the list.
From the Project tool window, open Gradle Scripts > build.gradle (Project: Display_a_scene). Add the following lines to the
repositories
block inallprojects
to reference the API from Esri's maven repository.build.gradle (Project: Display_a_scene)Add line. Add line. Add line. 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 17 18 19 20 21 22 23 24 25 26 27 27 27 27 27// Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { ext.kotlin_version = "1.4.21" repositories { google() jcenter() } dependencies { classpath "com.android.tools.build:gradle:4.1.1" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } } allprojects { repositories { google() jcenter() maven { url 'https://esri.jfrog.io/artifactory/arcgis' } } } task clean(type: Delete) { delete rootProject.buildDir }
From the Project tool window, open Gradle Scripts > build.gradle (Module: Display_a_scene.app). Add the following line in the
dependencies
block to include the ArcGIS Runtime API for Android.build.gradle (Module: Display_a_scene.app)Add line. 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 37 36 35 34 34 34 35 36 37 38 39 40 41 42 43plugins { id 'com.android.application' id 'kotlin-android' } android { compileSdkVersion 29 defaultConfig { applicationId "com.example.app" minSdkVersion 23 targetSdkVersion 29 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } kotlinOptions { jvmTarget = JavaVersion.VERSION_1_8.toString() } buildFeatures { viewBinding true } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation 'androidx.appcompat:appcompat:1.2.0' implementation 'androidx.constraintlayout:constraintlayout:2.0.4' implementation 'com.esri.arcgisruntime:arcgis-android:100.10.0' }
Enable view binding by adding it to a
buildFeatures
block in theandroid
block.build.gradle (Module: Display_a_scene.app)Add line. Add line. Add line. 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 29 30 31 32 33 34 35 35 35 35 35 35 35 35 35 35 35 35 35plugins { id 'com.android.application' id 'kotlin-android' } android { compileSdkVersion 29 defaultConfig { applicationId "com.example.app" minSdkVersion 23 targetSdkVersion 29 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } kotlinOptions { jvmTarget = JavaVersion.VERSION_1_8.toString() } buildFeatures { viewBinding true } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation 'androidx.appcompat:appcompat:1.2.0' implementation 'androidx.constraintlayout:constraintlayout:2.0.4' implementation 'com.esri.arcgisruntime:arcgis-android:100.10.0' }
Sync the Gradle changes. Click the Sync now prompt or click the refresh icon (Sync Project with Gradle Files) in the toolbar. This may take several minutes.
From the Project tool window, open app > manifests > AndroidManifest.xml. Update the Android manifest to allow network access, and also to indicate the app uses OpenGL 2.0 or above.
Insert these new elements within the
manifest
element. Do not alter or remove any other statements.Depending on what ArcGIS functionality you add in future tutorials, it is likely you will need to add additional permissions to your manifest.
AndroidManifest.xmlAdd line. Add line. Add line. Add line. 1 2 3 4 5 6 7 8 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.app"> <uses-permission android:name="android.permission.INTERNET" /> <uses-feature android:glEsVersion="0x00030000" android:required="true" /> <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=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
Add import statements
Open app > java > com.example.app MainActivity.kt, and add import statements to reference the ArcGIS Runtime API.
/*
* Copyright 2021 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
*
* https://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.example.app
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.esri.arcgisruntime.ArcGISRuntimeEnvironment
import com.esri.arcgisruntime.geometry.Point
import com.esri.arcgisruntime.geometry.SpatialReferences
import com.esri.arcgisruntime.mapping.ArcGISScene
import com.esri.arcgisruntime.mapping.ArcGISTiledElevationSource
import com.esri.arcgisruntime.mapping.Basemap
import com.esri.arcgisruntime.mapping.Surface
import com.esri.arcgisruntime.mapping.view.Camera
import com.esri.arcgisruntime.mapping.view.SceneView
import com.example.app.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
private val activityMainBinding: ActivityMainBinding by lazy {
ActivityMainBinding.inflate(layoutInflater)
}
private val sceneView: SceneView by lazy {
activityMainBinding.sceneView
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(activityMainBinding.root)
setupScene()
}
override fun onPause() {
sceneView.pause()
super.onPause()
}
override fun onResume() {
super.onResume()
sceneView.resume()
}
override fun onDestroy() {
sceneView.dispose()
super.onDestroy()
}
// set up your scene here. You will call this method from onCreate()
private fun setupScene() {
// Note: it is not best practice to store API keys in source code.
// The API key is referenced here for the convenience of this tutorial.
ArcGISRuntimeEnvironment.setApiKey("YOUR_API_KEY")
val scene = ArcGISScene(Basemap.createImagery())
// set the scene on the scene view
sceneView.scene = scene
// add base surface for elevation data
val elevationSource = ArcGISTiledElevationSource("https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer")
val surface = Surface(listOf(elevationSource))
// add an exaggeration factor to increase the 3D effect of the elevation.
surface.elevationExaggeration = 2.5f
scene.baseSurface = surface
// Point(x, y, z, spatialReference)
val cameraLocation = Point(-118.794, 33.909, 5330.0, SpatialReferences.getWgs84())
// Camera(location, heading, pitch, roll)
val camera = Camera(cameraLocation, 355.0, 72.0, 0.0)
sceneView.setViewpointCamera(camera)
}
}
Add a UI for the scene view
A scene view is a UI component that displays a scene. It also handles user interactions with the scene, including navigating with touch gestures. Use XML to add a scene view to the UI and make it available to the main activity source code.
In app > res > layout > activity_main.xml, replace the entire
TextView
element with aSceneView
element.If you do not see the XML code, select the Code tab to switch out of design mode and display the XML code in the editor.
Your
SceneView
element creates an instance of theSceneView
class from the ArcGIS Runtime API for Android.In your main activity source code, you can access the
SceneView
using animplicit
property, which is declared in the value of theandroid:id
attribute. In this case, the property will be namedsceneView
.activity_main.xmlChange line Change line Change line Change line 1 2 3 4 5 6 7 8 9 10 11 12 13<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <com.esri.arcgisruntime.mapping.view.SceneView android:id="@+id/sceneView" android:layout_width="match_parent" android:layout_height="match_parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
In MainActivity.kt, create a read-only local variable named
activityMainBinding
referencing the generated Android classActivityMainBinding
.MainActivity.ktAdd line. Add line. Add line. 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 35 36 37 38 39 40 40 40 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -14/* * Copyright 2021 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 * * https://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.example.app import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import com.esri.arcgisruntime.ArcGISRuntimeEnvironment import com.esri.arcgisruntime.geometry.Point import com.esri.arcgisruntime.geometry.SpatialReferences import com.esri.arcgisruntime.mapping.ArcGISScene import com.esri.arcgisruntime.mapping.ArcGISTiledElevationSource import com.esri.arcgisruntime.mapping.Basemap import com.esri.arcgisruntime.mapping.Surface import com.esri.arcgisruntime.mapping.view.Camera import com.esri.arcgisruntime.mapping.view.SceneView import com.example.app.databinding.ActivityMainBinding class MainActivity : AppCompatActivity() { private val activityMainBinding: ActivityMainBinding by lazy { ActivityMainBinding.inflate(layoutInflater) } private val sceneView: SceneView by lazy { activityMainBinding.sceneView } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(activityMainBinding.root) setupScene() } override fun onPause() { sceneView.pause() super.onPause() } override fun onResume() { super.onResume() sceneView.resume() } override fun onDestroy() { sceneView.dispose() super.onDestroy() } // set up your scene here. You will call this method from onCreate() private fun setupScene() { // Note: it is not best practice to store API keys in source code. // The API key is referenced here for the convenience of this tutorial. ArcGISRuntimeEnvironment.setApiKey("YOUR_API_KEY") val scene = ArcGISScene(Basemap.createImagery()) // set the scene on the scene view sceneView.scene = scene // add base surface for elevation data val elevationSource = ArcGISTiledElevationSource("https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer") val surface = Surface(listOf(elevationSource)) // add an exaggeration factor to increase the 3D effect of the elevation. surface.elevationExaggeration = 2.5f scene.baseSurface = surface // Point(x, y, z, spatialReference) val cameraLocation = Point(-118.794, 33.909, 5330.0, SpatialReferences.getWgs84()) // Camera(location, heading, pitch, roll) val camera = Camera(cameraLocation, 355.0, 72.0, 0.0) sceneView.setViewpointCamera(camera) } }
Create a read-only variable named
sceneView
and bind it to thesceneView
created in activity_main.xml.MainActivity.ktAdd line. Add line. Add line. 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 35 36 37 38 39 40 41 42 43 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -10/* * Copyright 2021 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 * * https://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.example.app import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import com.esri.arcgisruntime.ArcGISRuntimeEnvironment import com.esri.arcgisruntime.geometry.Point import com.esri.arcgisruntime.geometry.SpatialReferences import com.esri.arcgisruntime.mapping.ArcGISScene import com.esri.arcgisruntime.mapping.ArcGISTiledElevationSource import com.esri.arcgisruntime.mapping.Basemap import com.esri.arcgisruntime.mapping.Surface import com.esri.arcgisruntime.mapping.view.Camera import com.esri.arcgisruntime.mapping.view.SceneView import com.example.app.databinding.ActivityMainBinding class MainActivity : AppCompatActivity() { private val activityMainBinding: ActivityMainBinding by lazy { ActivityMainBinding.inflate(layoutInflater) } private val sceneView: SceneView by lazy { activityMainBinding.sceneView } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(activityMainBinding.root) setupScene() } override fun onPause() { sceneView.pause() super.onPause() } override fun onResume() { super.onResume() sceneView.resume() } override fun onDestroy() { sceneView.dispose() super.onDestroy() } // set up your scene here. You will call this method from onCreate() private fun setupScene() { // Note: it is not best practice to store API keys in source code. // The API key is referenced here for the convenience of this tutorial. ArcGISRuntimeEnvironment.setApiKey("YOUR_API_KEY") val scene = ArcGISScene(Basemap.createImagery()) // set the scene on the scene view sceneView.scene = scene // add base surface for elevation data val elevationSource = ArcGISTiledElevationSource("https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer") val surface = Surface(listOf(elevationSource)) // add an exaggeration factor to increase the 3D effect of the elevation. surface.elevationExaggeration = 2.5f scene.baseSurface = surface // Point(x, y, z, spatialReference) val cameraLocation = Point(-118.794, 33.909, 5330.0, SpatialReferences.getWgs84()) // Camera(location, heading, pitch, roll) val camera = Camera(cameraLocation, 355.0, 72.0, 0.0) sceneView.setViewpointCamera(camera) } }
Add a scene
Use the scene view to display a scene centered on the Santa Monica Mountains in California. The scene will contain a imagery basemap layer.
In MainActivity.kt, add a new
setupScene()
method in yourMainActivity
class and create anArcGISScene
with an imagery basemap.MainActivity.ktAdd line. 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 67 66 66 66 65 64 63 62 61 60 59 58 57 56 55 54 53 52 51 52 53 54 54 54 54 54 55 56 56 56 56 56 56 56 56 56 56 55 54 54 54 54 54 54 54 54 55 55 55/* * Copyright 2021 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 * * https://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.example.app import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import com.esri.arcgisruntime.ArcGISRuntimeEnvironment import com.esri.arcgisruntime.geometry.Point import com.esri.arcgisruntime.geometry.SpatialReferences import com.esri.arcgisruntime.mapping.ArcGISScene import com.esri.arcgisruntime.mapping.ArcGISTiledElevationSource import com.esri.arcgisruntime.mapping.Basemap import com.esri.arcgisruntime.mapping.Surface import com.esri.arcgisruntime.mapping.view.Camera import com.esri.arcgisruntime.mapping.view.SceneView import com.example.app.databinding.ActivityMainBinding class MainActivity : AppCompatActivity() { private val activityMainBinding: ActivityMainBinding by lazy { ActivityMainBinding.inflate(layoutInflater) } private val sceneView: SceneView by lazy { activityMainBinding.sceneView } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(activityMainBinding.root) setupScene() } override fun onPause() { sceneView.pause() super.onPause() } override fun onResume() { super.onResume() sceneView.resume() } override fun onDestroy() { sceneView.dispose() super.onDestroy() } // set up your scene here. You will call this method from onCreate() private fun setupScene() { // Note: it is not best practice to store API keys in source code. // The API key is referenced here for the convenience of this tutorial. ArcGISRuntimeEnvironment.setApiKey("YOUR_API_KEY") val scene = ArcGISScene(Basemap.createImagery()) // set the scene on the scene view sceneView.scene = scene // add base surface for elevation data val elevationSource = ArcGISTiledElevationSource("https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer") val surface = Surface(listOf(elevationSource)) // add an exaggeration factor to increase the 3D effect of the elevation. surface.elevationExaggeration = 2.5f scene.baseSurface = surface // Point(x, y, z, spatialReference) val cameraLocation = Point(-118.794, 33.909, 5330.0, SpatialReferences.getWgs84()) // Camera(location, heading, pitch, roll) val camera = Camera(cameraLocation, 355.0, 72.0, 0.0) sceneView.setViewpointCamera(camera) } }
Set the
scene
property ofsceneView
to the newArcGISScene
.MainActivity.ktAdd line. Add line. 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 67 66 66 66 65 64 63 62 61 60 59 58 57 56 55 54 53 52 51 52 53 54 54 54 54 54 55 56 57 58 59 59 59 59 59 59 59 58 57 57 57 57 57 57 57 57 58 58 58/* * Copyright 2021 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 * * https://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.example.app import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import com.esri.arcgisruntime.ArcGISRuntimeEnvironment import com.esri.arcgisruntime.geometry.Point import com.esri.arcgisruntime.geometry.SpatialReferences import com.esri.arcgisruntime.mapping.ArcGISScene import com.esri.arcgisruntime.mapping.ArcGISTiledElevationSource import com.esri.arcgisruntime.mapping.Basemap import com.esri.arcgisruntime.mapping.Surface import com.esri.arcgisruntime.mapping.view.Camera import com.esri.arcgisruntime.mapping.view.SceneView import com.example.app.databinding.ActivityMainBinding class MainActivity : AppCompatActivity() { private val activityMainBinding: ActivityMainBinding by lazy { ActivityMainBinding.inflate(layoutInflater) } private val sceneView: SceneView by lazy { activityMainBinding.sceneView } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(activityMainBinding.root) setupScene() } override fun onPause() { sceneView.pause() super.onPause() } override fun onResume() { super.onResume() sceneView.resume() } override fun onDestroy() { sceneView.dispose() super.onDestroy() } // set up your scene here. You will call this method from onCreate() private fun setupScene() { // Note: it is not best practice to store API keys in source code. // The API key is referenced here for the convenience of this tutorial. ArcGISRuntimeEnvironment.setApiKey("YOUR_API_KEY") val scene = ArcGISScene(Basemap.createImagery()) // set the scene on the scene view sceneView.scene = scene // add base surface for elevation data val elevationSource = ArcGISTiledElevationSource("https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer") val surface = Surface(listOf(elevationSource)) // add an exaggeration factor to increase the 3D effect of the elevation. surface.elevationExaggeration = 2.5f scene.baseSurface = surface // Point(x, y, z, spatialReference) val cameraLocation = Point(-118.794, 33.909, 5330.0, SpatialReferences.getWgs84()) // Camera(location, heading, pitch, roll) val camera = Camera(cameraLocation, 355.0, 72.0, 0.0) sceneView.setViewpointCamera(camera) } }
Create a new
ArcGISTiledElevationSource
and use it to create a newSurface
. Then set theelevationExaggeration
property on thesurface
to 2.5f to increate the 3D effect of the elevation.MainActivity.ktAdd line. Add line. Add line. Add line. Add line. Add line. 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 76 75 75 75 74 73 72 71 70 69 68 67 66 65 64 63 62 61 60 60 60 60 59 58 57 56 56 56 57 58 59 60 61 62 63 64 65 64 62 61 60 59 58 57 56 55 55 55 55/* * Copyright 2021 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 * * https://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.example.app import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import com.esri.arcgisruntime.ArcGISRuntimeEnvironment import com.esri.arcgisruntime.geometry.Point import com.esri.arcgisruntime.geometry.SpatialReferences import com.esri.arcgisruntime.mapping.ArcGISScene import com.esri.arcgisruntime.mapping.ArcGISTiledElevationSource import com.esri.arcgisruntime.mapping.Basemap import com.esri.arcgisruntime.mapping.Surface import com.esri.arcgisruntime.mapping.view.Camera import com.esri.arcgisruntime.mapping.view.SceneView import com.example.app.databinding.ActivityMainBinding class MainActivity : AppCompatActivity() { private val activityMainBinding: ActivityMainBinding by lazy { ActivityMainBinding.inflate(layoutInflater) } private val sceneView: SceneView by lazy { activityMainBinding.sceneView } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(activityMainBinding.root) setupScene() } override fun onPause() { sceneView.pause() super.onPause() } override fun onResume() { super.onResume() sceneView.resume() } override fun onDestroy() { sceneView.dispose() super.onDestroy() } // set up your scene here. You will call this method from onCreate() private fun setupScene() { // Note: it is not best practice to store API keys in source code. // The API key is referenced here for the convenience of this tutorial. ArcGISRuntimeEnvironment.setApiKey("YOUR_API_KEY") val scene = ArcGISScene(Basemap.createImagery()) // set the scene on the scene view sceneView.scene = scene // add base surface for elevation data val elevationSource = ArcGISTiledElevationSource("https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer") val surface = Surface(listOf(elevationSource)) // add an exaggeration factor to increase the 3D effect of the elevation. surface.elevationExaggeration = 2.5f scene.baseSurface = surface // Point(x, y, z, spatialReference) val cameraLocation = Point(-118.794, 33.909, 5330.0, SpatialReferences.getWgs84()) // Camera(location, heading, pitch, roll) val camera = Camera(cameraLocation, 355.0, 72.0, 0.0) sceneView.setViewpointCamera(camera) } }
Set the
baseSurface
property of thescene
to thesurface
.MainActivity.ktAdd line. 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 76 75 75 75 74 73 72 71 70 69 68 67 66 65 64 63 62 61 60 60 60 60 59 58 57 56 56 56 57 58 59 60 61 62 63 64 65 66 66 65 64 63 62 61 60 59 59 59 59/* * Copyright 2021 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 * * https://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.example.app import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import com.esri.arcgisruntime.ArcGISRuntimeEnvironment import com.esri.arcgisruntime.geometry.Point import com.esri.arcgisruntime.geometry.SpatialReferences import com.esri.arcgisruntime.mapping.ArcGISScene import com.esri.arcgisruntime.mapping.ArcGISTiledElevationSource import com.esri.arcgisruntime.mapping.Basemap import com.esri.arcgisruntime.mapping.Surface import com.esri.arcgisruntime.mapping.view.Camera import com.esri.arcgisruntime.mapping.view.SceneView import com.example.app.databinding.ActivityMainBinding class MainActivity : AppCompatActivity() { private val activityMainBinding: ActivityMainBinding by lazy { ActivityMainBinding.inflate(layoutInflater) } private val sceneView: SceneView by lazy { activityMainBinding.sceneView } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(activityMainBinding.root) setupScene() } override fun onPause() { sceneView.pause() super.onPause() } override fun onResume() { super.onResume() sceneView.resume() } override fun onDestroy() { sceneView.dispose() super.onDestroy() } // set up your scene here. You will call this method from onCreate() private fun setupScene() { // Note: it is not best practice to store API keys in source code. // The API key is referenced here for the convenience of this tutorial. ArcGISRuntimeEnvironment.setApiKey("YOUR_API_KEY") val scene = ArcGISScene(Basemap.createImagery()) // set the scene on the scene view sceneView.scene = scene // add base surface for elevation data val elevationSource = ArcGISTiledElevationSource("https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer") val surface = Surface(listOf(elevationSource)) // add an exaggeration factor to increase the 3D effect of the elevation. surface.elevationExaggeration = 2.5f scene.baseSurface = surface // Point(x, y, z, spatialReference) val cameraLocation = Point(-118.794, 33.909, 5330.0, SpatialReferences.getWgs84()) // Camera(location, heading, pitch, roll) val camera = Camera(cameraLocation, 355.0, 72.0, 0.0) sceneView.setViewpointCamera(camera) } }
Create a
Point
for the camera and assign it tocameraLocation
. Then create aCamera
, passing thecameraLocation
and values for the camera's heading, pitch, and roll.The position from which you view the scene is defined by a
Camera
. The following properties of the camera are used to define an observation point in the scene:- 3D location: Latitude, longitude, and altitude
- Heading: Azimuth of the camera's direction
- Pitch: Up and down angle
- Roll: Side-to-side angle
MainActivity.ktAdd line. Add line. Add line. Add line. Add line. 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 85 84 84 84 83 82 81 80 79 78 77 76 75 74 73 72 71 70 69 69 69 69 68 67 66 65 65 65 65 65 65 65 65 65 65 65 65 66 67 68 69 70 71 72 72 71 71 71 71/* * Copyright 2021 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 * * https://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.example.app import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import com.esri.arcgisruntime.ArcGISRuntimeEnvironment import com.esri.arcgisruntime.geometry.Point import com.esri.arcgisruntime.geometry.SpatialReferences import com.esri.arcgisruntime.mapping.ArcGISScene import com.esri.arcgisruntime.mapping.ArcGISTiledElevationSource import com.esri.arcgisruntime.mapping.Basemap import com.esri.arcgisruntime.mapping.Surface import com.esri.arcgisruntime.mapping.view.Camera import com.esri.arcgisruntime.mapping.view.SceneView import com.example.app.databinding.ActivityMainBinding class MainActivity : AppCompatActivity() { private val activityMainBinding: ActivityMainBinding by lazy { ActivityMainBinding.inflate(layoutInflater) } private val sceneView: SceneView by lazy { activityMainBinding.sceneView } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(activityMainBinding.root) setupScene() } override fun onPause() { sceneView.pause() super.onPause() } override fun onResume() { super.onResume() sceneView.resume() } override fun onDestroy() { sceneView.dispose() super.onDestroy() } // set up your scene here. You will call this method from onCreate() private fun setupScene() { // Note: it is not best practice to store API keys in source code. // The API key is referenced here for the convenience of this tutorial. ArcGISRuntimeEnvironment.setApiKey("YOUR_API_KEY") val scene = ArcGISScene(Basemap.createImagery()) // set the scene on the scene view sceneView.scene = scene // add base surface for elevation data val elevationSource = ArcGISTiledElevationSource("https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer") val surface = Surface(listOf(elevationSource)) // add an exaggeration factor to increase the 3D effect of the elevation. surface.elevationExaggeration = 2.5f scene.baseSurface = surface // Point(x, y, z, spatialReference) val cameraLocation = Point(-118.794, 33.909, 5330.0, SpatialReferences.getWgs84()) // Camera(location, heading, pitch, roll) val camera = Camera(cameraLocation, 355.0, 72.0, 0.0) sceneView.setViewpointCamera(camera) } }
Call
setViewpointCamera()
on thesceneView
and pass in thecamera
.MainActivity.ktAdd line. 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 85 84 84 84 83 82 81 80 79 78 77 76 75 74 73 72 71 70 69 69 69 69 68 67 66 65 65 65 65 65 65 65 65 65 65 65 65 66 67 68 69 70 71 72 73 73 73 73 73/* * Copyright 2021 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 * * https://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.example.app import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import com.esri.arcgisruntime.ArcGISRuntimeEnvironment import com.esri.arcgisruntime.geometry.Point import com.esri.arcgisruntime.geometry.SpatialReferences import com.esri.arcgisruntime.mapping.ArcGISScene import com.esri.arcgisruntime.mapping.ArcGISTiledElevationSource import com.esri.arcgisruntime.mapping.Basemap import com.esri.arcgisruntime.mapping.Surface import com.esri.arcgisruntime.mapping.view.Camera import com.esri.arcgisruntime.mapping.view.SceneView import com.example.app.databinding.ActivityMainBinding class MainActivity : AppCompatActivity() { private val activityMainBinding: ActivityMainBinding by lazy { ActivityMainBinding.inflate(layoutInflater) } private val sceneView: SceneView by lazy { activityMainBinding.sceneView } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(activityMainBinding.root) setupScene() } override fun onPause() { sceneView.pause() super.onPause() } override fun onResume() { super.onResume() sceneView.resume() } override fun onDestroy() { sceneView.dispose() super.onDestroy() } // set up your scene here. You will call this method from onCreate() private fun setupScene() { // Note: it is not best practice to store API keys in source code. // The API key is referenced here for the convenience of this tutorial. ArcGISRuntimeEnvironment.setApiKey("YOUR_API_KEY") val scene = ArcGISScene(Basemap.createImagery()) // set the scene on the scene view sceneView.scene = scene // add base surface for elevation data val elevationSource = ArcGISTiledElevationSource("https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer") val surface = Surface(listOf(elevationSource)) // add an exaggeration factor to increase the 3D effect of the elevation. surface.elevationExaggeration = 2.5f scene.baseSurface = surface // Point(x, y, z, spatialReference) val cameraLocation = Point(-118.794, 33.909, 5330.0, SpatialReferences.getWgs84()) // Camera(location, heading, pitch, roll) val camera = Camera(cameraLocation, 355.0, 72.0, 0.0) sceneView.setViewpointCamera(camera) } }
In the
onCreate()
method, modify thesetContentView()
call to takeactivityMainBinding.root
as a parameter. Then callsetupScene()
.MainActivity.ktChange line Add line. 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 45 46 47 48 49 50 51 52 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 37 37 37 36 35 34 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33/* * Copyright 2021 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 * * https://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.example.app import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import com.esri.arcgisruntime.ArcGISRuntimeEnvironment import com.esri.arcgisruntime.geometry.Point import com.esri.arcgisruntime.geometry.SpatialReferences import com.esri.arcgisruntime.mapping.ArcGISScene import com.esri.arcgisruntime.mapping.ArcGISTiledElevationSource import com.esri.arcgisruntime.mapping.Basemap import com.esri.arcgisruntime.mapping.Surface import com.esri.arcgisruntime.mapping.view.Camera import com.esri.arcgisruntime.mapping.view.SceneView import com.example.app.databinding.ActivityMainBinding class MainActivity : AppCompatActivity() { private val activityMainBinding: ActivityMainBinding by lazy { ActivityMainBinding.inflate(layoutInflater) } private val sceneView: SceneView by lazy { activityMainBinding.sceneView } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(activityMainBinding.root) setupScene() } override fun onPause() { sceneView.pause() super.onPause() } override fun onResume() { super.onResume() sceneView.resume() } override fun onDestroy() { sceneView.dispose() super.onDestroy() } // set up your scene here. You will call this method from onCreate() private fun setupScene() { // Note: it is not best practice to store API keys in source code. // The API key is referenced here for the convenience of this tutorial. ArcGISRuntimeEnvironment.setApiKey("YOUR_API_KEY") val scene = ArcGISScene(Basemap.createImagery()) // set the scene on the scene view sceneView.scene = scene // add base surface for elevation data val elevationSource = ArcGISTiledElevationSource("https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer") val surface = Surface(listOf(elevationSource)) // add an exaggeration factor to increase the 3D effect of the elevation. surface.elevationExaggeration = 2.5f scene.baseSurface = surface // Point(x, y, z, spatialReference) val cameraLocation = Point(-118.794, 33.909, 5330.0, SpatialReferences.getWgs84()) // Camera(location, heading, pitch, roll) val camera = Camera(cameraLocation, 355.0, 72.0, 0.0) sceneView.setViewpointCamera(camera) } }
Override the Android lifecyle methods
onPause()
,onResume()
, andonDestroy()
to pause, resume and dispose of thesceneView
.The
sceneView
needs to know when your app goes to the background or is restored from background in order to properly manage the view. When the view is no longer needed, its resources should be released with a call todispose
.You can place these methods anywhere inside your
MainActivity
class definition.MainActivity.ktAdd line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 67 67 67 67 66 65 64 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63/* * Copyright 2021 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 * * https://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.example.app import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import com.esri.arcgisruntime.ArcGISRuntimeEnvironment import com.esri.arcgisruntime.geometry.Point import com.esri.arcgisruntime.geometry.SpatialReferences import com.esri.arcgisruntime.mapping.ArcGISScene import com.esri.arcgisruntime.mapping.ArcGISTiledElevationSource import com.esri.arcgisruntime.mapping.Basemap import com.esri.arcgisruntime.mapping.Surface import com.esri.arcgisruntime.mapping.view.Camera import com.esri.arcgisruntime.mapping.view.SceneView import com.example.app.databinding.ActivityMainBinding class MainActivity : AppCompatActivity() { private val activityMainBinding: ActivityMainBinding by lazy { ActivityMainBinding.inflate(layoutInflater) } private val sceneView: SceneView by lazy { activityMainBinding.sceneView } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(activityMainBinding.root) setupScene() } override fun onPause() { sceneView.pause() super.onPause() } override fun onResume() { super.onResume() sceneView.resume() } override fun onDestroy() { sceneView.dispose() super.onDestroy() } // set up your scene here. You will call this method from onCreate() private fun setupScene() { // Note: it is not best practice to store API keys in source code. // The API key is referenced here for the convenience of this tutorial. ArcGISRuntimeEnvironment.setApiKey("YOUR_API_KEY") val scene = ArcGISScene(Basemap.createImagery()) // set the scene on the scene view sceneView.scene = scene // add base surface for elevation data val elevationSource = ArcGISTiledElevationSource("https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer") val surface = Surface(listOf(elevationSource)) // add an exaggeration factor to increase the 3D effect of the elevation. surface.elevationExaggeration = 2.5f scene.baseSurface = surface // Point(x, y, z, spatialReference) val cameraLocation = Point(-118.794, 33.909, 5330.0, SpatialReferences.getWgs84()) // Camera(location, heading, pitch, roll) val camera = Camera(cameraLocation, 355.0, 72.0, 0.0) sceneView.setViewpointCamera(camera) } }
Set your API key
An API key is required to enable access to services, web maps, and web scenes hosted in ArcGIS Online.If you haven't already, go to your developer dashboard to get your API key. For these tutorials, use your default API key. It is scoped to include all of the services demonstrated in the tutorials.
Before running your app, set the
apiKey
property on theArcGISRuntimeEnvironment
using the API Key.MainActivity.ktAdd line. Add line. Add line. 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 69 70 71 72 73 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74/* * Copyright 2021 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 * * https://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.example.app import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import com.esri.arcgisruntime.ArcGISRuntimeEnvironment import com.esri.arcgisruntime.geometry.Point import com.esri.arcgisruntime.geometry.SpatialReferences import com.esri.arcgisruntime.mapping.ArcGISScene import com.esri.arcgisruntime.mapping.ArcGISTiledElevationSource import com.esri.arcgisruntime.mapping.Basemap import com.esri.arcgisruntime.mapping.Surface import com.esri.arcgisruntime.mapping.view.Camera import com.esri.arcgisruntime.mapping.view.SceneView import com.example.app.databinding.ActivityMainBinding class MainActivity : AppCompatActivity() { private val activityMainBinding: ActivityMainBinding by lazy { ActivityMainBinding.inflate(layoutInflater) } private val sceneView: SceneView by lazy { activityMainBinding.sceneView } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(activityMainBinding.root) setupScene() } override fun onPause() { sceneView.pause() super.onPause() } override fun onResume() { super.onResume() sceneView.resume() } override fun onDestroy() { sceneView.dispose() super.onDestroy() } // set up your scene here. You will call this method from onCreate() private fun setupScene() { // Note: it is not best practice to store API keys in source code. // The API key is referenced here for the convenience of this tutorial. ArcGISRuntimeEnvironment.setApiKey("YOUR_API_KEY") val scene = ArcGISScene(Basemap.createImagery()) // set the scene on the scene view sceneView.scene = scene // add base surface for elevation data val elevationSource = ArcGISTiledElevationSource("https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer") val surface = Surface(listOf(elevationSource)) // add an exaggeration factor to increase the 3D effect of the elevation. surface.elevationExaggeration = 2.5f scene.baseSurface = surface // Point(x, y, z, spatialReference) val cameraLocation = Point(-118.794, 33.909, 5330.0, SpatialReferences.getWgs84()) // Camera(location, heading, pitch, roll) val camera = Camera(cameraLocation, 355.0, 72.0, 0.0) sceneView.setViewpointCamera(camera) } }
Click Run > Run > app to run the app.
An emulator should display, running your app.
If your app builds but no emulator displays, you need to add an emulator. Click Tools > AVD Manager > Create Virtual Device...
You should see a scene with the imagery basemap layer centered on the Santa Monica Mountains in California. Pinch, drag, and double-tap the scene view to explore the scene.
What's next?
Learn how to use additional API features, ArcGIS platform services, and ArcGIS tools in these tutorials: