ArcGISRuntimeException: Cannot call this method in this context when doing exportTile from Android

3416
7
Jump to solution
10-09-2017 06:54 AM
JasonChristian
New Contributor II

Hi,

I am currently using the ExportTileCacheTask to export a tpk file from http://services.arcgisonline.com/arcgis/rest/services/World_Street_Map/MapServer

Following the sample: arcgis-runtime-samples-android/export-tiles at master · Esri/arcgis-runtime-samples-android · GitHub 

The problem is, it crashes with exception

java.util.concurrent.ExecutionException: com.esri.arcgisruntime.ArcGISRuntimeException: Cannot call this method in this context

The exception is thrown on the line similar to line 211 of the sample

ExportTileCacheParameters parameters = parametersFuture.get();

Here's the full exception log:

10-09 15:50:40.182 12160-12160/package W/System.err: java.util.concurrent.ExecutionException: com.esri.arcgisruntime.ArcGISRuntimeException: Cannot call this method in this context
10-09 15:50:40.182 12160-12160/package W/System.err:     at com.esri.arcgisruntime.internal.a.b.get(SourceFile:128)
10-09 15:50:40.182 12160-12160/package W/System.err:     at de.maengelmelder.mainmodule.activities.MapCachingActivity$doRetrieveMapCache$1.run(MapCachingActivity.kt:184)
10-09 15:50:40.182 12160-12160/package W/System.err:     at android.os.Handler.handleCallback(Handler.java:739)
10-09 15:50:40.182 12160-12160/package W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:95)
10-09 15:50:40.192 12160-12160/package W/System.err:     at android.os.Looper.loop(Looper.java:145)
10-09 15:50:40.192 12160-12160/package W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:5951)
10-09 15:50:40.192 12160-12160/package W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
10-09 15:50:40.192 12160-12160/package W/System.err:     at java.lang.reflect.Method.invoke(Method.java:372)
10-09 15:50:40.192 12160-12160/package W/System.err:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1400)
10-09 15:50:40.192 12160-12160/package W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1195)
10-09 15:50:40.192 12160-12160/package W/System.err: Caused by: com.esri.arcgisruntime.ArcGISRuntimeException: Cannot call this method in this context
10-09 15:50:40.192 12160-12160/package W/System.err:     at com.esri.arcgisruntime.internal.a.b.get(SourceFile:120)
10-09 15:50:40.192 12160-12160/package W/System.err:     ... 9 more

There's no more indication of the error or the cause of it.

Any possible cause or solution?

Thanks before,

Jason

0 Kudos
1 Solution

Accepted Solutions
AlexanderNohe1
Occasional Contributor III

I imagine using the sample server might be part of the problem.

I do not think this is equipped to handle that type of call as it would need an export tiles call on the service.  I know this service is equipped to handle the request:

https://tiledbasemaps.arcgis.com/arcgis/rest/services/World_Topo_Map/MapServer/

I hope this helps!

View solution in original post

0 Kudos
7 Replies
AlexanderNohe1
Occasional Contributor III

On your ExportTileCacheTask, did you call loadAsync prior to calling get()?  I would also place the get in the DoneLoadingListener section as well.

0 Kudos
JasonChristian
New Contributor II

Hi, thank you for the reply.

The problem still persists. I have added the exportTask.loadAsync() after adding exportTask.addDoneLoadingListener() and it's still showing the same error on the get() method. Here's the overview of my code (in Kotlin):

val env = viewToExtent() // Similar to the sample
val minScale = 10000.0 // 1 : 10000
val maxScale = 1000.0 // 1 : 1000
val url = "http://services.arcgisonline.com/arcgis/rest/services/World_Street_Map/MapServer"

val exportTask = ExportTileCacheTask(url)
exportTask.addDoneLoadingListener{
   val future = exportTask.createDefaultExportTileCacheParametersAsync(env, minScale, maxScale)
   future.addDoneListener {
      val params = future.get() // ArcGISRunTimeException: Cannot call this method..
      ...
      ...  
   }
}
exportTask.loadAsync()

EDIT: I noticed that there's a setCredential() method from the ExportTileCacheTask. 
I have not used that (and the sample uses sampleserver rather than actual ArcGIS service). Might that be the problem?
EDIT 2: Tried adding UserCredential(username, password) to the ExportTileCacheTask.setCredential(). Still the same problem
0 Kudos
AlexanderNohe1
Occasional Contributor III

I imagine using the sample server might be part of the problem.

I do not think this is equipped to handle that type of call as it would need an export tiles call on the service.  I know this service is equipped to handle the request:

https://tiledbasemaps.arcgis.com/arcgis/rest/services/World_Topo_Map/MapServer/

I hope this helps!

0 Kudos
JasonChristian
New Contributor II

Thanks for the reply. It works with this URL and the credential supplied. I didn't realize the ArcGIS online service does not have exportTiles method

Perhaps the developers for runtime SDK can make more meaningful error message than "java.util.concurrent.ExecutionException: com.esri.arcgisruntime.ArcGISRuntimeException: Cannot call this method in this context"

For others who faced the same problem, here's the snippet in Kotlin

val env = viewToExtent() // Similar to the sample
val minScale = 10000.0 // 1 : 10000
val maxScale = 1000.0 // 1 : 1000. Make sure maxScale < minScale
val filepath = "sdcard/mymap/test.tpk" // Path to your map file. Make sure the directories are already created
val url = "https://tiledbasemaps.arcgis.com/arcgis/rest/services/World_Topo_Map/MapServer/"

val exportTask = ExportTileCacheTask(url)
// Set the credentials, because the tiledbasemap service requires auth
exportTask.setCredential(UserCredential("<your-username>", "<your-password>"))
exportTask.addDoneLoadingListener{
   val future = exportTask.createDefaultExportTileCacheParametersAsync(env, minScale, maxScale)
   future.addDoneListener {
      // Get parameter
      val params = future.get()

      // Create export job with the given param and filepath. The actual download and export happen here
      val exportJob = exportTask.exportTileCacheAsync(params, filepath)

      // If you care about the status of your job
      exportJob.addJobChangedListener { Log.i("INFO", "jobInfo: ${exportJob.messages.last().message}") }

      // When the job is done    
      exportJob.addJobDoneListener { 
         val result = job.result
         if (result != null) {
            // Success. The tpk file is saved to the supplied file path. The result contains the info about the TPK file
         } else {
            // Failed. Perhaps due to the above error, or the tpk size is too big (Dunno the exact limit)  
         }
      }  

      // Start the job
      exportJob.start()
   }
}

exportTask.loadAsync()

Also, another bit of a problem. I noticed that the Envelope class is not serialized (or is it?).
So, is it not possible to pass the Envelope inside an Intent, to be sent to a Service / another Activity?

Thanks again for the quick response,
Jason
AlexanderNohe1
Occasional Contributor III

There is a toJson() and fromJson() method so you can construct it from a Parcelable or even put it into the Intent extras.

0 Kudos
JasonChristian
New Contributor II

Ah very nice. Thank you

0 Kudos
AlexanderNohe1
Occasional Contributor III

No problem.  Happy to help.  I will forward the suggestion about descriptive error messages internally and hopefully we will see some positive results.