Android Developer Guide
Build an Android app with a PDA backend

Overview

In order to build an Android app that uses HAT APIs you first need to install the HAT API Android library from github. To do so you can either manually download the library and add it to your project or you can use maven.

Requirements

  • Android studio 3.2
  • Kotlin 1.3
  • In this guide there is no mention how to set up the UI, so you have to be able to design a basic UI in order to make everything work

Install manually

In order to manually install the library you have to download the repo from github and add it to your project via drag n drop.

Install via Gradle

Step 1
In the top-level gradle file, add the jitpack repository link
1
allprojects {
2
repositories {
3
maven { url "https://jitpack.io" }
4
}
5
}
Copied!
Step 2
In your app level gradle file , implement the library dependency
1
implementation 'com.hubofallthings.android.hatApi:hat:<latest-version>'
Copied!
Step 3
Sync the project to download the library.
Step 4
Add internet permission into the AndroidManifest
1
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
2
package="com.hubofallthings.myProject">
3
<uses-permission android:name="android.permission.INTERNET" />
Copied!

Using the library

HAT-API-Android provides features that make your app to be able to authenticate with the PDA, read/write to the PDA, fetch and setup Data Plugs and Applications, fetch Data debits and use advanced features like Combinators and Bundles.

Authenticate with PDA

