Sonde Health API Platform Documentation

Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 3 Current »

Server-side setup:

Please refer “Setting up the Server” section from README.md file present at https://github.com/sondehealth-samples/score

Before going to through client-side integration we are considering that you have done with server-side setup.

Integration steps for Android :

  • Step-1 : Get Access token (Authentication Token)

The first step to integrate the sonde services into your mobile app is to get the access token which will authenticate your further requests made from app to Sonde services. To know how to get the access token from Sonde services at backend you can refer this link Respiratory Symptoms Risk API

Below code snipped you can refer to get access token from your backend.

    private void getAccessToken(String apiUrl) {
        BackendApi backendApi = RetrofitClientInstance.getRetrofitInstance().create(BackendApi.class);
        Call<AccessTokenResponse> call = backendApi.getAuthToken(apiUrl);
        call.enqueue(new Callback<AccessTokenResponse>() {
            @Override
            public void onResponse(Call<AccessTokenResponse> call, Response<AccessTokenResponse> response) {
                Log.i(TAG, "AccessToken Response : " + response.toString());
                AccessTokenResponse accessTokenResponse = response.body();
                if (accessTokenResponse != null) {
                    Log.i(TAG, "AccessToken is : " + accessTokenResponse.getAccessToken());
                    // use this accessToken for further apis call
                    String accessToken = accessTokenResponse.getAccessToken();
                } else {
                    Log.e(TAG, "error: code " + response.code());
                }
            }

            @Override
            public void onFailure(Call<AccessTokenResponse> call, Throwable t) {
                Log.e(TAG, "error: " + t);
            }
        });
    }

Here apiUrl should be your backend api url to get access token

e.g. apiUrl=https://YOUR_BACKEND/authToken (Please note that this url should not be Sonde APIs end point)


onResponse: Callback method where you will get access token. You should store this received token in secure place, as this token will be used for further request to Sonde. Please note that this access token is only valid for certain time (1 hour), so its your responsibility to re-fetch the token after expiry.

onFailure : Callback method for failure case

  • Step-2 : Register User

In this step you have to register user to Sonde platform but this registration should be done through your backend. So you have to call your backend api to register user. You can refer below code snippet to register user.

 private void registerUser(String apiUrl) {
        SignUpRequest signUpRequest = new SignUpRequest("1985", "MALE", "ENGLISH");
        BackendApi backendApi = RetrofitClientInstance.getRetrofitInstance().create(BackendApi.class);
        Call<SignUpResponse> call = backendApi.signUpUser(apiUrl, signUpRequest);
        call.enqueue(new Callback<SignUpResponse>() {
            @Override
            public void onResponse(Call<SignUpResponse> call, Response<SignUpResponse> response) {
                SignUpResponse signUpResponse = response.body();
                if (signUpResponse != null) {
                    // use this userIdentifier to calculate score for wav file
                    String userIdentifier = signUpResponse.getUserIdentifier();
                } else {
                    Log.e(TAG, "error: code " + response.code());
                }
            }

            @Override
            public void onFailure(Call<SignUpResponse> call, Throwable t) {
                Log.e(TAG, "error: " + t);
            }
        });
    }
  • Step-3 : Get list of measures

In this step you have to get list of all the accessible measures. Any measure from the list can be used to get score for an audio (wav) file.

Request -

URL : SONDE_API_BASE_URL/measures

Method : GET

Headers : Authorization - <Access token received in step 1>

Response : List of measures

Below snipped can be refer to get measures lists

private void getMeasures() {
        BackendApi backendApi = RetrofitClientInstance.getRetrofitInstance().create(BackendApi.class);
        Call<MeasureResponse> call = backendApi.getMeasures(accessToken);
        call.enqueue(new Callback<MeasureResponse>() {
            @Override
            public void onResponse(Call<MeasureResponse> call, Response<MeasureResponse> response) {
                MeasureResponse measureResponse = response.body();
                if (measureResponse != null) {
                    measureList = measureResponse.getMeasures();
                } else {
                    Log.e(TAG, "error: code " + response.code());
                }
            }

            @Override
            public void onFailure(Call<MeasureResponse> call, Throwable t) {
                Log.e(TAG, "error: " + t);
            }
        });
    }

  • Step-4 : Record audio file (wav file)

