WebAPI Server retrieval¶
Instantiate WebAPITransfer¶
Instantiate a WebAPITransfer
object and set the TransferReceiveCallback
and TransferProgressListener
.
Instantiation may throw SDKException
if cannot create the object.
NotInitializedException
if SDK is not initializedUnsupportedFeatureException
if license does not support this feature
Setting timeout¶
WebAPI class provides two methods to set the timeout for connection and reading. Both methods accept the timeout in milliseconds.
WebAPI#setReadTimeout(int)
WebAPI#setConnectionTimeout(int)
Example
package com.example.app;
import ...
public class MainActivity extends AppCompatActivity
implements DeviceEngagementCallback, TransferReceiveCallback {
...
private final Map<String, Map<String, Map<String, Boolean>>> docRequests
= new HashMap<>();
private WebAPITransfer webApiTransfer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Map<String, Boolean> itemsRequest = new HashMap<>();
itemsRequest.put("age_over_21", true);
itemsRequest.put("portrait", true);
Map<String, Map<String, Boolean>> nameSpaces = new HashMap<>();
nameSpaces.put("org.iso.18013.5.1", itemsRequest);
docRequests.put("org.iso.18013.5.1.mDL", nameSpaces);
try {
webApiTransfer = new WebAPITransfer()
.setTransferReceiveCallback(this);
} catch (SDKException e) {
// handle failed BLETransfer initialization
}
...
}
...
}
Send request¶
When device engagement is received, use the WebAPITransfer#forDeviceEngagement(DeviceEngagement)
method to set the current device engagement to WebAPITransfer object.
Then create the request using RequestBuilder
and use the WebAPITransfer#send(Request)
to send
it.
Example
package com.example.app;
import ...
public class MainActivity extends AppCompatActivity
implements DeviceEngagementCallback, TransferReceiveCallback {
...
private WebAPITransfer webApiTransfer;
...
@Override
public void onEngage(@NonNull Received<EngagementReceived> received) {
try {
received.runCatching(
failure -> {
// handle failed device engagement
},
success -> {
DeviceEngagement deviceEngagement = success.getDeviceEngagement();
Request request = new RequestBuilder()
.setDeviceEngagement(deviceEngagement)
.setDocRequests(docRequests)
.build();
webAPITransfer
.forDeviceEngagement(deviceEngagement)
.send(request);
}
);
} catch (Exception e) {
// handle exception sending request
}
}
...
}
Receiving response¶
When response is received, use the Received#run(Consumer<Failure>, Consumer<TransferReceived>)
or
Received#runCatching(Functions.FailableConsumer<Failure>, Functions.FailableConsumer<TransferReceived>)
to handle the response.
Example
package com.example.app;
import ...
public class MainActivity extends AppCompatActivity
implements DeviceEngagementCallback, TransferReceiveCallback {
...
@Override
public void onReceive(@NonNull Received<TransferReceived> received) {
try {
received.runCatching(
failure -> {
// handle failed data received
},
success -> success.runCatchingForServer(bytesReceived -> {
// consume bytesReceived
})
);
} catch (Exception e) {
// handle exception
}
}
}
Failure Types¶
- WEBAPI_ERROR
- WEBAPI_JWT_VERIFICATION_ERROR
Sample code¶
The following example demonstrates a typical implementation for retrieving data using QR device engagement and WebAPI.
Example
package com.example.app;
import android.Manifest.permission;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.Button;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import com.scytales.mvalid.sdk.FailureType;
import com.scytales.mvalid.sdk.Received;
import com.scytales.mvalid.sdk.SDKException;
import com.scytales.mvalid.sdk.data.Request;
import com.scytales.mvalid.sdk.data.RequestBuilder;
import com.scytales.mvalid.sdk.data.ServerResponse;
import com.scytales.mvalid.sdk.engagement.DeviceEngagement;
import com.scytales.mvalid.sdk.engagement.DeviceEngagementCallback;
import com.scytales.mvalid.sdk.engagement.EngagementReceived;
import com.scytales.mvalid.sdk.engagement.qr.QRDeviceEngagement;
import com.scytales.mvalid.sdk.retrieval.TransferProgressEvent;
import com.scytales.mvalid.sdk.retrieval.TransferProgressListener;
import com.scytales.mvalid.sdk.retrieval.TransferReceiveCallback;
import com.scytales.mvalid.sdk.retrieval.TransferReceived;
import com.scytales.mvalid.sdk.retrieval.server.WebAPITransfer;
import com.scytales.mvalid.sdk.verify.ServerResponseVerifier;
import com.scytales.mvalid.sdk.verify.ServerVerifierResult;
import com.scytales.mvalid.sdk.verify.Verifier;
import com.scytales.mvalid.sdk.verify.VerifierResult;
import java.security.cert.X509Certificate;
import java.util.Collection;
import java.util.List;
public class MainActivity extends AppCompatActivity
implements DeviceEngagementCallback, TransferProgressListener,
TransferReceiveCallback {
private static final String TAG = "MainActivity";
private final QRDeviceEngagement qrDeviceEngagement = new QRDeviceEngagement();
private WebAPITransfer webAPITransfer;
private final ActivityResultLauncher<String> requestPermissionsLauncher =
registerForActivityResult(new ActivityResultContracts.RequestPermission(), status -> {
if (status) {
enableScanQrBtn();
}
});
private Collection<X509Certificate> rootCertificates;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
rootCertificates = Verifier.getRootCertificates(this);
if (ContextCompat.checkSelfPermission(this, permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
requestPermissionsLauncher.launch(permission.CAMERA);
} else {
enableScanQrBtn();
}
try {
qrDeviceEngagement.enableDeviceEngagement(this, this);
webAPITransfer = new WebAPITransfer()
.setTransferProgressListener(this)
.setTransferReceiveCallback(this);
} catch (SDKException e) {
Log.e(TAG, "onCreate", e);
// handle failed initialization
}
}
private void enableScanQrBtn() {
Button scanQrBtn = findViewById(R.id.scan_qr_btn);
scanQrBtn.setOnClickListener(v -> qrDeviceEngagement.scanQR());
}
@Override
public void onEngage(@NonNull Received<EngagementReceived> received) {
Log.d(TAG, received.toString());
try {
received.runCatching(
failure -> {
Log.e(TAG, failure.toString());
FailureType type = failure.getType();
// handle failed device engagement
},
success -> {
DeviceEngagement deviceEngagement = success.getDeviceEngagement();
// request for age_over_21
Request request = new RequestBuilder()
.setDeviceEngagement(deviceEngagement)
.forIsoDocTypeAgeOver(21, true)
.build();
webAPITransfer
.forDeviceEngagement(deviceEngagement)
.send(request);
}
);
} catch (Exception e) {
// handle exception sending request
}
}
@Override
public void onProgressEvent(@NonNull TransferProgressEvent transferProgressEvent) {
Log.i(TAG, transferProgressEvent.toString());
// update UI with progress information
}
@Override
public void onReceive(@NonNull Received<TransferReceived> received) {
try {
received.runCatching(
failure -> {
Log.e(TAG, failure.toString());
FailureType type = failure.getType();
// handle failed data received
},
success -> success.runCatchingForServer(bytesReceived -> {
// create a ServerResponse to manipulate received data
ServerResponse serverResponse =
ServerResponse.fromBytes(bytesReceived);
// verify received data; a ServerVerifierResult for each
// requested document
List<ServerVerifierResult> verifierResults =
new ServerResponseVerifier(rootCertificates)
.verify(bytesReceived);
// check verification for all verified documents
boolean isVerified = verifierResults.stream()
.allMatch(VerifierResult::isValid);
})
);
} catch (Exception e) {
Log.e(TAG, "onReceive", e);
// handle exception
}
}
}