Update regarding branching and versioning of maps

966
5
Jump to solution
08-11-2021 11:52 AM
Latheesh
New Contributor II

Can someone help me regarding branching and versioning of the app? As i am using the servicegeodatabase it is throwing an error it must be loaded. Do we need any requirements to use servicegeodatabase

0 Kudos
1 Solution

Accepted Solutions
FinlayPearson
New Contributor

Hello @Latheesh I think the immediate error you are seeing is caused by a mistake in the code. I have reproduced the code above and I see the following stack trace:

 

Spoiler
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.esri.arcgisruntime.app.runWithAndroidAPIAndDailyBuild/com.esri.arcgisruntime.app.MainActivity}: com.esri.arcgisruntime.ArcGISRuntimeException: Invalid call.: ServiceGeodatabase must be loaded
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3654)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3806)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2267)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:237)
at android.app.ActivityThread.main(ActivityThread.java:8154)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:496)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1100)
Caused by: com.esri.arcgisruntime.ArcGISRuntimeException: Invalid call.: ServiceGeodatabase must be loaded
at com.esri.arcgisruntime.internal.jni.CoreServiceGeodatabase.nativeGetTable(Native Method)
at com.esri.arcgisruntime.internal.jni.CoreServiceGeodatabase.b(SourceFile:2)
at com.esri.arcgisruntime.data.ServiceGeodatabase.getTable(SourceFile:1)
at com.esri.arcgisruntime.app.MainActivity.onCreate(MainActivity.kt:42)
at android.app.Activity.performCreate(Activity.java:7963)
at android.app.Activity.performCreate(Activity.java:7952)

The immediate stack trace is not very helpful but further down we see:

Caused by: com.esri.arcgisruntime.ArcGISRuntimeException: Invalid call.: ServiceGeodatabase must be loaded
at com.esri.arcgisruntime.internal.jni.CoreServiceGeodatabase.nativeGetTable(Native Method)
at com.esri.arcgisruntime.internal.jni.CoreServiceGeodatabase.b(SourceFile:2)
at com.esri.arcgisruntime.data.ServiceGeodatabase.getTable(SourceFile:1)
at com.esri.arcgisruntime.app.MainActivity.onCreate(MainActivity.kt:42)

So the error is caused by the getTable call. getTable can only be called once the ServiceGeodatabase has been loaded, so the call must be placed in the addDoneLoadingListener.

Doing so stops the app from crashing but the ServiceGeodatabase still fails to load with the following load error:

Service Geodatabase failed to load: com.esri.arcgisruntime.ArcGISRuntimeException: Invalid argument.: Cannot load a non-versioned service with a version name, null

(Note: in order to see the full error, you need to change your logging code to print out the exception as well as its cause. Sometimes, exceptions do not have causes. You can make the following change:)

Log.e("Tag", "Service Geodatabase failed to load: ${it}, ${it.cause}")

 

To fix this, the ServiceGeodatabase constructor should be changed so that it does not specify a versionName parameter (see below discussion about branch versioning). After making this change, the layer in that service table can be displayed on a map successfully. I have included a full code snippet below, which should load the ServiceGeodatabase's layer on a map, and display it on the screen, although you must also create a corresponding layout which contains a MapView with id mapView.

import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import com.esri.arcgisruntime.mapping.ArcGISMap
import com.esri.arcgisruntime.mapping.Basemap
import kotlinx.android.synthetic.main.activity_main.*
import com.esri.arcgisruntime.data.ServiceGeodatabase
import com.esri.arcgisruntime.layers.FeatureLayer
import com.esri.arcgisruntime.loadable.LoadStatus

class MainActivity : AppCompatActivity() {

    // Keep ServiceGeodatabase as a field in the class so that it doesn't get
    // garbage collected while it is being loaded.
    private lateinit var mServiceGeodatabase: ServiceGeodatabase

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        mapView.map = ArcGISMap(Basemap.createDarkGrayCanvasVector())

