how to Send object/string from android Activity onActivityResult to react native - android

In my react native project ,I have implemented payment native sdk in android (that does not supported in react native).so i am tried to call native sdk with native modules..
i am able calling the payment SDKUI from react native native module ,but when the time of results can not send results back to react native component..
Payment gateway is -> PAYUBIZ
for more details pls find below code..
at the end of payment gateway i have displayed payment response in android native alert..
Code used..
1. Created NATIVE MODULES in react native side..
import {NativeModules} from 'react-native';
module.exports = NativeModules.PayUBizAccess;
in button action following code to call native method from android
PayUBizAccess.showPayuBiz();
2. Created ReactContextBaseJavaModule based PayUBizModule
#ReactMethod
public void showPayuBiz() {
final Activity activity = getCurrentActivity();
Intent intent = new Intent(activity, PayuActivity.class);
getReactApplicationContext().startActivity(intent);
}
PayuActivity.class is the payment activity class
3. Display results after payment success or failure..
#Override
public void onActivityResult(int requestCode, int resultCode, final Intent data) {
if (requestCode == PayuConstants.PAYU_REQUEST_CODE) {
if (data != null) {
new AlertDialog.Builder(this)
.setCancelable(false)
.setMessage("Payu's Data : " + data.getStringExtra("payu_response") + "\n\n\n Merchant's Data: " + data.getStringExtra("result"))
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dialog.dismiss();
finish();
}
}).show();
} else {
Toast.makeText(this, getString(R.string.could_not_receive_data), Toast.LENGTH_LONG).show();
}
}
}
4. After alert clicking button in alert it directly moves to react native component..
So now i want results data's to react native ,Kindly suggest me any solutions
thanks in advance

You can send an event from your native code like this:
private void sendEvent(ReactContext reactContext,
String eventName,
#Nullable WritableMap params) {
reactContext
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
//supply the result in params
.emit(eventName, params);
}
And in your react native code you can receive the event like this:
componentWillMount: function() {
DeviceEventEmitter.addListener('keyboardWillShow', function(e: Event) {
// handle event.
});
}
Check full docs here
Another way of doing this is given here

I would suggest use of promise.
In your native module have a property as Promise mPromise;(also include import com.facebook.react.bridge.Promise;)
And accept promise in your react native method as
#ReactMethod
public void showPayuBiz(Promise promise) {
mPromise = promise;
final Activity activity = getCurrentActivity();
Intent intent = new Intent(activity, PayuActivity.class);
getReactApplicationContext().startActivity(intent);
}
And in your onActivityResult you can use it as follows.
#Override
public void onActivityResult(int requestCode, int resultCode, final Intent data)
{
if (requestCode == PayuConstants.PAYU_REQUEST_CODE) {
//example for handling success response
this.promise.resolve(data.getDataString()); // you can further process this data in react native component.
}
else{
//example for handling error response
this.promise.reject(data.getDataString());
}
}
Then you can use it as follows
PayUBizAccess.showPayuBiz()
.then(data => {
console.log(data);
//success
})
.catch(error => {
console.log(data);
//failure
});
Edit
If onActivityResult() is in another file. add mReactInstanceManager.onActivityResult(requestCode, resultCode, data); in onActivityResult() which is in MainActivity.
And inside you native module, add following method.
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
this.mPromise.resolve(data.getDataString());
}

