I set up a connection between Android and AWS Lambda which has the endpoint set to SageMaker. I am using the REST API during the connection, the AWS Cognito plug is set to be accessed without authorization.
I make a connection as described here:
https://aws.amazon.com/blogs/machine-learning/call-an-amazon-sagemaker-model-endpoint-using-amazon-api-gateway-and-aws-lambda/
My question is how to send this data:
{"data":"13.49,22.3,86.91,561.0,0.08752,0.07697999999999999,0.047510000000000004,0.033839999999999995,0.1809,0.057179999999999995,0.2338,1.3530000000000002,1.735,20.2,0.004455,0.013819999999999999,0.02095,0.01184,0.01641,0.001956,15.15,31.82,99.0,698.8,0.1162,0.1711,0.2282,0.1282,0.2871,0.06917000000000001"}
And how to view the received response later. Anyone know how to do it or where I can find tips on how to do it?
If I understand correctly, this is your system flow:
POST some data from your Android device
It gets received by API Gateway
And continues through to AWS Lambda
In AWS Lambda the data is extracted, and passed to Sage Maker
Creating a POST using AWS Amplify
To POST data form the Android device, follow the Amplify API (REST) category documentation.
Specifically, you can do something like:
val options = RestOptions.builder()
.addPath("/prod/predictbreastcancer")
.addBody("{\"data\":\"13.49,22.3,86.91,561.0,0.08752,0.07697999999999999,0.047510000000000004,0.033839999999999995,0.1809,0.057179999999999995,0.2338,1.3530000000000002,1.735,20.2,0.004455,0.013819999999999999,0.02095,0.01184,0.01641,0.001956,15.15,31.82,99.0,698.8,0.1162,0.1711,0.2282,0.1282,0.2871,0.06917000000000001\"}".toByteArray())
.build()
Amplify.API.post(options,
{ Log.i("Demo", "POST response = $it") },
{ Log.e("Demo", "POST failed", it) }
)
Creating POST body from EditText content
You mentioned you're using an EditText widget to gather the input data. I assume a user can enter a comma-separated list of values like 0.44, 6.11, etc.
To extract it's content and build the POST body, you can do:
val input = findViewById(R.id.input) as EditText
val body = JSONObject()
.put("data", input.text)
.toString()
.replaceAll("\"", "\\\"")
Displaying response in another Activity
Skimming the blog you referenced, I can't see an example of the response body content. But, here's how you can retrieve response JSON and pass it to a new activity.
Amplify.API.post(options,
{ response ->
val intent = Intent(this, YourOtherActivity::class.java)
intent.putExtra("json", response.data.asString())
runOnUiThread { startActivity(intent) }
},
{ /* handle error ... */ }
)
In YourOtherActivity, access the extra data in onCreate() like so:
val json = intent.getStringExtra("json")
I recently started update to okhttp3 to 4.x
In doing so I am getting following build time error:
Using 'url(): HttpUrl' is an error. moved to val
The issue is happening when I am trying to get url from request object obtained via call:
e.g
call.enque(callback : Callback){
override fun onFailure(call : Call, t:Throwable) {
val url = call.request().url().toString
}
}
I looked up further and the Url object within Request is val aka final now.
Also, no directions on their upgrade guide https://square.github.io/okhttp/upgrading_to_okhttp_4/
I would appreciate for any suggestions on another way to obtain Url.
Using 'url(): HttpUrl' is an error. moved to val
This means you should change the function call url() to a property access url.
okhttp 4 comes with replaceWith param in the deprecation annotation that makes e.g. Android Studio to offer that fix automatically with right-click/alt-enter on the error:
#Deprecated(
message = "moved to val",
replaceWith = ReplaceWith(expression = "url"),
level = DeprecationLevel.ERROR)
From comments:
Upon further investigation I found out that the request() or Request object is from Retrofit 2. And Retrofit 2 returns call object from okhttp3
That's an issue with Android Studio. You can work around it with explicit cast to okhttp 4 types, e.g. (call.request() as Request).url.
In my case, I just had to remove the brackets:
call.request().url() -> call.request().url
Working on an Android project with Kotlin using Retrofit. Problem is that the URL changes unexpectedly and 422 is thrown.
More specifically, the problem is in the way Retrofit handles my formatted date. The API uses this time format:
2019-08-21T05%3A12%3A53Z
which, in this example, represents August 21, 2019, at 05:12:53. As you can see, the separator for time values is %3A.
This is the interface I'm using:
interface CurrenciesApi {
#GET("currencies/sparkline?key=${apiKey}")
fun getCurrenciesSparkline(
#Query("start") start: String,
#Query("end") end: String): Call<List<CurrencySparkline>>
}
Minor remarks: apiKey is a top-level constant properly imported. CurrencySparkline is a data class corresponding to the JSON response.
From previous unit tests I know Retrofit should be built this way
let myBaseUrl: String = "https:// ..."
let retrofit: Retrofit = Retrofit.Builder()
.baseUrl(myBaseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build()
implementation of CurrenciesApi interface
val api = retrofit.create(CurrenciesApi::class.java)
and lastly the call
val start = "2019-08-08T02%3A17%3A59Z"
val end = "2019-09-01T00%3A00%3A00Z"
response: Response<List<CurrencySparkline>> = api
.getCurrenciesSparkline(start, end)
.execute()
When testing the API endpoint in browser, the response is valid and data comes back. However, if I look at the URL in debug mode, I see that I has changed values for start and end:
... &start=2019-08-08T02%253A17%253A59Z&end=2019-09-01T00%253A00%253A00Z ...
Why is this happening and how do I fix it? Any sort of help is much appreciated.
I'm new to GraphQL using the Apollo client on Android. I'm trying to sign up a user on the server via graphQL mutation.
I call a mutation and if user's data is not valid I get http code 422: Unprocessible Entity, and in this case I cannot get any response details. I use standard way to make a call:
.enqueue(object : ApolloCall.Callback<CreateUserMutation.Data>() {
override fun onFailure(e: ApolloException) {
}
override fun onResponse(response:
Response<CreateUserMutation.Data>) {
}
And after this I'm in the onFailure block. ApolloException contains only http code description. But I want to see error details in a full response, that I can see via the Postman. I've already tried com.apollographql.apollo.ApolloCall.Callback#onHttpError callback, but the networkResponse body = null. I've described this problem here, but haven't fixed my problem:
https://github.com/apollographql/apollo-android/issues/1166
The way to do this is to check if ApolloException is an instanceof ApolloHttpException.
If it is, you can get the throwable.rawResponse().code() from it.
If it's not it means it isn't server error (maybe timeout or others)
I am currently playing with Spring Android Resttemplate to interact with a java-backed REST API. Actually, I am using android annotations to send http calls to this back-end service and I must say it rocks. Basically, Android annotations allows you to define an interface for the service calls and the http methods to be used for each api call available : it will generate all the boiler-plate code related to low-level stuff like marshalling/unmarshalling, calling the right http method according to the interface definition.
Now, I would like to set some headers to http requests : How can I achieve this knowing that I only have a reference to the Service interface defining all the calls ?
I can also have reference to the RestTemplate object but it seems there is now way of setting the headers.
any help would really be appreciated
thanks
The way I approached it is by creating an instance of ApiClient in the application class and set a custom REST template.
In my case I was using Jackson for JSON message conversion:
RestTemplate restTemplate = new RestTemplate(fac);
MappingJacksonHttpMessageConverter converter =
new MappingJacksonHttpMessageConverter();
converter.getObjectMapper().configure(Feature.UNWRAP_ROOT_VALUE, true);
restTemplate
.getMessageConverters()
.add(converter);
mClient.setRestTemplate(restTemplate);
My request factory fac then looks like this:
ClientHttpRequestFactory fac = new HttpComponentsClientHttpRequestFactory() {
#Override
protected HttpUriRequest createHttpRequest(HttpMethod httpMethod, URI uri) {
HttpUriRequest uriRequest = super.createHttpRequest(httpMethod, uri);
// Add request headers
uriRequest.addHeader(
"Content-Type",
MediaType.APPLICATION_JSON_VALUE);
return uriRequest;
}
#Override
public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod)
throws IOException {
if (Config.DEBUG_REQUESTS) {
Log.d(TAG, uri);
}
return super.createRequest(uri, httpMethod);
}
};
WARNING
Although this works on all Android devices in our office, I've recently discovered that headers don't appear to be added with all devices! I'm not sure why this is (or which devices specifically), but I'm looking in to it and will try to update this answer when I've found a resolution.