I am basing my app off the foursquare-oAuth-sample app posted at Foursquare oAuth sample
Have made changes to MyActivity pretty much similar to the sample code but still getting this, can someone point out what I need to change, the code is as below
public class MyActivity extends FragmentActivity {
private static final int REQUEST_CODE_FSQ_CONNECT = 200;
private static final int REQUEST_CODE_FSQ_TOKEN_EXCHANGE = 201;
/**
* Obtain your client id and secret from:
* https://foursquare.com/developers/apps
*/
private static final String CLIENT_ID = "";
private static final String CLIENT_SECRET = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
ensureUi();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.my, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* Update the UI. If we already fetched a token, we'll just show a success
* message.
*/
private void ensureUi() {
boolean isAuthorized = !TextUtils.isEmpty(ExampleTokenStore.get().getToken());
TextView tvMessage = (TextView) findViewById(R.id.tvMessage);
tvMessage.setVisibility(isAuthorized ? View.VISIBLE : View.GONE);
Button btnLogin = (Button) findViewById(R.id.btnLogin);
btnLogin.setVisibility(isAuthorized ? View.GONE : View.VISIBLE);
btnLogin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Start the native auth flow.
Intent intent = FoursquareOAuth.getConnectIntent(MyActivity.this, CLIENT_ID);
// If the device does not have the Foursquare app installed, we'd
// get an intent back that would open the Play Store for download.
// Otherwise we start the auth flow.
if (FoursquareOAuth.isPlayStoreIntent(intent)) {
toastMessage(MyActivity.this, getString(R.string.app_not_installed_message));
startActivity(intent);
} else {
startActivityForResult(intent, REQUEST_CODE_FSQ_CONNECT);
}
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_CODE_FSQ_CONNECT:
onCompleteConnect(resultCode, data);
break;
case REQUEST_CODE_FSQ_TOKEN_EXCHANGE:
onCompleteTokenExchange(resultCode, data);
break;
default:
super.onActivityResult(requestCode, resultCode, data);
}
}
private void onCompleteConnect(int resultCode, Intent data) {
AuthCodeResponse codeResponse = FoursquareOAuth.getAuthCodeFromResult(resultCode, data);
Exception exception = codeResponse.getException();
if (exception == null) {
// Success.
String code = codeResponse.getCode();
performTokenExchange(code);
} else {
if (exception instanceof FoursquareCancelException) {
// Cancel.
toastMessage(this, "Canceled");
} else if (exception instanceof FoursquareDenyException) {
// Deny.
toastMessage(this, "Denied");
} else if (exception instanceof FoursquareOAuthException) {
// OAuth error.
String errorMessage = exception.getMessage();
String errorCode = ((FoursquareOAuthException) exception).getErrorCode();
toastMessage(this, errorMessage + " [" + errorCode + "]");
} else if (exception instanceof FoursquareUnsupportedVersionException) {
// Unsupported Fourquare app version on the device.
toastError(this, exception);
} else if (exception instanceof FoursquareInvalidRequestException) {
// Invalid request.
toastError(this, exception);
} else {
// Error.
toastError(this, exception);
}
}
}
private void onCompleteTokenExchange(int resultCode, Intent data) {
AccessTokenResponse tokenResponse = FoursquareOAuth.getTokenFromResult(resultCode, data);
Exception exception = tokenResponse.getException();
if (exception == null) {
String accessToken = tokenResponse.getAccessToken();
// Success.
toastMessage(this, "Access token: " + accessToken);
// Persist the token for later use. In this example, we save
// it to shared prefs.
ExampleTokenStore.get().setToken(accessToken);
// Refresh UI.
ensureUi();
} else {
if (exception instanceof FoursquareOAuthException) {
// OAuth error.
String errorMessage = ((FoursquareOAuthException) exception).getMessage();
String errorCode = ((FoursquareOAuthException) exception).getErrorCode();
toastMessage(this, errorMessage + " [" + errorCode + "]");
} else {
// Other exception type.
toastError(this, exception);
}
}
}
/**
* Exchange a code for an OAuth Token. Note that we do not recommend you
* do this in your app, rather do the exchange on your server. Added here
* for demo purposes.
*
* #param code
* The auth code returned from the native auth flow.
*/
private void performTokenExchange(String code) {
Intent intent = FoursquareOAuth.getTokenExchangeIntent(this, CLIENT_ID, CLIENT_SECRET, code);
startActivityForResult(intent, REQUEST_CODE_FSQ_TOKEN_EXCHANGE);
}
public static void toastMessage(Context context, String message) {
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
}
public static void toastError(Context context, Throwable t) {
Toast.makeText(context, t.getMessage(), Toast.LENGTH_SHORT).show();
}
Error Log
Here is the exception i am getting, can someone please point out why is it not able to find the activity to handle intent? Thank you
08-13 23:15:23.137 2754-2754/com.example.panaceatechnologysolutions.farhansfoursquareapp E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.example.panaceatechnologysolutions.farhansfoursquareapp, PID: 2754
android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.VIEW dat=market://details?id=com.example.panaceatechnologysolutions.farhansfoursquareapp&referrer=utm_source=foursquare-android-oauth&utm_term=CLIENT_ID }
at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:1691)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:1482)
at android.app.Activity.startActivityForResult(Activity.java:3711)
at android.app.Activity.startActivityForResult(Activity.java:3669)
at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:840)
at android.app.Activity.startActivity(Activity.java:3914)
at android.app.Activity.startActivity(Activity.java:3882)
at com.example.panaceatechnologysolutions.farhansfoursquareapp.MyActivity$1.onClick(MyActivity.java:90)
at android.view.View.performClick(View.java:4598)
at android.view.View$PerformClick.run(View.java:19268)
at android.os.Handler.handleCallback(Handler.java:738)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5070)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:836)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:631)
08-13 23:15:30.157 2754-2765/com.example.panaceatechnologysolutions.farhansfoursquareapp I/art﹕ Heap transition to ProcessStateJankImperceptible took 7.253732ms saved at least 72KB
Ok so based on Rohans reply I checked, since I was doing this on the Emulator, this snippet from the Foursquare oAuth library I have in my project cannot create the intent based on the context and client Id. I am not sure why it returns null and as a result redirects me to the Google play store to install foursquare on my emulator. I have registered my app with foursquare and am using the registered client Id and the rest of the parameters used by this function are the ones in Foursquare oAuth Java class. If someone has worked with this library or can point out why it can't find the intent please let me know as I have been stuck on this for a couple of days.
This is the line of code like Rohan pointed out calling the Foursquare oAuth Java class in MyActivity class
Intent intent = FoursquareOAuth.getConnectIntent(MyActivity.this, CLIENT_ID);
And this is the getConnectIntent method in the Foursquare oAuth Java Class
public static Intent getConnectIntent(Context context, String clientId) {
Uri.Builder builder = new Uri.Builder();
builder.scheme(URI_SCHEME);
builder.authority(URI_AUTHORITY);
builder.appendQueryParameter(PARAM_CLIENT_ID, clientId);
builder.appendQueryParameter(PARAM_VERSION, String.valueOf(LIB_VERSION));
builder.appendQueryParameter(PARAM_SIGNATURE, getSignatureFingerprint(context));
Intent intent = new Intent(Intent.ACTION_VIEW, builder.build());
if (isIntentAvailable(context, intent)) {
return intent;
}
return getPlayStoreIntent(clientId);
}
it redirects you to play store becuase "isIntentAvailable is false" and it calls "getPlayStoreIntent" which redirects you to play store.
inside isIntentAvailable method
private static boolean isIntentAvailable(Context context, Intent intent) {
PackageManager packageManager = context.getPackageManager();
List<ResolveInfo> resolveInfo = packageManager.queryIntentActivities(
intent, PackageManager.MATCH_DEFAULT_ONLY);
return resolveInfo.size() > 0;
}
this method return true if a suitable package is found.
also check your client id is not null and is correct
Yes Rohan...you are right it is false because the intent wasnt returning anything from isIntentAvailable, but the real reason why that was not returning an intent back was because since I am using the emulator, the package manager is apparently looking for a foursquare.apk package installed which it didnt find. I didnt Foursquare anywhere indicate that their apk has to be installed which is not included as part of the oAuth Library which they provide in the link above on the sample project. I guess they assume you are using an Android device for testing and not the emulator. These are the steps to use oAuth from Foursquare on Android emulator from Android studio or Eclipse im guessing as well.
1) Download the Foursquare APK http://www.apk4fun.com/apk/6395/
2) As a pre-requisite open Android SDK Manager in Android studio and make sure Google API's are downloaded and installed, these are needed by Foursquare
3) copy the foursquare.apk file in the /Applications/sdk/platform-tools folder
4) install the apk using the adb tool in the folder like shown in this link How to install an apk on the emulator in Android Studio?
5) and now your app can use the emulator to contact foursquare and you will not be redirected to install the app on the emulator!
-Note, I noticed I had to reinstall the "foursquare.apk" when i closed down Android studio and the emulator the next day. But was easy since i knew what to do, Hopefully this saves someone else the frustration as it took me a couple of days to figure this out :)
Related
To display sensible data users can enable authentication in my app. I am using the android in-build authentication.
However, if the user did not secure his device using any pattern, pin, password or biometric authentication, I would like to open the android settings, where he can setup his authentication. Is there any Intent/ way to go there? I did not find it.
Some code so far:
To determine, if the user did not setup any authentication method:
androidx.biometric.BiometricPrompt biometricPrompt = new BiometricPrompt((FragmentActivity) activity, executor, new BiometricPrompt.AuthenticationCallback() {
#Override
public void onAuthenticationError(int errorCode, #NonNull CharSequence errString) {
super.onAuthenticationError(errorCode, errString);
// Determine, if the user has no device password set.
boolean errorCodeIsBeingHandledSeparately = false;
// HERE WE DETERMINE THAT CREDENTIALS HAVE NOT BEEN SETUP
if (errorCode == BiometricPrompt.ERROR_NO_DEVICE_CREDENTIAL) {
if (authenticationInterface != null) {
errorCodeIsBeingHandledSeparately = true;
authenticationInterface.onUserHasNoDevicePassWordSet();
}
}
// Display error message, only if the error code is not being handled seperately.
if (!errorCodeIsBeingHandledSeparately) {
Toast.makeText(activity, "Authentication error\n" + errString, Toast.LENGTH_LONG).show();
}
}
#Override
public void onAuthenticationSucceeded(#NonNull BiometricPrompt.AuthenticationResult result) {
super.onAuthenticationSucceeded(result);
if (authenticationInterface == null) {
Toast.makeText(activity, "Success", Toast.LENGTH_LONG).show();
}
else {
authenticationInterface.onUserSuccessfullyAuthenticated();
}
}
#Override
public void onAuthenticationFailed() {
super.onAuthenticationFailed();
Toast.makeText(activity, "Authentication failed", Toast.LENGTH_LONG).show();
}
});
The interface to receive authentication return.
/**
* Interface to receive authentication return.
*/
private AuthenticationUtils.AuthenticationInterface authenticationInterface;
public interface AuthenticationInterface {
public void onUserSuccessfullyAuthenticated();
public void onUserHasNoDevicePassWordSet();
}
The dialog where I want to lead the user to go to the device setup credentials.
public void displayNoDeviceCredentialsSetDialog() {
MaterialAlertDialogBuilder noDeviceCredentialsDialog = new MaterialAlertDialogBuilder(activity, R.style.AlertDialogTheme);
String noDeviceCredentials_goToSettings_dialogMessage = activity.getString(R.string.authentication_noDeviceCredentials_goToSettings_dialogMessage);
noDeviceCredentialsDialog.setMessage(noDeviceCredentials_goToSettings_dialogMessage);
noDeviceCredentialsDialog.setPositiveButton(
R.string.DialogConfirmationOK,
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// HERE I WOULD LIKE TO OPEN THE ANDROID SETTING WHERE HE CAN SETUP HIS CREDENTIALS
}
}
);
noDeviceCredentialsDialog.setNegativeButton(
R.string.DialogConfirmationNegativeAnswerText,
null
);
noDeviceCredentialsDialog.show();
}
I would like to go here:
You can get there from settings here:
What i am looking for is something like this: Here we navigate the user to some other android settings.
Intent intent2 = new Intent();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
intent2.setAction(android.provider.Settings.ACTION_APPLICATION_SETTINGS);
intent2.putExtra(android.provider.Settings.EXTRA_APP_PACKAGE, getPackageName());
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
intent2.setAction(android.provider.Settings.ACTION_APPLICATION_SETTINGS);
intent2.putExtra("app_package", getPackageName());
intent2.putExtra("app_uid", getApplicationInfo().uid);
} else {
intent2.setAction(android.provider.Settings.ACTION_APPLICATION_SETTINGS);
intent2.addCategory(Intent.CATEGORY_DEFAULT);
intent2.setData(Uri.parse("package:" + getPackageName()));
}
startActivity(intent2);
Just figured it out.
There are 3 viable options to use: Settings.ACTION_BIOMETRIC_ENROLL, Settings.ACTION_FINGERPRINT_ENROLL and Settings.ACTION_SECURITY_SETTINGS.
Final implementation I use is:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
activity.startActivity(new Intent(Settings.ACTION_BIOMETRIC_ENROLL));
}
else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
activity.startActivity(new Intent(Settings.ACTION_FINGERPRINT_ENROLL));
}
else {
activity.startActivity(new Intent(Settings.ACTION_SECURITY_SETTINGS));
}
}
Settings.ACTION_FINGERPRINT_ENROLL opens this: After chosing backup lock screen method and setup the chosen method, the device will ask you to register a fingerprint.
Settings.ACTION_SECURITY_SETTINGS opens this:
In lack of a device higher than Android Build "R" I could not test ACTION_BIOMETRIC_ENROLL, but I presume it will be similar to ACTION_FINGERPRINT_ENROLL.
If you want to see what options there are to open android settings. You can just use "CTRL" + "mouse click" on any Settings.XXX (ACTION_SECURITY_SETTINGS, ACTION_FINGERPRINT_ENROLL, ...) in Android Studio.
You will then see "..\android\platforms\android-31\android.jar!\android\provider\Settings.class"
In case you struggle to figure out which API version is described with "Build.VERSION_CODES.P" you can also click "CTRL" + "Mose Click" on the Build version (P, O, ...).
You will then see this:
I'm trying to implement WeChat InApp payments in our app. But we are struggling to make it work.
I will try to sum it up real quick.
Given user is not logged in, WeChat login screen show up every time.
Given user is logged in, when clicked on pay button for a first time, WeChat order info screen shows up, but when clicked back, and clicked on pay button again (in our app), WeChat screen doesn’t show up.
We did implemented WXPayEntryActivity but neither onCreate, onNewIntent nor onResp are called. And yes, this activity is sending broadcast but neither toast nor log shows up.
I tried call registerApp on application started, I tried it just before creating payment req.
Did anybody come across this issue?
Can WeChat help me directly?
Want to see some code?
This is my payment class
public class WXInAppPayment {
public void startPayment(AppCompatActivity activity, PaymentDataResponse data) {
IWXAPI api = getApi(activity);
if (api.isWXAppInstalled()) {
api.sendReq(getPayRequest(data));
} else {
// Showing toast
}
}
public WXReceiver getReceiver() {
// returning BR for wechat payments
return new WXReceiver();
}
public IntentFilter getIntentFilter() {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Constants.WE_CHAT_BR_ID);
return intentFilter;
}
private IWXAPI getApi(AppCompatActivity activity) {
final IWXAPI api = WXAPIFactory.createWXAPI(activity, null);
api.registerApp(Constants.WE_CHAT_APP_ID);
return api;
}
private PayReq getPayRequest(PaymentDataResponse data) {
PayReq request = new PayReq();
request.appId = dataFromAPI.appId;
request.partnerId = dataFromAPI.partnerId;
request.prepayId = dataFromAPI.prepayId;
request.packageValue = dataFromAPI.packageValue;
request.nonceStr = dataFromAPI.nonceStr;
request.timeStamp = dataFromAPI.timestimeStampamp;
request.sign = dataFromAPI.sign;
return request;
}
}
And this is WXPayEntryActivity. In manifest:
<activity android:name=".wxapi.WXPayEntryActivity"
android:label="#string/app_name"
android:exported="true"/>
And class:
public class WXPayEntryActivity extends Activity implements IWXAPIEventHandler {
private final String TAG = getClass().getSimpleName();
private IWXAPI api;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
api = WXAPIFactory.createWXAPI(this, Constants.WE_CHAT_APP_ID);
api.handleIntent(getIntent(), this);
}
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
api.handleIntent(intent, this);
}
#Override
public void onReq(BaseReq baseReq) {
Log.e(TAG, "onReq: " + baseReq.transaction);
}
#Override
public void onResp(BaseResp baseResp) {
Log.e(TAG, "onResp: " + baseResp.errStr + " " + baseResp.errCode);
Intent intent = new Intent(Constants.WE_CHAT_BR_ID);
intent.putExtra("error_code", baseResp.errCode);
intent.putExtra("error_string", baseResp.errStr);
sendBroadcast(intent);
finish();
}
}
I went through same issue... Your code look fine.
lets cover the scenario:
This is normal ... if user is not logged in.. Wechat App will
redirect to login screen
"Only first time payment passed" happened due to wrong packageName. consider these checks:
You need to use ApplicationId not packageName
WhiteSpace
Debug buildType by default has suffix: .debug to applicatonId
Check AppSign which is MD5 of cert you sign with.. Be careful not to use the default one for debug buildType.
Try to reassign ApplicationId and AppSign it again.(that was our issue 😞) due to hidden WS not visible.
Contact Wechat team support.. they have logs to payment.
Sorry for my poor English and the fact I am a newbie on Android development.
I'm developping an Android app which should send data to the datastore of Dropbox. My problem is, when my code is getting this line:
mAccountManager.startLink(DropboxHelper.this,REQUEST_LINK_TO_DBX);
Then my logcat send me the message below:
10-19 10:40:32.411: W/com.dropbox.client2.android.AuthActivity(28381): There are multiple
apps registered for the AuthActivity URI scheme (db-qeojdcjk0dkkswc). Another app may be
trying to impersonate this app, so authentication will be disabled.
The closer explanation I have found is this one:
Android + DropboxSync startLink
But the comments have not helped me.
Here my code :
public class DropboxHelper extends ActionBarActivity {
// *** Objects and APP_KEY + APP_SECRET are instantiate here ***
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.dropbox_activity);
// Set up the account manager
mAccountManager = DbxAccountManager.getInstance(getApplicationContext(), APP_KEY, APP_SECRET);
mUnlinkButton = (Button) findViewById(R.id.unlink_button);
mUnlinkButton.setVisibility(View.GONE);
// Button to link to Dropbox
mLinkButton = (Button) findViewById(R.id.link_button);
mLinkButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if ( mAccountManager.getLinkedAccount() == null )
mAccountManager.startLink(DropboxHelper.this, REQUEST_LINK_TO_DBX);
else
{
Toast.makeText(DropboxHelper.this, "Connection déjà établie, vous pouvez vous déconnecter si vous le souhaitez", Toast.LENGTH_LONG).show();
mUnlinkButton.setVisibility(View.VISIBLE);
}
}
});
mUnlinkButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
mAccountManager.unlink();
Toast.makeText(DropboxHelper.this, "Déconnecté", Toast.LENGTH_LONG).show();
}
});
// Set up the datastore manager
if (mAccountManager.hasLinkedAccount()) {
try {
// Use Dropbox datastores
mDatastoreManager = DbxDatastoreManager.forAccount(mAccountManager.getLinkedAccount());
mLinkButton.setVisibility(View.GONE);
} catch (DbxException.Unauthorized e) {
System.out.println("Account was unlinked remotely");
}
}
if (mDatastoreManager == null) {
// Account isn't linked yet, use local datastores
mDatastoreManager = DbxDatastoreManager.localManager(mAccountManager);
// Show link button
mLinkButton.setVisibility(View.VISIBLE);
}
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_LINK_TO_DBX) {
if (resultCode == Activity.RESULT_OK) {
account = mAccountManager.getLinkedAccount();
try {
// Migrate any local datastores to the linked account
mDatastoreManager.migrateToAccount(account);
// Now use Dropbox datastores
mDatastoreManager = DbxDatastoreManager.forAccount(account);
// Hide link button
mLinkButton.setVisibility(View.GONE);
} catch (DbxException e) {
e.printStackTrace();
}
} else {
// Link failed or was cancelled by the user
}
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
}
I can't figure out How to solve this issue, I really thank you If you can help me.
Best regards.
This generally means you have more than one app installed using the same app key. Often, this can happen if you have, for example, a sample app from the SDK as well as the app you're developing installed on the same device (or virtual device) using your app key. The solution is just to uninstall one of the apps, or use a different app key in one of them.
I have integrated sdk in my application but when i am going to sharedialog and press back button sdk gives "success" even not post click.
For more details SDK v 3.5 and it's code which given success while i am trying to test using real Facebook account and pressing cancel.but while using test account and when i check with this "getNativeDialogCompletionGesture" method it's working but not in real account.
My requirement is while pressing cancel it should not show success on backpressed.
public static boolean handleActivityResult(Context context, PendingCall appCall, int requestCode, Intent data,
Callback callback) {
if (requestCode != appCall.getRequestCode()) {
return false;
}
if (attachmentStore != null) {
attachmentStore.cleanupAttachmentsForCall(context, appCall.getCallId());
}
if (callback != null) {
if (NativeProtocol.isErrorResult(data)) {
Exception error = NativeProtocol.getErrorFromResult(data);
callback.onError(appCall, error, data.getExtras());
} else {
callback.onComplete(appCall, data.getExtras());
}
}
return true;
}
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);
}