I have used #Ayush Khare responses..faced few issues while debugging ..so i post here exact answer
1.React Native Side
Component will mount add following
DeviceEventEmitter.addListener('PAYUEVENT', this.payuResponseGet);debugger
Add following method for trigger event
payuResponseGet = (payUData) => {
console.log(payUData);debugger // logging twice
// this.setState({
// modalVisible: args.visible
// })
}
2. Activity side
import com.facebook.react.ReactInstanceManager;
//import com.facebook.react.ReactApplicationContext;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.modules.core.DeviceEventManagerModule;
Add following on result method
// mPromise.resolve(data.getDataString());
ReactInstanceManager mReactInstanceManager = getReactNativeHost().getReactInstanceManager();
ReactApplicationContext context = (ReactApplicationContext) mReactInstanceManager.getCurrentReactContext();
WritableMap payuData = Arguments.createMap();
payuData.putString("PayuResponses", data.getStringExtra("payu_response"));
payuData.putString("Merchant's Data", data.getStringExtra("result"));
sendEvent(context,"PAYUEVENT",payuData);
//send event method
private void sendEvent(ReactContext reactContext,
String eventName,
#Nullable WritableMap params) {
reactContext
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
//supply the result in params
.emit(eventName, params);
}
once added above, run and get responses from trigger event method..

Related

Open Android Activity and iOS ViewController from Flutter

I have a Flutter project that requires some certain features that needs to be implemented in native Android Activity or iOS ViewController. is there a way to navigate to android Activity and pass data to it and also retrieve data from it in Flutter?
and if it's impossible, is it possible to show an Activity or fragment from Android, and a ViewController from iOS, as a Widget in Flutter?
Not sure whether this is the best way and I only created it for Android, but this is what I did.
Simple Flutter method channel calling native:
static const platform = const MethodChannel(MY_CHANNEL);
string result await platform.invokeMethod("mycall");
From the native Android part in your mainActivity:
//Class attribute
private Result myresult;
//Method chanel
new MethodChannel(getFlutterView(), MY_CHANNEL).setMethodCallHandler(
(call, result) -> {
// Note: this method is invoked on the main thread.
if (call.method.equals("mycall")) {
myresult = result; //Store the flutter result
Intent intent1 = new Intent(MyClass.class);//Start your special native stuff
startActivityForResult(intent1, RQ_CODE);
} else {
result.notImplemented();
}
});
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Check which request we're responding to
if (requestCode == RQ_CODE) {
myresult.success("this will be your result"); //Probably do something with the data instead of a static string.
}
}
Basically the same can be done for iOS
use intent or android_intent packages for android and for ios use https://flutter.dev/docs/get-started/flutter-for/ios-devs link

Xamarin Android: using StartActivityForResult(); resultCode in OnActivityResult is always "Canceled"