In step-4 you have to record the audio file (wav file). Please note the currently Sonde only accepts the wav file format, other audio format like MP3, 3GP are not supported.

You can record a audio file in following steps :

i). Request for microphone permission :

To record an audio, you must request for microphone permission on android 6 and above.

Add the permission in manifest

<uses-permission android:name="android.permission.RECORD_AUDIO"/>

Below code snippet you can refer to request for microphone permission.

  private void requestAudioPermissions() {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {

            //When permission is not granted by user, show them message why this permission is needed.
            if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.RECORD_AUDIO)) {
                Toast.makeText(this, "Please grant permissions to record audio", Toast.LENGTH_LONG).show();
                ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO}, PERMISSIONS_RECORD_AUDIO);

            } else {
                // Show user dialog to grant permission to record audio
                ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO}, PERMISSIONS_RECORD_AUDIO);
            }
        }
        //If permission is granted, then go ahead for recording audio
        else if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.RECORD_AUDIO)
                == PackageManager.PERMISSION_GRANTED) {
            // start Recording audio;
        }
    }

ii). Start recording of audio :

Below snipped you can refer to start recording of audio and writing it to a file.

// starts recording a file at internal memory
    private void startRecording() {
        mAudioRecord = new AudioRecord(AUDIO_SOURCE, SAMPLE_RATE_HZ, AUDIO_CHANNEL_CONFIG, AUDIO_FORMAT, AUDIO_BUFFER_SIZE_BYTES);
        mAudioRecord.startRecording();
        mFilePath = getFilesDir().getAbsolutePath() + "/" + System.currentTimeMillis() + ".wav";
        recording = true;
        new Thread(new Runnable() {
            @Override
            public void run() {
                writeAudioDataToFile(mFilePath);
            }
        }).start();
    }
    
    private void writeAudioDataToFile(String filename) {
        String audioFilename = filename + ".pcm";
        OutputStream outputStream = null;
        try {
            outputStream = new FileOutputStream(audioFilename);
            int bufferSizeBytes = AUDIO_BUFFER_SIZE_BYTES;
            short[] audioBuffer = new short[bufferSizeBytes / 2]; // assumes 16-bit encoding
            byte[] outputBuffer = new byte[bufferSizeBytes];
            int totalBytesRead = 0;
            while (recording) {
                int numShortsRead = mAudioRecord.read(audioBuffer, 0, audioBuffer.length);

                for (int i = 0; i < numShortsRead; i++) {
                    outputBuffer[i * 2] = (byte) (audioBuffer[i] & 0x00FF);
                    outputBuffer[i * 2 + 1] = (byte) (audioBuffer[i] >> 8);
                    audioBuffer[i] = 0;
                }

                int numBytesRead = numShortsRead * 2;
                totalBytesRead += numBytesRead;
                outputStream.write(outputBuffer, 0, numBytesRead);
            }

            OutputStream waveOutputStream = new FileOutputStream(mFilePath);
            InputStream dataInputStream = new FileInputStream(audioFilename);
            short numChannels = 1;
            short sampleSizeBytes =  2;
            //convert pcm to wav file
            WaveUtils.pcmToWave(waveOutputStream, dataInputStream, totalBytesRead, numChannels, SAMPLE_RATE_HZ, sampleSizeBytes);
        } catch (Exception e) {
            Log.e(TAG, "Error : " + e);
        }finally {
            try {
                if (outputStream != null) {
                    outputStream.close();
                }
            } catch (IOException e) {
            Log.e(TAG, "Error : " + e);
            }
            try {
                if (mAudioRecord != null) {
                    mAudioRecord.stop();
                    mAudioRecord.release();
                    mAudioRecord = null;
                }
            } catch (IllegalStateException e) {
            Log.e(TAG, "Error : " + e);
            }
            // delete PCM file
            File file = new File(audioFilename);
            file.delete();
        }
    }
  • Step-5 : Get S3 signed url to upload wav file

