arcgis-runtime-samples-android icon indicating copy to clipboard operation
arcgis-runtime-samples-android copied to clipboard

Authentication and Offline Tile Packages

Open billmyers opened this issue 7 years ago • 13 comments

I asked this question on GeoNet but haven't received any responses...

"I have a registered app (with client id and secret id). I want to enable users to download tiled map packages from the app ex: (https://tiledbasemaps.arcgis.com/arcgis/rest/services/USA_Topo_Maps/MapServer)... How do I use the new authentication patterns in version 100 to do an "app" login without having to present the user with the login screen. My users will not have logins to ArcGIS online or portal."

billmyers avatar Apr 21 '17 15:04 billmyers

Have you reviewed this topic in the Guide: https://developers.arcgis.com/android/latest/guide/access-the-arcgis-platform.htm#ESRI_SECTION1_2513881AFEDD4B1688E614554463EB71 ?

Does it help? Let us know...

eric906 avatar Apr 21 '17 15:04 eric906

I have... but I couldn't get the code figured out. A code sample or pseudo-code sample would be very helpful. Thanks.

billmyers avatar Apr 21 '17 15:04 billmyers

Agreed! Apologies for not having this more clear for you. We will work to get something for you on this. Thank you!

eric906 avatar Apr 21 '17 15:04 eric906

Thanks. That's awesome!

billmyers avatar Apr 21 '17 16:04 billmyers

Just following up to see if you have had a chance to look at this issue. Thanks. -Bill

billmyers avatar Apr 27 '17 16:04 billmyers

We are still trying to put this together. I apologize for the delay. Stay tuned....

eric906 avatar Apr 27 '17 17:04 eric906

Hi Bill,

Looks like we've hit a current limitation in 100.0. One approach is to have a proxy in the mix, which gives your app a token, based on a set of credentials, without having those credentials baked into the app, is highly not recommended. I apologize for the delay in getting back to you. This is taking some time verifying that it will work for you. Stay tuned, though.

eric906 avatar May 01 '17 14:05 eric906

Thanks for the update.

billmyers avatar May 02 '17 13:05 billmyers

Can someone guide me how to use .tpk file usuing android runtime api version 100.0? Thanks

adnanmacro avatar May 11 '17 10:05 adnanmacro

@adnanmacro Use a TileCache.

doneill avatar May 17 '17 03:05 doneill

Here's code I developed based on examples in the docs using the OAuthLoginManager... Even though I get logged in I'm getting the following error when I try to export a tile cache: "Job error 498 Invalid Token"

static final String TILE_URL_USA_TOPO = "https://tiledbasemaps.arcgis.com/arcgis/rest/services/USA_Topo_Maps/MapServer";

    private void appLogin() {
        Log.d("MyApp", "login");
        try {
            oauthLoginManager = new OAuthLoginManager("https://www.arcgis.com/", getString(R.string.arcgis_app_id), getString(R.string.redirect_uri), 0);
            oauthLoginManager.launchOAuthBrowserPage(getApplicationContext());
        } catch (Exception e) {
            Log.e("error-", e.getMessage() + "");
        }
    }

    private void fetchCredentials(Intent intent) {
        // Fetch oauth access token.
        final ListenableFuture<OAuthTokenCredential> future = oauthLoginManager.fetchOAuthTokenCredentialAsync(intent);
        future.addDoneListener(new Runnable() {
            @Override
            public void run() {
                try {
                    oauthCred = future.get();
                    Log.d("MyApp", oauthCred.getUsername());
                    downloadMapTPK2();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

private void downloadMapTPK2() {
        Log.d("MyApp","Running ExportTileCacheJob");
        //extent
        Envelope mapExtent = Util.getMapExtent(mMapView);

        //Storage path for offline tiles
        DEFAULT_BASEMAP_PATH = getString(R.string.offline_dir);
        mDefaultPath = Environment.getExternalStorageDirectory().getPath() + DEFAULT_BASEMAP_PATH;
        File directory = new File(mDefaultPath);
        if (!directory.exists()) {
            directory.mkdirs();
        }
        final String tileCachePath = mDefaultPath + "topo.tpk";

        //Tile Cache
        // Create the export tile cache
        ExportTileCacheTask exportTilesTask = new ExportTileCacheTask(TILE_URL_USA_TOPO);
        exportTilesTask.setCredential(oauthCred);
        Log.d("MyApp",oauthCred.toJson());

        // Define the parameters for the new tile cache - in this case, using the parameter object constructor
        ExportTileCacheParameters exportTilesParameters = new ExportTileCacheParameters();
        //exportTilesParameters.getLevelIDs().addAll(Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9));
        exportTilesParameters.setAreaOfInterest(mapExtent);

        // Create the export task, passing in parameters, and file path ending in ".tpk"
        final ExportTileCacheJob exportJob = exportTilesTask.exportTileCacheAsync(exportTilesParameters, tileCachePath);
        exportJob.setCredential(oauthCred);

        exportJob.addJobChangedListener(new Runnable() {
            @Override
            public void run() {
                List<Job.Message> messages = exportJob.getMessages();
                //updateUiWithProgress(messages.get(messages.size() - 1).getMessage());
                Log.d("MyApp",messages.get(messages.size() - 1).getMessage());
            }
        });

        // Listen for when the job is completed
        exportJob.addJobDoneListener(new Runnable() {
            @Override
            public void run() {
                if (exportJob.getError() != null) {
                    //dealWithException(exportJob.getError()); // deal with exception appropriately...
                    Log.d("MyApp",exportJob.getError().getAdditionalMessage());
                    return;
                }

                if (exportJob.getStatus() == Job.Status.SUCCEEDED) {
                    Log.d("MyApp","Download Succeeded");
                    final TileCache exportedTileCache = exportJob.getResult();
                    ArcGISTiledLayer tiledLayer = new ArcGISTiledLayer(exportedTileCache);
                    mMapView.getMap().getOperationalLayers().add(tiledLayer);
                }
            }
        });

// Start the ExportTileCacheJob
        exportJob.start();
    }

billmyers avatar May 23 '17 16:05 billmyers

Just checking in to see if there are any updates or news on this issue?

billmyers avatar Jun 16 '17 14:06 billmyers

I ran across this issue while I was trying to find a solution to the same problem, so I figured I would add what worked for me:

  1. Generate a temporary token; I did this via HTTP request, see: https://developers.arcgis.com/documentation/core-concepts/security-and-authentication/accessing-arcgis-online-services/

  2. Encode the token and put it in the service url as a parameter: exportUrl = tileServiceUrl + "?token=" + URLEncoder.encode(token, StandardCharsets.UTF_8.name());

barnonahill avatar Nov 08 '18 22:11 barnonahill