I am working on NGenious payment SDK and trying to implement it in my Kotlin project but when the SDK shows up in Fragment, after 2 to 3 seconds the screen automatically got white and nothing is being shown.
This is the payment SDK
Method to launch payment Fragment
activity?.let {
PaymentClient(it).launchCardPayment(
CardPaymentRequest.builder()
.gatewayUrl(paymentOption.paymentCreateOrderResponse.data?.links?.paymentAuthorization?.href?:"")
.code(Constants.currencyCode)
.build(), CARD_PAYMENT_REQUEST_CODE)
}
onActivityResult Method
override fun onActivityResult(
requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
Log.e("onActivityResult","onActivityResult" + resultCode)
if (requestCode == CARD_PAYMENT_REQUEST_CODE) {
when (resultCode) {
Activity.RESULT_OK -> onCardPaymentResponse(CardPaymentData.getFromIntent(data!!))
Activity.RESULT_CANCELED -> onCardPaymentCancelled()
}
Log.e("resultCode CCPF","" + resultCode)
}
Log.e("CPRC CCPF","" + CARD_PAYMENT_REQUEST_CODE)
}
As I review your CardPaymentRequest builder you are sending the Currency Code in the code field thats why they throwing an exception on it.
pass payment code in the code field, you can get the code by this field.
paymentOption.paymentCreateOrderResponse.data?.links?.payment?.href?.split("=")!!.get(1)
Now run the code like that.
activity?.let {
PaymentClient(it).launchCardPayment(request = CardPaymentRequest.builder()
.gatewayUrl(paymentOption.paymentCreateOrderResponse.data?.links?.paymentAuthorization?.href?:"")
.code(paymentOption.paymentCreateOrderResponse.data?.links?.payment?.href?.split("=")!!.get(1))
.build(), requestCode = CARD_PAYMENT_REQUEST_CODE)
}
Related
I implemented the google sign in api in my android app. Everything was fine until recently. One of the challenges I had was with client_id which regenerated. The most recent that has opened more errors is that the google sign in wont work in the release.apk that built.
After two days of debugging I decided to create a new demo project to start the process afresh. It won't work as the task return false for task.isSuccessful.
Perhaps there is something I am missing.
const val RC_SIGN_IN = 0
class MainActivity : AppCompatActivity() {
lateinit var observer:StartActivityForResults
private lateinit var mGoogleSignInClient:GoogleSignInClient
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
observer = StartActivityForResults(activityResultRegistry)
lifecycle.addObserver(observer)
val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.build()
mGoogleSignInClient = GoogleSignIn.getClient(this, gso);
sign_in_button.setOnClickListener{
signIn()
}
}
private fun signIn() {
val signInIntent = mGoogleSignInClient.signInIntent
startActivityForResult(signInIntent, RC_SIGN_IN)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
// Result returned from launching the Intent from GoogleSignInClient.getSignInIntent(...);
if (requestCode == RC_SIGN_IN) {
// The Task returned from this call is always completed, no need to attach
// a listener.
val task = Auth.GoogleSignInApi.getSignInResultFromIntent(data)
task?.isSuccess
Toast.makeText(this, "Success", Toast.LENGTH_LONG).show()
}
else{
Log.i("title", "OKCODE ${Activity.RESULT_OK} RESULTCODE ${resultCode}")
}
}
}
Easily add sign-in to your Android app with FirebaseUI
If you haven't already, add Firebase to your Android project.
Add the dependencies for FirebaseUI to your app-level build.gradle file
dependencies {
// ...
implementation 'com.firebaseui:firebase-ui-auth:6.2.0'
}
In the Firebase console, open the Authentication section and enable the sign-in methods you want to support. Some sign-in methods require additional information, usually available in the service's developer console.
If you support Google Sign-in and haven't yet specified your app's SHA-1 fingerprint, do so from the Settings page of the Firebase console
// Choose authentication providers
val providers = arrayListOf(
AuthUI.IdpConfig.EmailBuilder().build(),
AuthUI.IdpConfig.PhoneBuilder().build(),
AuthUI.IdpConfig.GoogleBuilder().build(),
AuthUI.IdpConfig.FacebookBuilder().build(),
AuthUI.IdpConfig.TwitterBuilder().build())
// Create and launch sign-in intent
startActivityForResult(
AuthUI.getInstance()
.createSignInIntentBuilder()
.setAvailableProviders(providers)
.build(),
RC_SIGN_IN)
When the sign-in flow is complete, you will receive the result in onActivityResult:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == RC_SIGN_IN) {
val response = IdpResponse.fromResultIntent(data)
if (resultCode == Activity.RESULT_OK) {
// Successfully signed in
val user = FirebaseAuth.getInstance().currentUser
// ...
} else {
// Sign in failed. If response is null the user canceled the
// sign-in flow using the back button. Otherwise check
// response.getError().getErrorCode() and handle the error.
// ...
}
}
}
Not sure if this answers your question, but I faced a similar issue where signing worked in debug builds and wouldn't work for release builds.
In the Firebase console, if you have Google Sign in enabled you will be prompted to enter the SHA-1 Key of your build. Now, what happened in my case was I got the SHA-1 key for debug keystore and didn't do it for the release key-store.
Try,
keytool -list -v
-alias -keystore <path-to-production-keystore
and entering it on your Firebase console.
I am using prebuilt Firebase UI to authenticate user such as below:
val providers = arrayListOf(
AuthUI.IdpConfig.EmailBuilder().build(),
AuthUI.IdpConfig.GoogleBuilder().build())
startActivityForResult(
AuthUI.getInstance().createSignInIntentBuilder()
.setAvailableProviders(providers)
.build(),
RC_SIGN_IN)
How do I attach a OnCompleteListener during sign-in? More specifically, I want to call getAdditionalUserInfo().isNewUser() to check if the user is first time log in. I know I can add onCompleteListener if I sign in using email and password-based method, but I want to handle multiple sign-in providers using the prebuilt UI method above.
In onActivityResult you receive the result for the sign in with some data passed as Parcelable which u are already overriding for validation!
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == RC_SIGN_IN) {
// this class has all the needed data !
val response = IdpResponse.fromResultIntent(data)
if (resultCode == Activity.RESULT_OK) {
// Successfully signed in
val isNewUser = response?.isNewUser!! // flag to check if the user is first time login
}
}
}
#See class IdpResponse of package com.firebase.ui.auth:-
Dug a bit deep for you ;) Happy coding!
I have a fragment in my activity, that it will get some data on its onActivityResult(), And try to update the UI. This is my onActivityResult() code:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when (requestCode) {
GET_USER_AUDIO_TO_TEXT_REQUEST_CODE -> {
if (resultCode == RESULT_OK) {
data?.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS)?.let {
val receivedCityName = it[0]
binding.homeCityNameEditTextView.setText(receivedCityName)//Update UI at this line
viewModel.fetchWeatherCity(receivedCityName)
}
} else {
Toast.makeText(activity, R.string.error_while_getting_data_from_recognizer, Toast.LENGTH_SHORT).show()
}
}
}
}
So I tried to create some Instrumentation test with the Espresso for this part as bellow:
#Test
fun checkActionsAfterReceivingDataInOnActivityResult() {
val intent = Intent()
intent.putStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS, arrayListOf(DEFAULT_CITY_NAME))
activityRule.activity.supportFragmentManager
.findFragmentByTag(HomeFragment.CLASS_NAME)
?.onActivityResult(
HomeFragment.GET_USER_AUDIO_TO_TEXT_REQUEST_CODE,
Activity.RESULT_OK,
intent
)
}
But I will get an error after running this Test method that says:
This error is because of my ViewModel methods that will run. by calling this line in onActivityResult():
viewModel.fetchWeatherCity(receivedCityName)
This is its error:
java.lang.IllegalStateException: Cannot invoke setValue on a background thread
at android.arch.lifecycle.LiveData.assertMainThread(LiveData.java:435)
at android.arch.lifecycle.LiveData.setValue(LiveData.java:279)
And because of updating my UI by this line:
binding.homeCityNameEditTextView.setText(receivedCityName)//Update UI at this line
I will get this error too:
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
Test instrumentation runs on a different thread, so wrap up the test method-body with run on UI thread.
activityRule.activity.runOnUiThread {
// the test method body goes in here
}
In your case:-
activityRule.activity.runOnUiThread {
activityRule.activity.supportFragmentManager
.findFragmentByTag(HomeFragment.CLASS_NAME)
?.onActivityResult(
HomeFragment.GET_USER_AUDIO_TO_TEXT_REQUEST_CODE,
Activity.RESULT_OK,
intent)
}
You shouldn't invoke methods such as onActivityResult directly in your Espresso test. You will always get the same error because these tests are executed on different threads. If you want to test it correctly, you should consider using Espresso-Intents:
#Test
fun checkActionsAfterReceivingDataInOnActivityResult() {
val intent = Intent()
intent.putStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS, arrayListOf(DEFAULT_CITY_NAME))
intending(hasComponent(YourActivity.class.getName())).respondWith(ActivityResult(Activity.RESULT_OK, intent))
// onView(...).perform(click())
// First do something to cause your app to launch the intended activity
// onView(...).check(matches(...))
// Then test something on activity result
}
I am using the following code to open the calendar app:
class Appointments : AppCompatActivity() {
lateinit var tv:TextView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_appointments)
tv = findViewById(R.id.textView4)
tv.setOnClickListener(View.OnClickListener {
var callIntent = Intent(Intent.ACTION_EDIT)
.setType("vnd.android.cursor.item/event")
startActivityForResult(callIntent, 3);
})
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if(requestCode == 3 && resultCode == Activity.RESULT_OK && data!=null){
Toast.makeText(this#Appointments,"Some data came",Toast.LENGTH_SHORT).show()
} else{
Toast.makeText(this#Appointments,"Some Error",Toast.LENGTH_SHORT).show()
}
}
}
I keep getting 'some error' message. I tried removing 'data!=null' but I think the resultcode is the problem.
What I 'finally' want to achieve is this:
User opens the app
User clicks on a button to open the calendar app
User is able to see the calendar and then the user makes an appointment in the calendar
User comes back to the app and I am able to extract the date and time of the new appointment
Is it possible to do? If yes then some code example will be much appreciated.
If it is not possible then what are the other ways to achieve this?
Remove the call to super. Calling super will change the requestCode. This fact isn't exactly clear in a lot of documentation but I have spun my tires on it in the past. Similarly, you will find this answer Wrong requestCode in onActivityResult useful if you encounter a similar issue with fragment to activity communication
I am trying to implement `KeyManager' into my app. When authorized action is needed, user is prompted with pattern for unlock. I observe result of this in my activity and based on result I proceed to further action. Following is code I am using,
private const val RESULT_OK = 99
val km = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
val i = km.createConfirmDeviceCredentialIntent("Name", "Something")
i?.let { ind ->
startActivityForResult(ind, RESULT_OK)
// startActivityForResult(Intent(this#LoginActivity, AnotherActivity::class.java), RESULT_OK) //This works
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
Log.i("TAG======", requestCode.toString() + "--" + resultCode.toString())
}
Whenever I am using startActivityForResult(ind, RESULT_OK) onActivityResult is not called but when I used any other activity like startActivityForResult(Intent(this#LoginActivity, AnotherActivity::class.java), RESULT_OK) , onActivityResult is getting called after activity is finished. Am I missing something? I am testing this on physical device (OnePlus 5t) running Android 8.1.
I found the answer after 2 hours of debugging ! This was happening because I was using RESULT_OK constant as private. As soon as I made it public, my KeyManager was working properly! I assume system was taking it as a 0 and hence it was not returning anything to activity :)