HttpURLConnection and expired tokens

1797
2
04-13-2017 02:00 PM
by Anonymous User
Not applicable

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
Occasional Contributor III

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
by Anonymous User
Not applicable

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();
}