AWS SDK Kotlin couldn't find credentials - android

I am using AWS SDK for Kotlin in my Android project and my app always crashes with error
aws.sdk.kotlin.runtime.auth.credentials.CredentialsProviderException: No credentials could be loaded from the chain: CredentialsProviderChain -> EnvironmentCredentialsProvider -> ProfileCredentialsProvider -> StsWebIdentityProvider -> EcsCredentialsProvider -> ImdsCredentialsProvider
I am using AWS secret manager and implementing the SDK in gradle as -
implementation 'aws.sdk.kotlin:secretsmanager:0.17.5-beta'
My Kotlin code looks like -
SecretsManagerClient { region = "ap-south-1" }.use { secretsClient ->
CoroutineScope(Dispatchers.IO).launch {
val secretValueRequest = GetSecretValueRequest {
secretId = "prod"
}
val response = secretsClient.getSecretValue(secretValueRequest)
val secret = response.secretString
print("Secret: $secret")
}
}
I tried to setup the credential in my Mac computer as mentioned in this article, for both environment variable and also having a file named credentials .
Can anyone please help me to fix the issue

Your problem here is the Android app will not read creds from the file system of your machine. To get around this, you can use the StaticCredentialsProvider shown in this example that is referenced from the Kotlin DEV Guide.
https://docs.aws.amazon.com/sdk-for-kotlin/latest/developer-guide/cross_SnsPublishSubscription_kotlin_topic.html
Github URL
https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/kotlin/usecases/subpub_app_android
Once you follow this -- you can successfully make AWS Service calls from the Android app.
UPDATE
After talking with the Kotlin team, you can setup your creds as environment variables then use this provider - which is mentioned in the docs here:
https://docs.aws.amazon.com/sdk-for-kotlin/latest/developer-guide/credential-providers.html
Code that works....
SnsClient { credentialsProvider = EnvironmentCredentialsProvider(); region = "us-east-1" }.use { snsClient ->
val result = snsClient.subscribe(request)
showToast(result.subscriptionArn.toString())
}
This Kotlin Android example will be updated and published soon as well.

Related

ClassCastException while trying to use com.google.api.client.http.HttpTransport

Basically, I can't find an implementation of com.google.api.client.http.HttpTransport that works in Android SDK 31.
I'm trying to get started with the google-signin API, and I'm getting a ClassCastException.
I'm using code taken nearly verbatim from the google api examples.
val credentialStream = resources.openRawResource(R.raw.credentials)
?: throw FileNotFoundException("Resource not found: $CREDENTIALS_FILE_PATH")
val clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, InputStreamReader(credentialStream))
// Build flow and trigger user authorization request.
val flow = GoogleAuthorizationCodeFlow.Builder(NetHttpTransport(), JSON_FACTORY, clientSecrets, SCOPES)
.setDataStoreFactory(FileDataStoreFactory(requireContext().filesDir?.resolve(File(TOKENS_DIRECTORY_PATH))))
.setAccessType("offline")
.build()
val receiver = LocalServerReceiver.Builder().setPort(8888).build()
//returns an authorized Credential object.
return AuthorizationCodeInstalledApp(flow, receiver).authorize("user#gmail.com")
Every test results in an exception at the last line.
java.lang.NoClassDefFoundError: Failed resolution of: Lcom/sun/net/httpserver/HttpServer;
...
Caused by: java.lang.ClassNotFoundException: Didn't find class "com.sun.net.httpserver.HttpServer" on path: DexPathList[[dex file "/data/d ...
Any ideas? I'm pretty novice to android development.
One solution I found was to add rt.jar from the desktop JVM as a dependency, because it includes that missing class. Check here:
Is it possible to use com.sun.net.httpserver package in android program?
The solution I ended up using was to using Google Play Services instead of GoogleAuthorizationCodeFlow.
In gradle:
implementation 'com.google.android.gms:play-services-auth:20.1.0'
implementation ('com.google.api-client:google-api-client-android:1.34.0')
In my ViewModel:
val applicationName = "My Application"
val scopes = listOf( ... some scopes go here ...)
val credential = GoogleAccountCredential.usingOAuth2(application, scopes)
.setBackOff(ExponentialBackOff())
.setSelectedAccountName(accountName)
credential can then be used to access other parts of the Google API.

Huawei Map Kit throws Network Error (Code 060001) when calling it from Android app