The PDA is an API-only service, meaning it does not enforce a specific Application or User Interface to expose the data to the user. Instead, authentication happens using the HAT APIs and the Javascript Web Token (JWT). Each PDA runs as a separate server and has a publicly-reachable address (such as https://postman.hubat.net). All calls in this documentation are therefore executed against an individual PDA.

Steps

The steps in logging in with a PDA are:
  1. 1.
    You send the user to /hatlogin endpoint on their PDA, such as https://postman.hubat.net
  2. 2.
    The PDA owner enters their login details in the login screen and verifies the service they are logging into
  3. 3.
    User gets redirected back to the address you have provided with authentication token in a query parameter. You validate
    the token against the PDA’s public key and know that the user owns the specific PDA and log them in.

Step 1 - Redirect user to PDA Login

To log the user in with their PDA, you need to ask for their PDA address. Depending on the status of your app within the HAT ecosystem you may also have a specific application name, an allowed success redirect url and an allowed fallback redirect url for the user to be sent to complete authentication. If you do not have these details, you can put any application name, success redirect url and fallback redirect url, however the authentication token you will receive will not grant you any permissions to do any operations on the PDA but verify that the token really came from the PDA.
For an Android application that means asking user to type the PDA Address. Something very simple can be like the next image:
In the above image user is being asked to fill the HAT address, postman, and select a domain, .hubat.net. There can be other domains as well, e.g.: hubofallthings.net. We thought that splitting the address and the domain made for a better UX, but this is not a requirement for your app. You could have one EditText that the user will have to type the full address, postman.hubat.net
Having asked user to fill in the PDA address, e.g. postman.hubat.net, you have to send them to "https://$hatAddress/#/hatlogin?name=$applicationName&redirect=$redirectURL&fallback=$fallbackRedirectURL" endpoint of the PDA, where:
  • $hatAddress is the (fully qualified domain) address of the PDA, e.g. postman.hubat.net
  • $applicationName is the name of your application on the HAT. This is defined once when you complete the form to create a new application. e.g testing
  • $redirectURL is the URL where the user should be sent to after completing authentication. Optional. For an Android
    application that would probably be: $applicationName://success and has to be added in the AndroidManifest.xml file of
    the project in intent-filter of an Activity as a data with host="success" and scheme="$applicationName"
  • $fallbackRedirectURL is the URL where the user should be sent to in case the authentication has failed. Optional.
    For an Android application that would probably be: $applicationName://failed and has to be added in the AndroidManifest.xml
    file of the project in intent-filter of an Activity as a data with host="failed" and scheme="$applicationName"
In an Android application, in order to redirect the user to an existing PDA address and proceed to the next step, we have to use WebView to open the URL.
To achieve this with WebView you have to create an xml file with WebView element and an activity with the login address described above, "https://$hatAddress/#/hatlogin?name=$applicationName&redirect=$redirectURL&fallback=$fallbackRedirectURL", and then via a Activity present the WebView layout. e.g.:
1
<WebView xmlns:android="http://schemas.android.com/apk/res/android"
2
android:layout_width="match_parent"
3
android:layout_height="match_parent"
4
android:id="@+id/webView">
5
</WebView>
Copied!
1
val mWebView = findViewById(R.id.webView)
2
mWebView.loadUrl(url)
Copied!
That will launch WebView within the app and load the url specified.

Step 2 - Logging in the User

In the next step users will be asked to fill in the password for the particular PDA Address:
This screen cannot be modified in any way. Users have to insert the password for the specified PDA and tap LOGIN
Note that the complete address is served via SSL, contains the name of the PDA as well as the application parameters — application name, redirect url and fallback redirect url.
By tapping LOGIN the authentication process will begin. PDA will use one of the two redirect url that were included in the request, success redirect if everything went ok or fallbackRedirectURL if an error occurred. The application has to know how to respond in both scenarios.
In order to achieve that we have to add the success redirect and fallbackRedirectURL to the AndroidManifest file in the project.
In order to add them to the AndroidManifest file you have to add the Key URL Types as a data.
1
<activity name="MainActivity" >
2
<intent-filter>
3
<data
4
android:host="hatappfailed"
5
android:scheme="hatapp" />
6
</intent-filter>
7
</activity>
Copied!
This will be the url scheme of your app. That means every time Android intercepts a URL starting with this value, like test://host will hand the process to your app and your app will be responsible to either launch or not.

Step 3 - Verifying the login

Success callback

If the user logs in, they get redirected to the URL provided, with token query parameter appended and containing a RS256-signed JWT token, e.g.:
1
dataswift-sandbox://dataswift-sandboxhost?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhcHBsaWNhdGlvblZlcnNpb24iOiIxLjIuNyIsInN1YiI6IjEtT0tRdm1TdGdCZ0lKdm9mNUN6NktsMnhaYjhXMUszQmZFR28xa2dZVERCQmdLeUR0ZDBqOXp6VWRaUmlRdFloaFY2VjQ5a1g1WUlmTzE0K3lEcm1GUlwvN1RkUW1iWXNMS3BDST0iLCJhcHBsaWNhdGlvbiI6ImhhdGFwcHN0YWdpbmciLCJpc3MiOiJ0ZXN0aW5nLmh1YmF0Lm5ldCIsImV4cCI6MTU0NDA4Nzc3MiwiaWF0IjoxNTQxNDk1NzcyLCJqdGkiOiI5ZjdlN2MyOTYwMjZkNmM4ODBmN2M2ZTk0MzIzOTQ3Yzg2YmI2OGEwZTIxN2YxZmZhYWE2ZTY3NGYwYWE1ODRmOWRiMzEwNDhiZmI1ZjI4N2Y5YzU4OGM4MGNmOTlmNzJjZTUyOTcxZjU3Y2NkNzVmODUzNTg3OTcwYWM5NWQzNDZhYWNmMzY5OWVkN2IyYmIyMDY5ZTJiMmM5YjE1OTg2Mjc5ZGNiYTNlMTMwYjRkMTdkNTI0ZTVkMmE5MTYyZTUzM2JjNWRlODJmNDBjNTg2ZDc2ODk2MTU0NDE3NzBkOGMwNDRlZjhhNjFlNWM3Y2JkZGQzOWFmYmQ1MDllMjU2In0.i4W_pbOVP9Qb-kkNaari-2U1eWfPSZ6QfYubb6r2SzN1VK0xRe_YT6Zm8gIuEoq8mf5p9wKPcsqzgJwLe27rGNTypCI9qZhVGqY0bNEC5GaXjH3YCXGI_hRKfHiqGbRD8XN1uhOlyWJg0pw_7DA4hdy1pGapw11Pu10y1-YMy6dlieAAU3ot87OGSr5bpXi3P3Wzgvv_QHRRn0ZVXHwp9p1UvG8LFkfzAg5lPqwQGZwMhqmp2NKSF_pStmzcKIsox_1ogrfam_3cm7p1iSRPMROYWxU9rwaOLQiXYXHuB1kO9Z62vxRJLySX_1PunWwXohbu4Rw7biBvpTdLI9D_DQ
Copied!
The token will decode to something like this:
The Header:
1
{
2
"typ": "JWT",
3
"alg": "RS256"
4
}
Copied!
The Payload:
1
{
2
"applicationVersion": "1.2.7",
3
"sub": "1-FgW7/lhAajlonnWAr7g3yB7eByYVkiV8O3UzsFPhEkoOYdr+bbeGeATwKyZUM6YenuUQb85G+PIijAxmP85GRnTIX6bdOdeJuuw=",
4
"application": "hatappstaging",
5
"iss": "postman.hubat.net",
6
"exp": 1543692303,
7
"iat": 1541100303,
8
"jti": "1c73175cd84624efb3ead7ea21fb055ae6f95a519722d314927f251dd13d19aac438861c441ef255a33dae1e1762ee914070251998cbc723a1e2f03f47784470cf70bb6aa003e582e0226d5d8a116af362d9e522a9b29b8281ab2014cc3ae4808e55a6e4752634b3f5b4c4a37e105f57695c6def44e77a2db8e5c9f36a768749"
9
}
Copied!
The key parts of the Payload are:
  • The applicationVersion, the version of the app on HAT
  • The sub (subject), the subject of the token
  • The application, the application name that requested the token
  • The iss (issuer), which is the address of the PDA that has created the token and that you should be logging in
  • The exp (expiry) time of the token as a Unix timestamp, defining whether the token is still valid
  • The iat (issued at time) time that the token has been created as a Unix timestamp, defining whether the token
    is still valid. Token is expiring after 30 days of the issued at date no matter if a refreshed token has been received from PDA
  • The jti (JWT ID) the ID of the token
The Signature, which is generated from the token and the private key of the PDA. The signature must be verified to verify that the token has not been tampered with. A PDA’s public key can be accessed at the /publickey endpoint of the PDA (e.g. https://postman.hubat.net/publickey). The precise handling of tokens with asymmetric keys will depend on your library, however you need to make sure that your library supports RS256 keys.
jwt.io contains a very useful tool for token debugging while in development as well as listing all the major JWT libraries that you can use in your project.
When you have received a successful redirect from PDA you can check with HAT API Android and verity the user. To do so you simply have to call:
1
HATService().loginToHATAuthorization(
2
applicationName: Auth.serviceName,
3
url: url,
4
success: success,
5
failed: failed)
Copied!
  • applicationName is the name of the application that sent the user to log in
  • url is the full url that returned from the PDA, like the example at the beginning of the step 3.
  • success is a callback to execute when the library have successfully authorized user. You can use this callback to dismiss
    WebView activity, save the values needed and navigate to the next Activity
  • failed is a callback to execute when the library couldn't authorize user. You can use this callback to dismiss WebView
    activity and show an error message to the user.
Having received the success callback you have to save the token, ALWAYS use Encryption to save the token. DO NOT save it in any non encrypted database. A good idea would be to also save the full PDA Address as well, as you are gonna need it many times in order to communicate with the PDA. You can store the values in SharedPreferences in Private mode.
As soon as you save the token you are free to navigate to your next Activity.

Fail callback

In case the authentication failed, you will redirected to the fallback url. In that case you should dismiss WebView Activity and then update the UI or show an error message back to the user.
In order to dismiss the browser you do it from the viewController that presented originally the Activity, like this:
1
finish()
Copied!

PDA Data I/O

The PDA is a data store. That means that you can read and write any data you want. Be it a passport, your health records or any data you can think of.
HAT API Android has built in support for reading or writing data to your PDA
This section describes the mechanism of writing data. For reading, this is done through data-debits, a system of consented data exchange.

Writing Data to PDA

Make network requests

Hat API Android offers a general method to create network requests:
1
HATNetworkManager().postRequest(
2
url,
3
body: String,
4
headers: Map<String, String>,
5
completion: completionCallback)
Copied!
  • url the URL to send the request to
  • method the HTTP method of the request, you can find the different methods here
  • contentType the content-type of the request, you can find more here
  • headers the additional headers of the request, this field can be an empty dictionary, mapOf("","")
  • completion a callback function to execute when the request has finished. The result type of the callback can either
    be isSuccess(var statusCode: Int?, var error: Error?, var json: Json?, var resultString: String?, var token: String?)
    if the request was successful or HasFailed(var statusCode: Int?, var error: Error?, var json: Json?, var resultString: String?, var token: String?)
    if the request has failed.
The result type is an enum. Depending if the request was a success or a failure it will have the right type. When the request was successful the result type will include:
  • A boolean value isSuccess, indicating if the request was successful. It may be that the request triggers the successful
    result type but the isSuccess is false, maybe the response was 404 for example
  • The statusCode of the request. Usually the 200..299 range is a success and 400..599 is failure. You can learn more
    about the different status codes here
  • The result is Json type of Fuel, can be found here
  • The token is a refreshed token returned from the PDA. It's optional and sometimes can be null or empty.
When the request has failed the result type will include:
  • The error that has occurred with the request, e.g. no internet connection or time out
  • The statusCode of the request. Usually the 200..299 range is a success and 400..599 is failure. You can learn more
    about the different status codes here
  • The result is JSON type of Fuel, can be found here. Usually it will hold more info about the failure.

Write data

Let's say we want to save the randomStructure below in our PDA:
1
{
2
"value 1": "random",
3
"Int value": 0
4
}
Copied!
The URL that the data will be saved is https://$hatAddress/api/v2.6/data/$path
If the hatAddress is postman.hubat.net and the path is randomdata then the URL will be: https://postman.hubat.net/api/v2.6/data/dataswift-sandbox/randomdata.
The path is formed by your app name, dataswift-sandbox, and the rest of the path, randomdata. It can also be folder/something/data/random. How deep the path will be depends from the data structure that your app uses to navigate to different files.
One more thing that we need in order to write data to the PDA is the user's token in the headers of the request. The header you need to add is x-auth-token along with the token retrieved from the KeyStore. NEVER save the token in a not encrypted database.
Using the function from Hat API Android that will be
1
HATNetworkManager().postRequest(
2
"https://postman.hubat.net/api/v2.6/data/dataswift-sandbox/randomdata",
3
parameters: randomStructure,
4
headers: mapOf("x-auth-token" to token,"Content-Type" to "application/json"),
5
completion: completionCallback)
Copied!
Based on the type of the completionCallback you might have gotten the data back or you might get an error. Your app should know how to react in both scenarios:
1
when (result){
2
is ResultType.IsSuccess->{
3
4
//do something....
5
}
6
is ResultType.HasFailed->{
7
8
//do something....
9
}
10
}
Copied!
A successful response will have statusCode 201 and look like this:
1
{
2
"endpoint": "randomdata",
3
"recordId": "cf2c4ad5-bbb2-4a0e-8aaa-d3be8b76e115",
4
"data": {
5
"value 1": "random",
6
"Int value": 0
7
}
8
}
Copied!
  • endpoint is the path that the file resides, https://$hatAddress/api/v2.6/data/$path
  • recordId is the record identifier in the PDA. It's useful for when want to delete the file for example.
  • data is the data structure that you have saved in the PDA
A request that has failed will look like this:
1
{
2
"error": "Not Authenticated",
3
"message": "Not Authenticated"
4
}
Copied!
  • error is the error that has occurred.
  • message a more descriptive message about the error that has occurred

Read data

If we want to read data we are going to use the same request again but method will be GET instead of POST:
1
HATNetworkManager().getRequest(
2
url,
3
parameters: List<Pair<"key", value?>>,
4
headers: Map<String, String>?,
5
completion: completionCallback)
Copied!
If we make the same assumptions again, the hatAddress is postman.hubat.net, the path is randomdata and the x-auth-token in the headers includes the token then the call will look like below:
1
HATNetworkManager().getRequest(
2
"https://postman.hubat.net/api/v2.6/data/dataswift-sandbox/randomdata",
3
parameters: List<Pair<String, Any?>>,
4
headers: mapOf("x-auth-token" to token,"Content-Type" to "application/json"),
5
completion: completionCallback)
Copied!
Notice that since we want to read data and not write, we don't include any parameters.
Based on the type of the completionCallback you might have gotten the data back or you might get an error. Your app should know how to react in both scenarios:
1
when (result){
2
is ResultType.IsSuccess->{
3
4
//do something....
5
}
6
is ResultType.HasFailed->{
7
8
//do something....
9
}
10
}
Copied!
A successful response will have statusCode 200 and look like that:
1
{
2
"endpoint": "randomdata",
3
"recordId": "cf2c4ad5-bbb2-4a0e-8aaa-d3be8b76e115",
4
"data": {
5
"value 1": "random",
6
"Int value": 0
7
}
8
}
Copied!
  • endpoint is the path that the file resides, https://$hatAddress/api/v2.6/data/$path
  • recordId is the record identifier in the PDA. It's useful for when want to delete the file for example.
  • data is the data structure that you have saved in the PDA
A request that has failed will look like this:
1
{
2
"error": "Not Authenticated",
3
"message": "Not Authenticated"
4
}
Copied!
  • error is the error that has occurred.
  • message a more descriptive message about the error that has occurred

Update data

Let's say that we want to change our original example:
1
{
2
"value 1": "random",
3
"Int value": 0
4
}
Copied!
To something like this:
1
{
2
"value 1": "random",
3
"newValue": true,
4
"Int value": 1
5
}
Copied!
In order to update the data the HTTP method has to change to PUT:
1
HATNetworkManager.putRequest(
2
url,
3
body: String,
4
headers: Map<String, String>,
5
completion: completionCallback)
Copied!
If we make the same assumptions again, the hatAddress is postman.hubat.net and request and the x-auth-token in the headers includes the token then the call will look like below:
1
HATNetworkManager().putRequest(
2
"https://postman.hubat.net/api/v2.6/data",
3
body: body,
4
headers: ["x-auth-token" to token, "Content-Type" to "application/json"],
5
completion: completionCallback)
Copied!
Where parameters is an array of Key-value pair of type Map<String: Any> representing the new structure that we want to update. Mind the brackets, it has to be an array even if it's just one element.
Based on the type of the completionCallback you might have gotten the data back or you might get an error. Your app should know how to react in both scenarios:
1
when (result){
2
is ResultType.IsSuccess->{
3
4
//do something....
5
}
6
is ResultType.HasFailed->{
7
8
//do something....
9
}
10
}
Copied!
A successful response will have statusCode 201 and look like this:
1
{
2
"endpoint": "randomdata",
3
"recordId": "cf2c4ad5-bbb2-4a0e-8aaa-d3be8b76e115",
4
"data": {
5
"value 1": "random",
6
"newValue": true,
7
"Int value": 1
8
}
9
}
Copied!
  • endpoint is the path that the file resides, https://$hatAddress/api/v2.6/data/$path
  • recordId is the record identifier in the PDA. It's useful for when want to delete the file for example.
  • data is the data structure that you have saved in the PDA
A request that has failed will look like this:
1
{
2
"error": "Not Authenticated",
3
"message": "Not Authenticated"
4
}
Copied!
  • error is the error that has occurred.
  • message a more descriptive message about the error that has occurred

Delete data

If now we want to delete the file we have just created we need to create a DELETE request:
1
HATNetworkManager().deleteRequest(
2
url,
3
body: String,
4
headers: Map<String, String>,
5
completion: completionCallback)
Copied!
If we make the same assumptions again, the hatAddress is postman.hubat.net and request and the x-auth-token in the headers includes the token then the call will look like below:
1
HATNetworkManager().deleteRequest(
2
"https://postman.hubat.net/api/v2.6/data",
3
body: body,
4
headers: mapOf("x-auth-token" to token),
5
completion: completionCallback)
Copied!
Where body in this case is the recordId of the entry we want to delete. We can also delete multiple entries with one request using more parameters. If the recordId is 5 then the body will be.
1
{
2
"records": 5
3
}
Copied!
A successful response will have statusCode 200 and look like this:
1
{
2
"message": "All records deleted"
3
}
Copied!
A request that has failed will look like this:
1
{
2
"error": "Not Authenticated",
3
"message": "Not Authenticated"
4
}
Copied!
  • error is the error that has occurred.
  • message a more descriptive message about the error that has occurred

Upload Files

Hat API Android allows you to also upload files in your PDA. You can read more about HAT File Storage here.
The uploading of a file is a multi step process:
  • Request from PDA a temporary URL to upload the file
  • Upload the file to the URL
  • Mark the file as complete

Step 1

To start a file upload you have to call the function below:
1
HATFileService().uploadFileToHAT(
2
fileName: name,
3
token: token,
4
userDomain: userDomain,
5
tags: tags,
6
completion: completionCallback,
7
errorCallback: failCallback
8
)
Copied!
  • fileName is the desired name of the file. You can either randomize it or provide meaningful names, it's up to you
  • token is the user's token. This is needed to authenticate user with the PDA
  • userDomain is the user's PDA Address. This is need in order to form the URL to upload the file
  • tags is an array of String with useful tags to make searching for that file easier.
  • completion is an optional callback function of type ((FileUploadObject, String?) -> Unit)?, FileUploadObject
    is a custom object of HAT API Android describing the file upload object. The Optional String is the refreshed token
    returned from the PDA. This is executed on success and it includes the URL that you have to upload your file.
  • errorCallback is an optional callback that is executed when the request has failed. The type of the callback function
    is ((HATError) -> Unit)?. HATError is a custom object describing the errors that have occurred during the querying of the tables in the database.
So for the purpose of this example let's say that fileName is testfile, tags is just test-tag, userDomain is postman.hubat.net and token is token. That will translate to the request below:
1
HATFileService().uploadFileToHAT(
2
fileName: "testfile",
3
token: "token",
4
userDomain: "postman.hubat.net",
5
tags: arrayof("test-tag"),
6
completion: completionCallback,
7
errorCallback: failCallback
8
)
Copied!
A successful request will result in a status code 200 and the response will look like the one below:
1
{
2
"fileId": "dataswift-sandboxtestfile",
3
"name": "testfile",
4
"source": "dataswift-sandbox",
5
"dateCreated": "2018-11-08T16:08:38.679Z",
6
"lastUpdated": "2018-11-08T16:08:38.679Z",
7
"tags": [
8
"test-tag"
9
],
10
"status": {
11
"status": "New"
12
},
13
"contentUrl": "https://hubat-net-hatservice-v3ztbxc9civz-storages3bucket-m0gs7co0oyi2.s3.eu-west-1.amazonaws.com/postman.hubat.net/dataswift-sandboxtestfile?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20181108T160838Z&X-Amz-SignedHeaders=host%3Bx-amz-server-side-encryption&X-Amz-Expires=300&X-Amz-Credential=AKIAICFRCZUZIP4PQ64A%2F20181108%2Feu-west-1%2Fs3%2Faws4_request&X-Amz-Signature=f868940fad6ad21085c19b62d4b940127808858e64e57dd44b4de452178e107d",
14
"contentPublic": false,
15
"permissions": [
16
{
17
"userId": "de35e18d-14wf-4664-8de7-409abf881754",
18
"contentReadable": true
19
}
20
]
21
}
Copied!
The above response is described by FileUploadObject. The values are explained below:
  • fileId is the ID of the file on the PDA, it is formed by combining the source and name of the file.
  • name is the name of the file that we assigned. In case of a duplicate fileId, PDA will append an incremented number at the end
  • source is the source that requested to upload this file. It's good to have your app name as the source
  • dateCreated is the date that the file was created in ISO format
  • lastUpdated is the date that the file was last modified. You can change the name, status and make the file private or not.
  • tags is an array of String that allow for easier search of the file in the future. You can add multiple tags.
  • status is a Array<Pair<String, String>> Key-Value pair and it can be New, when you just requested the file upload,
    or Completed after the uploading has finished and you marked the file as Completed
  • contentUrl is the URL you will use to upload the file. This URL is short-lived and its use is just to provide a URL for your app that you can upload the file.
  • contentPublic is the flag that indicates if the file is private or public. You can mark a file as private or public after the file has been uploaded
  • permissions is an array of Key-Value pairs of type Array<Pair<String, Any>>. In the above example the permissions
    provide the user with that userId the ability to have access to the file even if the file is marked as private
A request that has failed will look like this:
1
{
2
"error": "Not Authenticated",
3
"message": "Not Authenticated"
4
}
Copied!
  • error is the error that has occurred.
  • message a more descriptive message about the error that has occurred

Step 2

The second step is to upload the actual file. There is no limitation on what type of file you can upload. You can upload images, videos, documents etc. It's up to the application to ensure that the file is uploaded correctly and that it can then download the file and read it without problems.
In order to upload a file you can use the function below included in HAT API Android:
1
HATNetworkHelper().uploadFile(
2
image: File,
3
url: contentURL,
4
completion: completionCallback,
5
error : errorCallBack
6
)
Copied!
  • image is type of File. This function requires to convert your file into File type first. You can convert a Bitmap image to `File``
  • url us the URL to upload the file. As we said earlier this URL is the contentUrl provided by the PDA in the first step
  • completion is a callback function of type (_ r: HATNetworkHelper.ResultType) -> Unit). It can be either
    isSuccess(var statusCode: Int?, var error: Error?, var json: Json?, var resultString: String?, var token: String?) if the
    request was successful or HasFailed(var statusCode: Int?, var error: Error?, var json: Json?, var resultString: String?, var token: String?)
    if the request has failed for some reason. You can read more about it here
A successful request will look like almost exactly the same as the original one:
1
{
2
"fileId": "dataswift-sandboxtestfile",
3
"name": "testfile",
4
"source": "dataswift-sandbox",
5
"dateCreated": "2018-11-08T16:08:38.679Z",
6
"lastUpdated": "2018-11-08T16:08:40.235Z",
7
"tags": [
8
"test-tag"
9
],
10
"status": {
11
"status": "New"
12
},
13
"contentUrl": "https://hubat-net-hatservice-v3ztbxc9civz-storages3bucket-m0gs7co0oyi2.s3.eu-west-1.amazonaws.com/postman.hubat.net/dataswift-sandboxtestfile?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20181108T160838Z&X-Amz-SignedHeaders=host%3Bx-amz-server-side-encryption&X-Amz-Expires=300&X-Amz-Credential=AKIAICFRCZUZIP4PQ64A%2F20181108%2Feu-west-1%2Fs3%2Faws4_request&X-Amz-Signature=f868940fad6ad21085c19b62d4b940127808858e64e57dd44b4de452178e107d",
14
"contentPublic": false,
15
"permissions": [
16
{
17
"userId": "de35e18d-14wf-4664-8de7-409abf881754",
18
"contentReadable": true
19
}
20
]
21
}
Copied!
The only thing that has now changed is the lastUpdated field.
A request that has failed will look like this:
1
{
2
"error": "Not Authenticated",
3
"message": "Not Authenticated"
4
}
Copied!

Step 3

When the file has finished uploading it's required to mark the file as completed, else the file will be deleted. To do so you have to make another request. To achieve that you have to call the next function:
1
HATFileService().completeUploadFileToHAT(
2
fileID: fileObject.fileID,
3
token: token,
4
tags: tags,
5
userDomain: userDomain,
6
completion: completionCallback,
7
errorCallback: failCallback
8
)
Copied!
  • fileID is the file id that is to be marked as completed
  • token is the user's token. This is needed to authenticate user with the PDA
  • tags is an array of String with useful tags to make searching for that file easier. This is added before HAT API Android
    returns you the full file.
  • userDomain is the user's PDA Address. This is need in order to form the URL to mark the file as completed
  • completion is an optional callback function of type ((FileUploadObject, String?) -> Unit)?, FileUploadObject is
    a custom object of HAT API Android describing the file upload object. The Optional String is the refreshed token returned from the PDA.
  • errorCallback is an optional callback that is executed when the request has failed. The type of the callback function
    is ((HATError) -> Unit)?. HATError is a custom object describing the errors that have occurred during the querying of the tables in the database.
A successful request will look like almost exactly the same as the original one:
1
{
2
"fileId": "dataswift-sandboxtestfile",
3
"name": "testfile",
4
"source": "dataswift-sandbox",
5
"dateCreated": "2018-11-08T16:08:38.679Z",
6
"lastUpdated": "2018-11-08T16:08:43.157Z",
7
"tags": [
8
"test-tag"
9
],
10
"status": {
11
"size": 123,
12
"status": "Completed"
13
},
14
"contentUrl": "https://hubat-net-hatservice-v3ztbxc9civz-storages3bucket-m0gs7co0oyi2.s3.eu-west-1.amazonaws.com/postman.hubat.net/dataswift-sandboxtestfile?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20181108T160838Z&X-Amz-SignedHeaders=host%3Bx-amz-server-side-encryption&X-Amz-Expires=300&X-Amz-Credential=AKIAICFRCZUZIP4PQ64A%2F20181108%2Feu-west-1%2Fs3%2Faws4_request&X-Amz-Signature=f868940fad6ad21085c19b62d4b940127808858e64e57dd44b4de452178e107d",
15
"contentPublic": false,
16
"permissions": [
17
{
18
"userId": "de35e18d-14wf-4664-8de7-409abf881754",
19
"contentReadable": true
20
}
21
]
22
}
Copied!
The only thing that has now changed is the lastUpdated field and the status field. The status is marked as Completed and includes the file size in bytes.
A request that has failed will look like this:
1
{
2
"error": "Not Authenticated",
3
"message": "Not Authenticated"
4
}
Copied!
  • error is the error that has occurred.
  • message a more descriptive message about the error that has occurred

Mark file as public

Be default the uploaded files are marked as private. You can change that by calling this function:
1
HATFileService().makeFilePublic(
2
fileID: file.fileID,
3
token: userToken,
4
userDomain: userDomain,
5
successCallback: completionCallback,
6
errorCallBack: errorCallBack)
Copied!
  • fileID is the file id that is to be marked as public
  • token is the user's token. This is needed to authenticate user with the PDA
  • userDomain is the user's PDA Address. This is need in order to form the URL to mark the file as public
  • completion is an optional callback function of type (Boolean -> Unit) returns true
  • errorCallback is an optional callback that is executed when the request has failed. The type of the callback function is
    ((HATError) -> Unit)?. HATError is a custom object describing the general error that occurred on the PDA
A successful request will have a statusCode of 200 and look like almost exactly the same as the original one:
1
{
2
"fileId": "dataswift-sandboxtestfile",
3
"name": "testfile",
4
"source": "dataswift-sandbox",
5
"dateCreated": "2018-11-08T16:08:38.679Z",
6
"lastUpdated": "2018-11-08T16:04:45.689Z",
7
"tags": [
8
"test-tag"
9
],
10
"status": {
11
"size": 123,
12
"status": "Completed"
13
},
14
"contentUrl": "https://hubat-net-hatservice-v3ztbxc9civz-storages3bucket-m0gs7co0oyi2.s3.eu-west-1.amazonaws.com/postman.hubat.net/dataswift-sandboxtestfile?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20181108T160838Z&X-Amz-SignedHeaders=host%3Bx-amz-server-side-encryption&X-Amz-Expires=300&X-Amz-Credential=AKIAICFRCZUZIP4PQ64A%2F20181108%2Feu-west-1%2Fs3%2Faws4_request&X-Amz-Signature=f868940fad6ad21085c19b62d4b940127808858e64e57dd44b4de452178e107d",
15
"contentPublic": true,
16
"permissions": [
17
{
18
"userId": "de35e18d-14wf-4664-8de7-409abf881754",
19
"contentReadable": true
20
}
21
]
22
}
Copied!
The only thing that has now changed is the lastUpdated field and the contentPublic field.
A request that has failed will look like this:
1
{
2
"error": "Not Authenticated",
3
"message": "Not Authenticated"
4
}
Copied!
  • error is the error that has occurred.
  • message a more descriptive message about the error that has occurred

Mark file as Private

Be default the uploaded files are marked as private. You can change that by calling this function:
1
HATFileService().makeFilePrivate(
2
fileID: file.fileID,
3
token: userToken,
4
userDomain: userDomain,
5
successCallback: completionCallback,
6
errorCallBack: errorCallBack)
Copied!
  • fileID is the file id that is to be marked as private
  • token is the user's token. This is needed to authenticate user with the PDA
  • userDomain is the user's PDA Address. This is need in order to form the URL to mark the file as private
  • completion is an optional callback function of type (Boolean -> Unit) returns true
  • errorCallback is an optional callback that is executed when the request has failed. The type of the callback function is
    ((HATError) -> Unit)?. HATError is a custom object describing the general error that occurred on PDA
A successful request will have a statusCode of 200 and look like almost exactly the same as the original one:
1
{
2
"fileId": "dataswift-sandboxtestfile",
3
"name": "testfile",
4
"source": "dataswift-sandbox",
5
"dateCreated": "2018-11-08T16:08:38.679Z",
6
"lastUpdated": "2018-11-08T16:09:44.247Z",
7
"tags": [
8
"test-tag"
9
],
10
"status": {
11
"size": 123,
12
"status": "Completed"
13
},
14
"contentUrl": "https://hubat-net-hatservice-v3ztbxc9civz-storages3bucket-m0gs7co0oyi2.s3.eu-west-1.amazonaws.com/postman.hubat.net/dataswift-sandboxtestfile?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20181108T160838Z&X-Amz-SignedHeaders=host%3Bx-amz-server-side-encryption&X-Amz-Expires=300&X-Amz-Credential=AKIAICFRCZUZIP4PQ64A%2F20181108%2Feu-west-1%2Fs3%2Faws4_request&X-Amz-Signature=f868940fad6ad21085c19b62d4b940127808858e64e57dd44b4de452178e107d",
15
"contentPublic": false,
16
"permissions": [
17
{
18
"userId": "de35e18d-14wf-4664-8de7-409abf881754",
19
"contentReadable": true
20
}
21
]
22
}
Copied!
The only thing that has now changed is the lastUpdated field and the contentPublic field.
A request that has failed will look like this:
1
{
2
"error": "Not Authenticated",
3
"message": "Not Authenticated"
4
}
Copied!
  • error is the error that has occurred.
  • message a more descriptive message about the error that has occurred

Search files

You can also search for files with Hat API Android. To do so you can use the next function:
1
HATFileService().searchFiles(
2
userDomain: userDomain,
3
token: userToken,
4
status: "Completed",
5
name: "",
6
tags: tags,
7
successCallback: receivedImages,
8
errorCallBack: receivedErrorGettingImages)
Copied!
  • userDomain is the user's HAT PDAAddress. This is need in order to form the URL to fetch the files
  • token is the user's token. This is needed to authenticate user with the PDA
  • status is the status of the file. You can search for Completed files only or for New files.
  • name is the name of the file. You can search for a specific file or leave this as an empty String in case you want to
    fetch all the files that match the status and tags
  • tags is an array of String with useful tags to make searching for that file easier. You can search file with specific tags
  • completion is a callback function of type (List<FileUploadObject>, String?) -> Unit. The first parameter is an array
    of FileUploadObject, it contains all the files that the PDA found during the search. The second parameter is an optional
    String, it is a refreshed token returned from the PDA. It can be nil.
  • errorCallback is an optional callback that is executed when the request has failed. The type of the callback function
    is ((HATError) -> Unit)?. HATError is a custom object describing the general error that occurred on PDA
A successful request will have a statusCode of 200 and look like this:
1
[
2
{
3
"fileId": "rumpel1532526508004.jpg",
4
"name": "1532526508004.jpg",
5
"source": "rumpel",
6
"dateCreated": "2018-07-25T13:48:24.976Z",
7
"lastUpdated": "2018-07-25T13:48:24.976Z",
8
"tags": [
9
"android",
10
"image/jpeg"
11
],
12
"status": {
13
"size": 144332,
14
"status": "Completed"
15
},
16
"contentUrl": "https://hubat-net-hatservice-v3zbxc9civz-storages3bucket-m0gs7co0oyi2.s3.eu-west-1.amazonaws.com/postman.hubat.net/rumpel1532526508004.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20181109T184507Z&X-Amz-SignedHeaders=host&X-Amz-Expires=299&X-Amz-Credential=AKIAICFRCZUZIP4PQ64A%2F20181109%2Feu-west-1%2Fs3%2Faws4_request&X-Amz-Signature=3492955b3870ab6bd321f43ba18cb62cd538547b7e523a57c87e0355c29eb3c3",
17
"contentPublic": true,
18
"permissions": [
19
{
20
"userId": "de35e1ed-147f-4664-8de7-409abf881754",
21
"contentReadable": true
22
}
23
]
24
},
25
{
26
"fileId": "rumpelrumpelphoto-49",
27
"name": "rumpelPhoto",
28
"source": "rumpel",
29
"dateCreated": "2018-06-18T08:31:10.420Z",
30
"lastUpdated": "2018-06-18T08:31:10.420Z",
31
"tags": [
32
"iphone",
33
"notes",
34
"photo"
35
],
36
"status": {
37
"size": 2066062,
38
"status": "Completed"
39
},
40
"contentUrl": "https://hubat-net-hatservice-v3ztbxc9ciz-storages3bucket-m0gs7co0oyi2.s3.eu-west-1.amazonaws.com/postman.hubat.net/rumpelrumpelphoto-49?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20181109T184507Z&X-Amz-SignedHeaders=host&X-Amz-Expires=299&X-Amz-Credential=AKIAICFRCZUZIP4PQ64A%2F20181109%2Feu-west-1%2Fs3%2Faws4_request&X-Amz-Signature=2cd122df4cdf15be3e66889d5cc2e525880eb4f2c82012b6dcf00c601ad390da",
41
"contentPublic": true,
42
"permissions": [
43
{
44
"userId": "de35e1ed-147f-4664-8de7-409abf881754",
45
"contentReadable": true
46
}
47
]
48
}
49
]
Copied!
A request that has failed will look like this:
1
{
2
"error": "Not Authenticated",
3
"message": "Not Authenticated"
4
}
Copied!
  • error is the error that has occurred.
  • message a more descriptive message about the error that has occurred

Delete files

You can also delete files from the PDA using the next function:
1
HATFileService().deleteFile(
2
fileID: fileID,
3
token: userToken,
4
userDomain: userDomain,
5
successCallback: fileDeleted,
6
errorCallBack: fileFailedToDelete)
Copied!
  • fileID is the file id on the PDA
  • token is the user's token. This is needed to authenticate user with the PDA
  • userDomain is the user's HAT PDAAddress. This is need in order to form the URL to delete the file
  • completion is a callback function of type (Boolean, String?) -> Unit. The first parameter is true. The second parameter
    is an optional String, it is a refreshed token returned from the PDA. It can be nil.
  • errorCallback is an optional callback that is executed when the request has failed. The type of the callback function
    is ((HATError) -> Unit)?. HATError is a custom object describing the general error that occurred on PDA
A successful request will have a statusCode of 200 and look like almost exactly the same as the original one:
1
{
2
"fileId": "dataswift-sandboxtestfile",
3
"name": "testfile",
4
"source": "dataswift-sandbox",
5
"dateCreated": "2018-11-08T16:08:38.679Z",
6
"lastUpdated": "2018-11-08T16:09:44.247Z",
7
"tags": [
8
"test-tag"
9
],
10
"status": {
11
"status": "Deleted"
12
},
13
"contentUrl": "https://hubat-net-hatservice-v3ztbxc9civz-storages3bucket-m0gs7co0oyi2.s3.eu-west-1.amazonaws.com/postman.hubat.net/dataswift-sandboxtestfile?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20181108T160838Z&X-Amz-SignedHeaders=host%3Bx-amz-server-side-encryption&X-Amz-Expires=300&X-Amz-Credential=AKIAICFRCZUZIP4PQ64A%2F20181108%2Feu-west-1%2Fs3%2Faws4_request&X-Amz-Signature=f868940fad6ad21085c19b62d4b940127808858e64e57dd44b4de452178e107d",
14
"contentPublic": false,
15
"permissions": [
16
{
17
"userId": "de35e18d-14wf-4664-8de7-409abf881754",
18
"contentReadable": true
19
}
20
]
21
}
Copied!
The only thing that has now changed is the status to Deleted
A request that has failed will look like this:
1
{
2
"error": "Not Authenticated",
3
"message": "Not Authenticated"
4
}
Copied!
  • error is the error that has occurred.
  • message a more descriptive message about the error that has occurred

Data Debits

PDA Data Debits are the cornerstone of consented data exchange. It is the only way data can be retrieved from the PDA by anyone else than the owner and enforces a strictly-defined format defining the specific data requested for the user to review and approve.

Fetch Data Debits

You can fetch the available Data Debits by using the next function:
1
HATDataDebitsService().getAvailableDataDebits(
2
userToken: userToken,
3
userDomain: userDomain,
4
succesfulCallBack: gotDataDebits,
5
failCallBack: failedGettingDataDebits)
Copied!
  • userToken is the user's token in order to authenticate with the PDA.
  • userDomain is the user's PDA address in order to form the url to fetch the available Data Debits.
  • succesfulCallBack is a callback. Is called when the request was successful with a type of (List<DataDebitObject>, String?) -> Unit).
    The first parameter is a list of DataDebitObject. This is the structure of Data Debits. More on that in the next section.
    The second parameter is an optional String, the refreshed user token that the PDA returns.
  • failCallBack is a callback that is called when the request has failed. They type of the function is ((HATError) -> Unit). HATError
    is a custom object describing the errors that have occurred during the querying of the PDA.
A successful response will have statusCode 200 and look like this:
1
[
2
{
3
"dataDebitKey": "97a0748f-bf81-4aaa-8f39-97ac2557d920",
4
"dateCreated": "2018-01-02T15:22:42+0000",
5
"permissions": [
6
{
7
"dateCreated": "2018-01-02T15:22:42+0000",
8
"purpose": "This Data Debit is in a legacy format, and the HAT App is unable to display all the information associated with it fully. This may include a logo, title and full description",
9
"start": "2018-01-02T15:23:02.000Z",
10
"period": 86400000,
11
"cancelAtPeriodEnd": true,
12
"termsUrl": "",
13
"bundle": {
14
"name": "97a0748f-bf81-4aaa-8f39-97ac2557d920",