I have two separate applications written using Xamarin.Android; for the sake of discussion, let's call them "Tristan" and "Isolde". Tristan has some state information that Isolde sometimes needs to know. Complication: Tristan may or may not be running at the moment Isolde develops the need to know his state.
I've got kludge working now where Isolde sends a special launch intent to Tristan, who then uses a broadcast intent to send information back to Isolde. (See my earlier question for details.)
"But wait!" I hear you cry, "Is this not a perfect use case for StartActivityForResult()?" Indeed it is! The code is a whole lot simpler, and everything I've read implies that this is how Android wants you to do stuff like this.
Unfortunately, I can't get it to work (despite trying many variations and reading the dozen-or-so related questions on this very site). My specific problem is that in Isolde's OnActivityResult() callback, the resultCode is always Result.Canceled and the data is always null.
Here is the code for Tristan (where commented-out bits represent variations I've tried):
using Android.App;
using Android.Content;
namespace com.example.Tristan.Android
{
[Activity(Name ="com.example.Tristan.Android.IsoldeQueryActivity")]
public class IsoldeQueryActivity : Activity
{
protected override void OnStart()
{
// base.OnStart();
var rtn = new Intent();
rtn.PutExtra("Test", "test");
//rtn.SetAction("TestAction");
SetResult(Result.Ok, rtn);
Finish();
//FinishActivity(1234);
}
}
}
And here is the relevant code from the Activity where Isolde needs to ask for Tristan's state:
private TaskCompletionSource<bool> TristanStateCompletion;
public async Task GetTristanState()
{
TristanStateCompletion = new TaskCompletionSource<bool>();
var req = new Intent("com.example.Tristan.Android.IsoldeQueryActivity");
//req.PutExtra(Intent.ExtraReturnResult, true);
StartActivityForResult(req, 1234);
var rtn = await TristanStateCompletion.Task;
if (!rtn) bomb("can't get state");
TristanStateCompletion = null;
}
protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
if(requestCode == 1234) {
DoStuffWith(data);
TristanStateCompletion?.TrySetResult(true);
}
}
Diagnostics -- or rather, a specific lack of them -- leads me to believe that Tristan's IsoldeQueryActivity.OnStart() is never actually being called.
Ideas, requests for additional information and/or useful experiments to try are all welcome. (If your idea is "Put <thing> in the manifest", remember this is Xamarin.Android and I have to do that by putting <relatedThing> in the attribute decorating the Activity.)
Edited to add: In Isolde's code, DoStuffWith(data) was crashing because data was null. When I changed that method to avoid that, I found that I got a (slightly later) exception thrown in StartActivityForResult():
Android.Content.ActivityNotFoundException No Activity found to handle Intent { act=com.example.Tristan.Android.IsoldeQueryActivity }
This leads me to believe I'm not creating the Intent properly in Isolde. Do I need to be using one of the other Intent constructors? If so, how specifically?
Okay, I think I have this figured out. The code in my original question had three major problems:
I was building the Intent incorrectly in Isolde.
I didn't export the IsoldeQueryActivity in Tristan.
The call to base.OnStart() in Tristan's OnStart override is mandatory.
Here is the working version of Tristan:
using Android.App;
using Android.Content;
namespace com.example.Tristan.Android
{
[Activity(Name ="com.example.Tristan.Android.IsoldeQueryActivity", Exported=true)]
public class IsoldeQueryActivity : Activity
{
protected override void OnStart()
{
base.OnStart();
var rtn = new Intent();
rtn.PutExtra("Test", "test");
SetResult(Result.Ok, rtn);
Finish();
}
}
}
And here is the fixed code from Isolde:
private TaskCompletionSource<bool> TristanStateCompletion;
public async Task GetTristanState()
{
TristanStateCompletion = new TaskCompletionSource<bool>();
var req = new Intent();
req.SetComponent(new ComponentName("com.example.Tristan.Android", "com.example.Tristan.Android.IsoldeQueryActivity"));
StartActivityForResult(req, 1234);
var rtn = await TristanStateCompletion.Task;
if (!rtn) bomb("can't get state");
TristanStateCompletion = null;
}
protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
if(requestCode == 1234) {
if(resultCode != Result.Ok) bomb("bad resultCode {0}", resultCode);
if(data == null) bomb("null data from Tristan");
DoStuffWith(data);
TristanStateCompletion?.TrySetResult(true);
}
}

Braintree Android SDK Drop-in UI not displayed

I am trying to display the Drop-in UI in my app upon clicking a specific button. I have used the guide from Braintree site but for some reason nothing is happening.
Code below:
OnClick function:
public void onClick(View v){
switch (v.getId()){
case R.id.showUI_button:
onBraintreeSubmit(v);
break;
}
}
Drop-in functions:
public void onBraintreeSubmit(View v) {
PaymentRequest paymentRequest = new PaymentRequest()
.clientToken(token)
.amount("$10.00")
.primaryDescription("Awesome payment")
.secondaryDescription("Using the Client SDK")
.submitButtonText("Pay");
startActivityForResult(paymentRequest.getIntent(this), REQUEST_CODE);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE) {
if (resultCode == BraintreePaymentActivity.RESULT_OK) {
PaymentMethodNonce paymentMethodNonce = data.getParcelableExtra(
BraintreePaymentActivity.EXTRA_PAYMENT_METHOD_NONCE
);
String nonce = paymentMethodNonce.getNonce();
// Send the nonce to your server.
}
}
}
I have checked that the token is returned from the server.
I have also tried by setting the onClick via the xml code of the button and removing the onClick from the java file but the result is the same, no UI shown.
The log has only two lines
performCreate Call Injection Manager
Timeline: Activity_idle id:android.os.BinderProxy#etc
Any ideas? If more info is needed to understand better let me know
Actually I found this there is a "BraintreeFragment" set up part. Braintree documentation needs to be more clear on this I think.
https://developers.braintreepayments.com/guides/client-sdk/setup/android/v2
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
mBraintreeFragment = BraintreeFragment.newInstance(this, mAuthorization);
// mBraintreeFragment is ready to use!
} catch (InvalidArgumentException e) {
// There was an issue with your authorization string.
}
}
The above code should work along with the previous code posted. mAuthorization is the token and needs to be valid to show the payment screen (so the variable "token" in the previous code posted which in my code I just have as private but visible from the whole activity).
Try with the test token that they have on their page and if this works then the main setup is ok.
https://developers.braintreepayments.com/start/hello-client/android/v2
For setting up tokens on your server, they have further documentation so that those test tokens work on the sandbox.

