Amplify.Storage.** does not work for me on Android - android

I am using AWS Amplify to make an Android app. I followed the official tutorial to add Authentication, API, and Storage. https://aws.amazon.com/getting-started/hands-on/build-android-app-amplify/module-one/ . But when I run Amplify.Storage.** it doesn't respond at all. There is no error message so I cannot track the issue. Does anyone have suggestions as to what might be wrong?
This is my uploadFile() function:
fun storeAudio(filePath: String, key: String) {
val file = File(filePath)
val options = StorageUploadFileOptions.builder()
.accessLevel(StorageAccessLevel.PROTECTED)
.build()
scope.launch {
Amplify.Storage.uploadFile(
key,
file,
options,
{ progress -> Log.i(TAG, "Fraction completed: ${progress.fractionCompleted}") },
{ result -> Log.i(TAG, "Successfully uploaded: " + result.key) },
{ error -> Log.e(TAG, "Upload failed", error) }
)
}
}
Amplify is configured properly. And my amplifyconfiguration.json file looks correct, but let me know if you need to take a look at it.

Related

PushNotificationsAPI: Failed to register device: NOKResponse(error=Unauthorized)

I am using Pusher Beams for sending notification to my users. It worked fine but today I got this error, and I don't know how to solve it.
PushNotificationsAPI: Failed to register device: NOKResponse(error=Unauthorized, description=The device token provided could not be validated against any known credentials)
This is my code:
private fun setPusherBeam() {
try {
val tokenProvider = BeamsTokenProvider(
BuildConfig.PUSHER_BEAM,
object : AuthDataGetter {
override fun getAuthData(): AuthData {
return AuthData(
headers = hashMapOf(
"Authorization" to getHawkString(AUTH_TOKEN)
),
queryParams = hashMapOf()
)
}
}
)
PushNotifications.setUserId(
DbHelper.getUser()?.user_id.toString(),
tokenProvider,
object : BeamsCallback<Void, PusherCallbackError> {
override fun onFailure(error: PusherCallbackError) {
Timber.i("BeamsAuth Could not login to Beams: ${error.message}")
}
override fun onSuccess(vararg values: Void) {
Timber.i("BeamsAuth Beams login success $values")
}
}
)
} catch (ex: Exception) {
Timber.i("BeamsAuth ex ${ex.localizedMessage}")
}
}
After 2days of struggling with this error, finally, it resolved due to these steps.
1-stop the API
PushNotifications.start(applicationContext, BuildConfig.INSTANCE_ID)
PushNotifications.stop()
PushNotifications.removeDeviceInterest("example")
PushNotifications.clearDeviceInterests()
2-clear android studio cash and reset it
3-remove the app from mobile and reinstall it
4-replace code from step1 with this
PushNotifications.start(applicationContext, BuildConfig.INSTANCE_ID)
PushNotifications.addDeviceInterest("example")
5-repeat 2 and 3
Delete the generated values.xml under app\build\generated\res\google-services\debug\values, then delete the app and build again. Took me a while to figure this out.

Android: AWS Amplify User State is not getting update

I have just started learning AWS Amplify and I am integrating it to my android project to authenticate users. I have successfully logged-in but UserState is still SIGNED_OUT.
AWSMobileClient.getInstance().signIn(userName, password, null, callback)
Callback Code snippet
fun fetchAuthenticationCallBack(): Callback<SignInResult> {
return object : Callback<SignInResult> {
override fun onResult(result: SignInResult?) {
when (result?.signInState) {
SignInState.DONE -> {
// AWSMobileClient.getInstance().confirmSignIn()
Log.d(TAG, "LOGIN SUCCESS ${AWSMobileClient.getInstance().tokens.accessToken}")
}
SignInState.NEW_PASSWORD_REQUIRED -> {
Log.d(TAG, "NEW PASSWORD CHALLENGE")
}
else -> {
// Unsupported sign-in confirmation:
}
}
}
override fun onError(e: java.lang.Exception?) {
TODO("Not yet implemented")
}
}
}
I want to get the accessToken but it gives me Exception
Token does not support retrieving while user is SIGN_OUT
Is there anything that I am missing in the authentication part?
If anyone will face this issue in the future.
Kindly check your awsconfiguration.json file there is something went wrong. In my case CognitoIdentity credentials were wrong. I have just fixed the awsconfiguration.json file everything is working as expected

Is it possible to generate an APK file from a base64String API response call?