After recording audio/wav file, the next step is to get the S3 signed url to upload the wav file.

Request -

URL : SONDE_API_BASE_URL/storage/files

Method : POST

Headers : Authorization - <Access token received in step 1>

Response : S3 signed url and file location

You can refer below snippet to get S3 signed url and file location.

   private void getS3SignedUrl( {
        BackendApi backendApi = RetrofitClientInstance.getRetrofitInstance().create(BackendApi.class);
        String countryCode = "IN"; //Use your country code
        Call<S3PathResponse> call = backendApi.getS3FilePath(accessToken, new S3FilePathRequest("wav", countryCode, userIdentifier));
        call.enqueue(new Callback<S3PathResponse>() {
            @Override
            public void onResponse(Call<S3PathResponse> call, Response<S3PathResponse> response) {
                S3PathResponse s3PathResponse = response.body();
                if (s3PathResponse != null) {
                String s3FilePath = s3PathResponse.getSignedURL();
                    //use the received signed url to upload wav file
                } else {
                    Log.e(TAG, "error: code " + response.code());
                }
            }

            @Override
            public void onFailure(Call<S3PathResponse> call, Throwable t) {
                Log.e(TAG, "error: " + t);
            }
        });
    }
  • Step-6 : Upload wav file to S3

Once you got the S3 signed url, next step is to upload wav file to S3 bucket.

To know how to upload file to S3 bucket, you can refer below code snippet

   private void uploadFileToS3(final S3PathResponse s3PathResponse, final File filePath) {
        BackendApi backendApi = RetrofitClientInstance.getRetrofitInstance().create(BackendApi.class);
        MediaType MEDIA_TYPE_OCTET_STREAM = MediaType.parse("application/octet-stream");
        String uploadUrl = s3PathResponse.getSignedURL();
        Call<ResponseBody> call = backendApi.uploadFileToS3(uploadUrl, RequestBody.create(MEDIA_TYPE_OCTET_STREAM, filePath));
        call.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                if (response.isSuccessful()) {
                    Log.i(TAG, " : File Uploaded successfully " + filePath.getName());
                    // request for measure score
                } else {
                    Log.e(TAG, " : Failed to upload file " + filePath.getName() + " Error code : " + response.code());
                }
            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
                Log.e(TAG, " : Failed to upload file " + filePath.getName() + " Error: " + t);
            }
        });
    }
  • Step-7 : Request for score

After successfully uploading the wav file, the last step requires you to request for measure score.

To request for score you should use the below rest api :

Request -

URL : SONDE_API_BASE_URL/inference/scores

Method : POST

Headers : Authorization - <Access token received in step 1>

Response : Measure score

You can refer below code snippet to request for measure score.

    private void requestForMeasureScore(String fileLocation, final String measureName, String userIdentifier) {
        Log.i(TAG, " : fileLocation : " + fileLocation);
        BackendApi backendApi = RetrofitClientInstance.getRetrofitInstance().create(BackendApi.class);
        Call<InferenceScoreResponse> call = backendApi.getInferenceScore(accessToken, new InferenceScoreRequest(fileLocation, measureName, userIdentifier));
        call.enqueue(new Callback<InferenceScoreResponse>() {
            @Override
            public void onResponse(Call<InferenceScoreResponse> call, Response<InferenceScoreResponse> response) {
                InferenceScoreResponse scoreResponse = response.body();
                if (scoreResponse != null) {
                    //show calculated score for measure
                } else {
                    Log.e(TAG, " : Failed to get score , Error: " + response.code());
                    Toast.makeText(MainActivity.this, "Could not calculate the score, please try again", Toast.LENGTH_LONG).show();
                }
            }

            @Override
            public void onFailure(Call<InferenceScoreResponse> call, Throwable t) {
                Log.e(TAG, " : Failed to get score , Error: " + t);
                Toast.makeText(MainActivity.this, "Could not calculate the score, please try again", Toast.LENGTH_LONG).show();
            }
        });
    }

For more information, please contact Sonde at support@sondehealth.com.

  • No labels