        mServiceGeodatabase = ServiceGeodatabase(
            "https://services3.arcgis.com/df7XtT0Re4z8S561/arcgis/rest/services/Chimpanzee/FeatureServer"
        )
        // ServiceGeodatabase is a Loadable, so we must trigger its loading before we can use it.
        mServiceGeodatabase.loadAsync()
        mServiceGeodatabase.addDoneLoadingListener {
            if (mServiceGeodatabase.loadStatus != LoadStatus.LOADED) {
                mServiceGeodatabase.loadError?.let {
                    Log.e("Tag", "Service Geodatabase failed to load: ${it}, ${it.cause}")
                }
                return@addDoneLoadingListener
            }

            Log.i("Tag", "ServiceGeodatabase loaded")
            // Code for getting the table is now here inside the doneLoadingListener.
            val serviceFeatureTable = mServiceGeodatabase.getTable(0)
            val layer = FeatureLayer(serviceFeatureTable)
            mapView.map.operationalLayers.add(layer)
        }
        // Any code placed below the listener will most-likely happen _before_ the listener code
        // is executed, since the listener code waits for the Geodatabase to load -- it is asynchronous.
    }

    override fun onResume() {
        super.onResume()
        mapView.resume()
    }

    override fun onPause() {
        mapView.pause()
        super.onPause()
    }

    override fun onDestroy() {
        mapView.dispose()
        super.onDestroy()
    }
}

 

Regarding branch versioning, I can direct you to this Android sample which explains the process and gives an example.

I hope this helps 🙂

View solution in original post

0 Kudos
5 Replies
by Anonymous User
Not applicable

Hi @Latheesh , 

do you have a picture of the error? 

also, how did you configure this, generally you connect to the sde. connection for branch versioning in ArcGIS Pro and in the web apps

Are you using a web app or experience builder widget? If you are using the Experience builder, this page may be useful 

Branch Version Management widget—ArcGIS Experience Builder | Documentation

0 Kudos
Latheesh
New Contributor II

Hi I am using mobile application to implement the branch versioning. 

serviceGeodatabase=ServiceGeodatabase("https://services3.arcgis.com/df7XtT0Re4z8S561/arcgis/rest/services/Chimpanzee/FeatureServer","1")

  serviceGeodatabase.addDoneLoadingListener {
if (serviceGeodatabase.loadStatus != LoadStatus.LOADED) {
serviceGeodatabase.loadError?.let {
Log.e("Tag", "Service Geodatabase failed to load: ${it.cause}")
}
return@addDoneLoadingListener
}
}
serviceFeatureTable=serviceGeodatabase.getTable(0)
It is showing error saying servicegeodatabase must be loaded in the error
0 Kudos
FinlayPearson
New Contributor

Hello @Latheesh I think the immediate error you are seeing is caused by a mistake in the code. I have reproduced the code above and I see the following stack trace:

 

Spoiler
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.esri.arcgisruntime.app.runWithAndroidAPIAndDailyBuild/com.esri.arcgisruntime.app.MainActivity}: com.esri.arcgisruntime.ArcGISRuntimeException: Invalid call.: ServiceGeodatabase must be loaded
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3654)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3806)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2267)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:237)
at android.app.ActivityThread.main(ActivityThread.java:8154)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:496)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1100)
Caused by: com.esri.arcgisruntime.ArcGISRuntimeException: Invalid call.: ServiceGeodatabase must be loaded
at com.esri.arcgisruntime.internal.jni.CoreServiceGeodatabase.nativeGetTable(Native Method)
at com.esri.arcgisruntime.internal.jni.CoreServiceGeodatabase.b(SourceFile:2)
at com.esri.arcgisruntime.data.ServiceGeodatabase.getTable(SourceFile:1)
at com.esri.arcgisruntime.app.MainActivity.onCreate(MainActivity.kt:42)
at android.app.Activity.performCreate(Activity.java:7963)
at android.app.Activity.performCreate(Activity.java:7952)

The immediate stack trace is not very helpful but further down we see:

Caused by: com.esri.arcgisruntime.ArcGISRuntimeException: Invalid call.: ServiceGeodatabase must be loaded
at com.esri.arcgisruntime.internal.jni.CoreServiceGeodatabase.nativeGetTable(Native Method)
at com.esri.arcgisruntime.internal.jni.CoreServiceGeodatabase.b(SourceFile:2)
at com.esri.arcgisruntime.data.ServiceGeodatabase.getTable(SourceFile:1)
at com.esri.arcgisruntime.app.MainActivity.onCreate(MainActivity.kt:42)

So the error is caused by the getTable call. getTable can only be called once the ServiceGeodatabase has been loaded, so the call must be placed in the addDoneLoadingListener.

Doing so stops the app from crashing but the ServiceGeodatabase still fails to load with the following load error:

Service Geodatabase failed to load: com.esri.arcgisruntime.ArcGISRuntimeException: Invalid argument.: Cannot load a non-versioned service with a version name, null

(Note: in order to see the full error, you need to change your logging code to print out the exception as well as its cause. Sometimes, exceptions do not have causes. You can make the following change:)

Log.e("Tag", "Service Geodatabase failed to load: ${it}, ${it.cause}")

 

To fix this, the ServiceGeodatabase constructor should be changed so that it does not specify a versionName parameter (see below discussion about branch versioning). After making this change, the layer in that service table can be displayed on a map successfully. I have included a full code snippet below, which should load the ServiceGeodatabase's layer on a map, and display it on the screen, although you must also create a corresponding layout which contains a MapView with id mapView.

import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import com.esri.arcgisruntime.mapping.ArcGISMap
import com.esri.arcgisruntime.mapping.Basemap
import kotlinx.android.synthetic.main.activity_main.*
import com.esri.arcgisruntime.data.ServiceGeodatabase
import com.esri.arcgisruntime.layers.FeatureLayer
import com.esri.arcgisruntime.loadable.LoadStatus

class MainActivity : AppCompatActivity() {

    // Keep ServiceGeodatabase as a field in the class so that it doesn't get
    // garbage collected while it is being loaded.
    private lateinit var mServiceGeodatabase: ServiceGeodatabase

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        mapView.map = ArcGISMap(Basemap.createDarkGrayCanvasVector())

        mServiceGeodatabase = ServiceGeodatabase(
            "https://services3.arcgis.com/df7XtT0Re4z8S561/arcgis/rest/services/Chimpanzee/FeatureServer"
        )
        // ServiceGeodatabase is a Loadable, so we must trigger its loading before we can use it.
        mServiceGeodatabase.loadAsync()
        mServiceGeodatabase.addDoneLoadingListener {
            if (mServiceGeodatabase.loadStatus != LoadStatus.LOADED) {
                mServiceGeodatabase.loadError?.let {
                    Log.e("Tag", "Service Geodatabase failed to load: ${it}, ${it.cause}")
                }
                return@addDoneLoadingListener
            }

            Log.i("Tag", "ServiceGeodatabase loaded")
            // Code for getting the table is now here inside the doneLoadingListener.
            val serviceFeatureTable = mServiceGeodatabase.getTable(0)
            val layer = FeatureLayer(serviceFeatureTable)
            mapView.map.operationalLayers.add(layer)
        }
        // Any code placed below the listener will most-likely happen _before_ the listener code
        // is executed, since the listener code waits for the Geodatabase to load -- it is asynchronous.
    }

    override fun onResume() {
        super.onResume()
        mapView.resume()
    }

    override fun onPause() {
        mapView.pause()
        super.onPause()
    }

    override fun onDestroy() {
        mapView.dispose()
        super.onDestroy()
    }
}

 

Regarding branch versioning, I can direct you to this Android sample which explains the process and gives an example.

I hope this helps 🙂

0 Kudos
Latheesh
New Contributor II

 @FinlayPearson Thank you so much for helping with the detailed explanation. You guys are awesome in responding to queries.

Latheesh
New Contributor II

Do we need to setup any additional from arcgis to get access for servicegeodatabase aside from the mobile application side?

0 Kudos