I'm currently working on a solution how to update and install APK file programmatically - very similar like this issue. My app doesn't use Google Services.
For updating purposes, APK-files with ascending versions are stored on an internal server and a C# Web service returns the latest version of the APK file.
I do this with Retrofit2:
#Streaming
#GET("/ws/webservice.svc/getUpdate")
fun getUpdate(
#Query("Programm") program: String,
#Query("version") version: String,
#Query("test") test: Boolean
): Single<String>
and LiveData:
override fun getUpdate() {
disposables += api.getUpdate(
program = context.getString(R.string.app_name),
version = context.getString(R.string.app_version),
test = isTest
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeBy(
onSuccess = {
liveData.value = GetUpdate(it)
},
onError = {
liveData.value = Error("Error getUpdate: " + it.message)
}
)
}
The problem that I'm facing, is that the response of that API call (which means - the latest APK file) has a base64String representation like shown in the image below - this is for example only a part of the server response when the API call is made in browser.
Is it somehow possible to generate a "real" APK file from this String representation after downloading it, so after that I can probably be able to install it on the device? I know that this is weird, but the customer wants me to re-use the same web service for this purposes.
I found a similar issue here. How can be this done in Kotlin? Thanks in advance.
Yes you need to decode the base64 into a ByteArray then write the bytes to a location with the postfix .apk. What you have is a String where the bytes are encoded using the base64 encoding scheme.
Since your using kotlin you might what to look here to get the ByteArray![1] from the String. Then just ensure the file you write has .apk extension.
[1] https://developer.android.com/reference/kotlin/java/util/Base64.Decoder#decode(kotlin.String)
AndroidManifest.xml
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
MVVM with LiveData:
override fun getUpdate() {
disposables += api.getUpdate(
program = context.getString(R.string.app_name) + ".apk",
version = context.getString(R.string.app_version),
test = isTest
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.map(::decodeToAPK)
.subscribe({
liveData.value = GetUpdate
}, {
liveData.value = Error("Error getUpdate: " + it.message)
})
}
private fun decodeToAPK(base64String: String) {
val byteArrayAPK = Base64.decode(base64String, Base64.DEFAULT)
val file =
File(context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "yourApp.apk")
try {
val fileOutputStream = FileOutputStream(file)
fileOutputStream.write(byteArrayAPK)
fileOutputStream.flush()
fileOutputStream.close()
} catch (e: UnsupportedEncodingException) {
Log.d(null, "error writing APK")
e.printStackTrace()
}
}
sealed class SomeAction : Action {
data class Error(val message: String) : SomeAction()
object GetUpdate : SomeAction()
}

How to sign in a user with AWS Amplify on Android + Kotlin?

I'm trying to make an Android app with a sign in screen on Android in Kotlin using AWS Amplify, here's my sign in code:
AWSMobileClient.getInstance().signIn(username, password, null, object : Callback<SignInResult> {
override fun onResult(signInResult: SignInResult) {
runOnUiThread {
Log.d("DEBUG", "Sign-in callback state: " + signInResult.signInState)
when (signInResult.signInState) {
SignInState.DONE -> Log.d("DEBUG", "Sign-in done.")
SignInState.SMS_MFA -> Log.d("DEBUG", "Please confirm sign-in with SMS.")
SignInState.NEW_PASSWORD_REQUIRED -> Log.d("DEBUG", "Please confirm sign-in with new password.")
else -> Log.d("DEBUG", "Unsupported sign-in confirmation: " + signInResult.signInState)
}
}
}
override fun onError(e: Exception) {
Log.e("DEBUG", "Sign-in error", e)
}
})
I used the documentation of Amazon here, copied and pasted the block found at the Sign In chapter into Android Studio that automatically converted the Java code into Kotlin.
Using logs I see that my code above this one is executed when I press the login button but the onResult block is never called. The logs only print a D/AWSMobileClient: Sending password. from AWS sdk.
I remember that this code worked before Christmas holidays so I think that it's maybe a change on the Amazon side but I find nothing in the documentation.
Do you have any idea of what's wrong here ?

Kotlin - Obfuscated Property Names

I'm developing a Kotlin Android app and I'm having an issue integrating Google Sign In, when I get the GoogleSignInAccount in order to extract properties, the property names seem to be obfuscated (or otherwise jumbled up), here's a screenshot of the way the properties look on AS 2.3 debugger:
Here's the snippet of code that tries to access those properties:
private fun googleSignInResult(data : GoogleSignInResult) {
if (data.isSuccess) {
if (data.signInAccount != null) {
val account = data.signInAccount
val authData = HashMap<String, String>()
authData["id_token"] = account?.idToken.let { it } ?: return
authData["id"] = account?.id.let { it } ?: return
val task = ParseUser.logInWithInBackground("google", authData)
task.continueWith { user ->
if (task.isCancelled) {
Log.d(TAG, "User cancelled Google login")
} else if (task.isFaulted) {
Log.d(TAG, "Failed: " + task.error)
} else {
this.user = task.result
this.user?.put("email", account?.email)
this.user?.put("name", account?.displayName)
this.user?.put("firstName", account?.displayName)
this.user?.saveInBackground({ error ->
if(error != null) {
Log.d(TAG, "Error: " + error.message)
this.user?.deleteInBackground()
ParseUser.logOutInBackground()
} else {
//Logged in successfully
}
})
}
}
}
}
}
Can anyone shed some light on why is it that properties look like that?, when I try to access idToken or id they're always null, however, the property names that are "obfuscated" can't be accessed, is this a kotlin bug or is it my error?
Any help will be much appreciated!
The following content is originally posted by #EugenPechanec as a comment to the question body. Some modification is applied to promote reading experience.
Fields, a term from JVM, is not properties, which is a Kotlin term. You're on JVM, and what you see in the debugger are obfuscated fields backing the Kotlin properties. The getters are public and retain original names. Java .getDisplayName() is .displayName in Kotlin.

Categories

Resources