Cordova (Android) Show Configuration page

As I do , from my APP , to show the settings page in Android GPS (only) ?
I want, if the GPS is off, to take the user directly to the configuration
Is it possible ?
With some plugin?
Thanks
First download custom plugin form here https://github.com/don/cordova-plugin-hello
Install plugin from local :- cordova plugin install LocalPathofDownloadedPlugin
and in JavaScript add following code:-
hello.greet("World", success, failure);
var success = function(message) {
alert(message);
}
var failure = function() {
alert("Error calling Hello Plugin");
}
once you installed the above plugin you will have one java file (Hello.java) in src folder:-
public class Hello extends CordovaPlugin {
#Override
public boolean execute(String action, JSONArray data, CallbackContext callbackContext) throws JSONException {
if (action.equals("greet")) {
//here you need to send intent
this.cordova.getActivity().startActivityForResult(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS), 1);
return true;
} else {
return false;
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == 1) {
switch (requestCode) {
case 1:
break;
}
}
}
}
I found the solution.
Thse two plugins can do it
https://www.npmjs.com/package/cordova.plugins.diagnostic#switchtolocationsettings
https://github.com/dpa99c/cordova-plugin-request-location-accuracy

PayPal Integration with Android

I have seen some related questions but none focusing on the specific problem I have:
I'm using the PayPal MPL Library.
I build my PayPalPayment object, then create the activity for the checkout to occur. That runs fine. My problem is, on the ResultDelegate I need to call a function from my activity, that occurs after the payment and makes some changes (such as storing SharedPreferences, etc.).
So something like this:
public class ResultDelegate implements PayPalResultDelegate, Serializable {
public void onPaymentSucceeded(String payKey, String paymentStatus) {
System.out.println("SUCCESS, You have successfully completed your transaction.");
System.out.println("PayKey: "+payKey);
System.out.println("PayStatus: "+paymentStatus);
callMyCustomAfterPaymentFunction();
}
...
}
Now the thing is, I tried to create a constructor for ResultDelegate that accepts my activity. My existing code is:
//On the activity class
public class MainMenuActivity extends Activity {
public void onCreate(Bundle savedInstanceState)
{
...
Button buy = (Button) findViewByID(R.id.buy_button);
buy.setOnClickListener(new View.OnClickListener(){
public void onClick(View v)
{
new PurchaseTask(activity).execute();
}
}
}
}
public class PurchaseTask extends AsyncTask <String, Void, String> {
protected String doInBackground()
{
...
PayPal pp = PayPal.getInstance();
CheckoutButton cb = pp.getCheckoutButton(...);
cb.setOnClickListener(new View.OnClickListener(){
public void onClick(View v){
ResultDelegate delegate = new ResultDelegate(myActivity);
Intent checkout = PayPal.getInstance().checkout(paument, activity, delegate);
activity.StartActivity(checkoutIntent);
}
}
}
}
//On the ResultDelegate class
public class ResultDelegate implements PayPalResultDelegate, Serializable {
private Activity myActivity;
public void onPaymentSucceeded(String payKey, String paymentStatus) {
System.out.println("SUCCESS, You have successfully completed your transaction.");
System.out.println("PayKey: "+payKey);
System.out.println("PayStatus: "+paymentStatus);
myActivity.performAfterPaymentOperations();
}
...
}
So the goal is to call the activity function from the ResultDelegate. Or even simpler, just to be able to store some SharedPreference changes when the ResultDelegate onPaymentSucceeded() fires.
But I get a NotSerializableException mentioning that the my MyActivity field is not Serializable.
So, then I added the transient identifier to my activity field inside the ResultDelegate, but now I get a NullPointerException.
Paypal Mobile Chekout guide
Implementation provided on paypal website is different from yours. They are doing startActivityForResult() to start PaypalActivity. and when in onActivityResult() method they are checking statusCode to check transaction status and act accordingly.
Follow that document for your implementation.
Here in your code, I donot find a point for using AsyncTask. Your ResultDelegate is Serializable where as Activity is not thats why it is throwing NotSerializableException.
Edit:
As you are developing for Google Android platform, then why not to use Google Checkout In-App?
Edit:
This method will be called when your PaypalActivity will finish. That activity will pass resultCode to this onActivityResult method.
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (resultCode) {
case Activity.RESULT_OK:
// The payment succeeded
String payKey = data.getStringExtra(PayPalActivity.EXTRA_PAY_KEY);
// Tell the user their payment succeeded
break;
case Activity.RESULT_CANCELED:
// The payment was canceled
// Tell the user their payment was canceled
break;
case PayPalActivity.RESULT_FAILURE:
// The payment failed -- we get the error from the EXTRA_ERROR_ID
// and EXTRA_ERROR_MESSAGE
String errorID = data.getStringExtra(PayPalActivity.EXTRA_ERROR_ID);
String errorMessage = data
.getStringExtra(PayPalActivity.EXTRA_ERROR_MESSAGE);
// Tell the user their payment was failed.
}
}
regards,
Aqif Hamid
You can create you custom listener something like this :
Create a custom listener :
OnDoubleTap mListener;
// Double tap custome listenre to edit photoes
public interface OnDoubleTap {
public void onEvent(Uri imgPath, int mPos);
}
public void setDoubleTapListener(OnDoubleTap eventListener) {
mListener = eventListener;
}
Now call this wherever you want like this :
mListener.onEvent(Uri, 1));
Now whenever you call this listener this will fire in your activity where you use this listener like this :
myCanvas.setDoubleTapListener(new OnDoubleTap() {
#Override
public void onEvent(Uri imgPath, int Pos) {
// TODO Auto-generated method stub
Toast.makeText(mContext, "LISTENER WORKING !!!", Toast.LENGTH_SHORT).show();
}
});
Where myCanvas is object of class where you create you listener.
Try this solution:
PayPalPayment thingToBuy = new PayPalPayment(new BigDecimal(price),getResources().getString(R.string.curruncy_code), getResources().getString(R.string.app_name),
PayPalPayment.PAYMENT_INTENT_SALE);
Intent intent = new Intent(CreateEventStep4.this, PaymentActivity.class);
intent.putExtra(PaymentActivity.EXTRA_PAYMENT, thingToBuy);
startActivityForResult(intent, REQUEST_PAYPAL_PAYMENT);
PaymentConfirmation confirm = data.getParcelableExtra(PaymentActivity.EXTRA_RESULT_CONFIRMATION);
if (confirm != null) {
try {
Log.e("paymentExample", confirm.toJSONObject().toString());
JSONObject jsonObj=new JSONObject(confirm.toJSONObject().toString());
String paymentId=jsonObj.getJSONObject("response").getString("id");
System.out.println("payment id:-=="+paymentId);
screenShotFile = takeScreenshot(frmTemplate);
uploadImage(myEvent.getEvent_id(),screenShotFile);
} catch (JSONException e) {
Log.e("paymentExample", "an extremely unlikely failure occurred: ", e);
}

Categories

Resources