I am implementing Map Kit on my Android app. After following the official documentation on installing the HMS Core SDK, I have:
Enabled Map Kit, Location Kit and Site Kit on AppGallery Connect.
Added agconnect-services.json
Encoded my API key using URLEncoder and utf-8.
Copied my SHA-256 certificate fingerprints for my release version AND debug version (using different keystore entries).
Asked for location permission.
Setting my API key on MapsInitializer before it's loaded.
In summary, my code looks like this:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
try {
API_KEY = URLEncoder.encode(
getString(R.string.api_key),
"utf-8"
)
MapsInitializer.setApiKey(API_KEY)
} catch (ignored: UnsupportedEncodingException) {
}
binding = ActivityMapBinding.inflate(layoutInflater)
setContentView(binding.root)
viewModel = ViewModelProvider(
this,
MapViewModel.MyViewModelFactory(application)
)[MapViewModel::class.java]
var mapViewBundle: Bundle? = null
if (savedInstanceState != null) {
mapViewBundle = savedInstanceState.getBundle(MAPVIEW_BUNDLE_KEY)
}
mMapView = binding.mapView
mMapView.onCreate(mapViewBundle)
mMapView.getMapAsync(this)
siteInfo = binding.siteInfo
siteInfo.visibility = View.GONE
// ...
}
But all I get when entering the activity is the blue point of my location over a blank map and a Toast saying REQUEST_DENIED.
Checking the logs, there seems not to be an API authentication or signing error, but most likely Petal Maps API being down:
E/HmsMapKit_ErrorTraceLogPusher_4: cache error trace log : ErrorTraceLogDTO{ scenario = ACCESS_SERVICE_ERROR', message='060001 : NETWORK_ERROR'}
com.huawei.hms.maps.foundation.client.mac: *e*v*r*A*d*e*s*f*o* *R* *s*e*p*y*
at com.huawei.hms.maps.foundation.client.mac$maa.b(Unknown Source:25)
This is disturbing, because there's no sign of this error code in the official Map Kit error codes documentation. Does anyone know what's going on? Thanks in advance!
Solved it! Here's my config:
HMS Core: latest version as of 14/03/2022 (6.4.0.306)
Map Kit: latest version as of 14/03/2022 (implementation 'com.huawei.hms:maps:6.3.1.300')
Main cause: my app signing configuration was missing in my build.gradle file.
Steps to solve it:
Deleted my existing keystore (.jks). DISCLAIMER: you will lose the capacity to update your app if it's released in AppGallery. Please do it as a last resort.
Created a new keystore INSIDE my Android Studio project, under the app directory.
Generated a signed APK for release and obtained the SHA-256 fingerprint.
Replaced my former fingerprint with the new one in AppGallery Connect.
In my map activity, DIDN'T encode my API key (thanks shirley!)
Rebuilt my project.
Complete instructions are here.
Update
This problem has been fixed in the latest version of the HMS Core. Try to upgrade the HMS Core apk to the latest version which may solve this issue.
Currently, the latest version of the HMS Core is 6.5.0.312.
Thank you for providing the information regarding this issue. We have reported this issue to the R&D team for handling, may i confirm is the HMS Core 6.4.0 installed on your device? You are advised to roll back to HMS Core 6.3 version apk. And we will release a patch package as soon as possible to fix this issue.

Got error 403 (Forbidden) when importRoute using Here Android SDK

I'm trying to import a list of Location to calculate the route (using Here Android SDK). However I always got error: (403) Forbidden.
Here SDK's guide: https://developer.here.com/documentation/android-sdk-explore/4.10.5.0/dev_guide/topics/routing.html#import-routes-from-other-services
I've checked key, key_secret and appID for my project, every things is fine.
Here is my code:
val routingEngine = RoutingEngine()
routingEngine.importRoute(
generateGeoLists(),
CarOptions()
) { routingError, routes ->
if (routingError == null) {
routes?.getOrNull(0)?.let {
showRouteOnMap(it)
}
} else {
DebugLog.d("Error import", "import failed: $routingError")
}
}
Please help me to solve this.
Note: Other methods like 'calculateRoute',... work fine except 'importRoute'.
I'm using Here SDK Explore edition.

io.grpc.StatusRuntimeException: UNAUTHENTICATED: Credentials require channel with PRIVACY_AND_INTEGRIY

I am using Dialogflow Java Client library in my android app, to run the detect intent API as given in below link.
https://github.com/dialogflow/dialogflow-java-client-v2/blob/master/samples/src/main/java/com/example/dialogflow/DetectIntentTexts.java
I modified the code given in above link slightly to authenticate the client first before sending the detect intent request. My sample code is as follows:
SessionsSettings sessionsSettings = SessionsSettings.newBuilder().setCredentialsProvider(credentialsProvider).build();
SessionsClient sessionsClient = SessionsClient.create(sessionsSettings);
SessionName session = SessionName.of(PROJECT_ID, sessionId);
System.out.println("Session Path: " + session.toString());
TextInput.Builder textInput = TextInput.newBuilder().setText(text).setLanguageCode(langCode);
QueryInput queryInput=QueryInput.newBuilder().setText(textInput).build();
DetectIntentResponse response = sessionsClient.detectIntent(session, queryInput);
where
CredentialsProvider credentialsProvider = new CredentialsProvider() {
#Override
public Credentials getCredentials() throws IOException {
InputStream fileStream = appContext.getApplicationContext().getAssets().open("MyDialogflowProject-4cxxxxx.json");
return ServiceAccountCredentials.fromStream(fileStream);
}
};
But I get the following error
com.google.api.gax.rpc.UnauthenticatedException:
io.grpc.StatusRuntimeException: UNAUTHENTICATED: Credentials require
channel with PRIVACY_AND_INTEGRITY security level. Observed security
level: NONE
at com.google.api.gax.rpc.ApiExceptionFactory.createException(ApiExceptionFactory.java:73)
Can anyone please tell how to set the Security Level for SessionSettings in this case ?
Try to update library versions you are using. On transport layer Security Level should be setup.
For example gradle dependencies from my hello world project which is working with dialogflow v2:
dependencies {
compile ("com.google.api.grpc:proto-google-common-protos:1.12.0")
compile ("io.grpc:grpc-netty:1.14.0")
compile ("io.grpc:grpc-protobuf:1.14.0")
compile ("io.grpc:grpc-stub:1.14.0")
compile ("com.google.auth:google-auth-library-oauth2-http:0.10.0")
compile ("com.google.cloud:google-cloud-storage:1.38.0")
compile ("io.netty:netty-tcnative-boringssl-static:2.0.12.Final")
compile ("com.google.cloud:google-cloud-dialogflow:0.55.1-alpha")
}
In my case, I have found out that I have set the IntelliJ environment variable to FIRESTORE_EMULATOR_HOST=localhost:8080 to use the Firebase emulators in the past.
Later I tried to push data to Cloud Firestore without removing that variable, but the attempts were unsuccessful with the error PRIVACY_AND_INTEGRITY.
After some time, I found the localhost setting and removed it. Once removed, I was able to push the data to the cloud without any issues.

Generate Cloud Endpoint Client Library in Android Studio using Entity Class Design Pattern

While following the steps outlined here :
https://cloud.google.com/developers/articles/how-to-build-mobile-app-with-app-engine-backend-tutorial/
for creating a cloud endpoint, but using Android Studio instead of Eclipse, I am stuck at Step 9 of the Entity Class Design Pattern as described here :
https://cloud.google.com/developers/articles/how-to-build-mobile-app-with-app-engine-backend-tutorial/#ecdp
In Eclipse, there is a right-click-menu-option for "Generate Cloud Endpoint Client library" when you right-click on the app engine project. However, there is no equivalent option in Android Studio (v1.0.0)
Is this an omission on Google's part or am I missing something.
What is the best workaround for generating the cloud endpoint client library from within Android Studio.
Is there a way to do it from the command-line?
I did find the steps for gradle here :
https://cloud.google.com/appengine/docs/java/endpoints/endpoints_tool
and here :
https://cloud.google.com/appengine/docs/java/endpoints/consume_android
but these are much more time-consuming than the single-step process described in the original link for eclipse.
As stated above the libraries are auto-compiled for you, the other point to note that had me confused is where to get the Builder from.
Now as of Android Studio 1.0.1 the original Eclipse instructions are a little out of date for this as well, the "Builder" is no longer buried into the Endpoint class you make. Instead it is rolled into a separate API class to describe the Builder and associated code.
See: https://github.com/GoogleCloudPlatform/gradle-appengine-templates/tree/master/HelloEndpoints
Endpoint Usage from Android would now look like this:
/* OLD
MyEndpoint.Builder builder = ... */
MyApi.Builder builder = new MyApi.Builder(AndroidHttp.newCompatibleTransport(),
new AndroidJsonFactory(), null)
// options for running against local devappserver
// - 10.0.2.2 is localhost's IP address in Android emulator
// - turn off compression when running against local devappserver
.setRootUrl("http://10.0.2.2:8080/_ah/api/")
.setGoogleClientRequestInitializer(new GoogleClientRequestInitializer() {
#Override
public void initialize(AbstractGoogleClientRequest<?> abstractGoogleClientRequest) throws IOException {
abstractGoogleClientRequest.setDisableGZipContent(true);
}
});
We're working on updating that shopping kart sample to use Android Studio.
In the meantime the documentation for generating endpoints in AS can be found here https://cloud.google.com/tools/android-studio/
There is no 'Generate Cloud Endpoint Client Library' task anymore since it's not needed in the Android Studio workflow. Simply building the project will ensure that the client libraries are available to your android app.
Check out the docs for the appengine gradle plugin https://github.com/GoogleCloudPlatform/gradle-appengine-plugin if you want to be able to manually perform some of the endpoint client library steps from the command line using Gradle.
As Lucien Murray-Pitts explained, the Builder is not in the Endpoint class but in a auto-generated XXXXApi class.
Imagine your java bean is a class called Portfolio under package com.example.backend
You have to add the following import in the AsyncTask class:
import com.example.backend.portfolioApi.PortfolioApi;
and then you can do
PortfolioApi.Builder builder = new PortfolioApi.Builder(....

Categories

Resources