HttpURLConnection and expired tokens

1419
2
04-13-2017 02:00 PM
AaronDick
Occasional Contributor

I am trying to access a TPK for download using HttpURLConnection.  The reason I am doing it this way versus 

InputStream is = item.fetchData();

is because i want to be able to resume download by setting a Range in Bytes to resume download when a network connection is available again.

Issue is this.  I can download a TPK right after logging into the application (before token expires) with the following code...

requestUrl = portal.getUrl() + "/sharing/rest/content/items/" + itemID + "/data?token=" + mValidLoginCredentials.getToken();
URL url2 = new URL(requestUrl);
HttpURLConnection urlConnection = (HttpURLConnection) url2.openConnection();
urlConnection.setRequestProperty("Range", "bytes=" + (baseMapFile.length()) + "-");
urlConnection.setRequestProperty("If-Range", lastModified);
inputStream = new BufferedInputStream(urlConnection.getInputStream(), 16384);

I am wondering how I can regenerate a token from credentials so that I can provide the new token into the requestURL variable.
I have tried a couple of things that do not work...

1.  Trying to setUserToken then use it does not work
portal.getCredentials().setUserToken(mValidLoginCredentials.getToken(), portal.getUrl());
requestUrl = portal.getUrl() + "/sharing/rest/content/items/" + itemID + "/data?token=" + portal.getCredentials().getToken();
2. Trying to generate token. Probably bad syntax here...
requestUrl = portal.getUrl() + "/sharing/rest/content/items/" + itemID + "/data?token=tokens/generateToken?username=mMouse&password=****;

I am pretty sure it is some sort of syntax issue here.  Any advice greatly appreciated.  Am using Runtime SDK Android 10.2.9.

0 Kudos
2 Replies
AlexanderNohe1
Regular Contributor II

Hi Aaron Dick‌,

What you could do is when you launch the app, is load your stored serialized credentials and using a new UserCredentials class UserCredentials | ArcGIS Android 10.2.9 API, all the setUserAccount(String userName, String password) method and then subsequently call the getToken() method on the object so you can get a new valid token.  You look to be trying to generate a token manually through a rest call but using the SDK might be a better way to go here.

Thanks,

Alexander

0 Kudos
AaronDick
Occasional Contributor

Thanks Alex, this advise helped me get on the right track with this.  

The critical bit was to use the credentials with PortalItem.fetchItem to establish a new token.

Portal portal = new Portal(url, uc);
PortalItem item = PortalItem.fetchItem(portal, itemID);

If anyone ever runs into issues trying to download  from AGOL via HttpURLConnection using token authentication below is the code that worked.....

try {
   // Fetch the portal item by ID, and the data, passing in a Portal with an
   // authenticated user with access to the item.
   String url = "https://www.arcgis.com";
   UserCredentials uc = new UserCredentials();
   uc = mValidLoginCredentials;
   Portal portal = new Portal(url, uc);
   PortalItem item = PortalItem.fetchItem(portal, itemID);
   String requestUrl = portal.getUrl() + "/sharing/rest/content/items/" + itemID + "/data";
   if(mValidLoginCredentials!=null) {
      String token = portal.getCredentials().getToken();
      requestUrl = portal.getUrl() + "/sharing/rest/content/items/" + itemID + "/data?token=" + token;
   }

   URL url2 = new URL(requestUrl);
   HttpURLConnection urlConnection = (HttpURLConnection) url2.openConnection();
   filePath = dataWorkingDirectory + "/Offline_Base_Maps/" + item.getName();
   TPKPath = filePath;
   int len = 0;
   //Check if file exists already
   File baseMapFile = new File(filePath);
   int length = 0;

   if (baseMapFile.exists()) {
      length = (int) baseMapFile.length();

         if (length==0) {
            lastModified = urlConnection.getHeaderField("Last-Modified");
            inputStream = new BufferedInputStream(urlConnection.getInputStream(), 16384);
            file_size = urlConnection.getContentLength();
         }else{

            urlConnection.setRequestProperty("Range", "bytes=" + (baseMapFile.length()) + "-");
            urlConnection.setRequestProperty("If-Range", lastModified);
            inputStream = new BufferedInputStream(urlConnection.getInputStream(), 16384);
         }


   }else{
      lastModified = urlConnection.getHeaderField("Last-Modified");
      inputStream = new BufferedInputStream(urlConnection.getInputStream(), 16384);
      file_size = urlConnection.getContentLength();
   }

   long fileLength = Long.valueOf(file_size);
   int latestPercentDone;
   int lastPercentDone = 0;
   // Save the data to a file.
   outputStream =(length==0)? new FileOutputStream(filePath😞 new FileOutputStream(filePath,true);
   byte[] buf = new byte[16384];
   int size = 0;

   while ((len = inputStream.read(buf)) != -1) {
      outputStream.write(buf, 0, len);
      length += len;
      latestPercentDone = (int) Math.round(length * 100.0 / fileLength);
      if (lastPercentDone != latestPercentDone) {
         publishProgress(latestPercentDone);
      }
      lastPercentDone = latestPercentDone;

   }
   mNotificationHelper.completed();
   outputStream.flush();
   outputStream.close();
   inputStream.close();
   error = "done";
} catch (Exception e) {
   e.printStackTrace();
}