Android Facebook SDK 3.0 auth - android

I'm actually following SessionLoginFragment.java example from facebook sdk samples.
What I really don't understand is this:
when I make
session.openForRead(new Session.OpenRequest(fragment).setCallback(statusCallback));
to log my user to facebook and ask basic read permission (just to test the integration) it simply does not work.
I digged a bit with the debugger and I followed the path. If you don't put a requestCode to the OpenRequest of the session it will give it a random one (and this is ok).
openForRead (my actual session is in CREATED status) will create the permission dialog. When you hit the "Ok" button it will perform a
request.getStartActivityDelegate().startActivityForResult(intent, request.getRequestCode());
You can see the code from the fb sdk source code. Well the requestCode is the same of the session (and here's ok).
When fb log you into the system it will finish his facebook.LoginActivity and call me back my onActivityResult in my activity. The problem is that here the requestCode is different from the request's one. And I don't know why and where it comes from!
If I go into my fb account my application is there, so it means that I've done the correct auth flow that finish well. But I wont get correctly authenticated from my app because of this problem.
Do you know why and how can I solve it?
Thanks.
UPDATE WITH FLOW DETAIL:
This is the actual flow (from fragment):
session.openForRead(new Session.OpenRequest(fragment).setCallback(statusCallback));
After creating it, the request code is (always) 64206
Now openForRead flow will call (final part)
request.getStartActivityDelegate().startActivityForResult(intent, request.getRequestCode());
That call the LoginActivity from facebook SDK and do the client/server validation/oauth
Now on my activity is called onActivityResult (not on the fragment but on the activity part)
and here I call
Session.getActiveSession().onActivityResult(activity, requestCode, resultCode, data);
And here the requestCode is requestCode 129742
How is it possible? As I already said, the problem in all this flow is that requestCode returned to onActivityResult is different from my pendingRequest requestCode and this break (getActiveSession().onActivityResult return without executing code) the login client part.

I ran into the same problem, except that in my case the offending requestCode was 326350 (0x4face). And I was indeed calling super.onActivityResult, so the workaround proposed by Eric Savage was already in place but not effective. Weirdest thing of all, this stuff did work just a couple of weeks ago, and the offending behaviour appeared without myself upgrading anything (Facebook SDK version, Android version, support library version, even the phone on which I'm developing/testing, are all the same as when I had it working).
However, Eric's answer contains other interesting hints, which I exploited to make my code work again. Basically, instead of passing the whole requestCode to Session.onActivityResult, I cut the lowest 16 bits and pass those only.
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Session session = Session.getActiveSession();
int sanitizedRequestCode = requestCode % 0x10000;
session.onActivityResult(this, sanitizedRequestCode, resultCode, data);
}
I do believe this is a bug that should be fixed in the Facebook SDK, and would insist to have it patched for the next release.

Just ran into this same issue. The difference between 64206 (0xface) and 129742 (0x1face) is because FragmentActivity has tacked on an extra 0x10000 to determine which fragment it came from. This was resolved by making sure the super activity was called during onActivityResult
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
// ...
}
}
You "Can only use lower 16 bits for requestCode", as stated in FragmentActivity.startActivityFromFragment

Related

Flutter Google Sign In not returning result if onActivityResult implemented in MainActivity

I currently use google_sign_in plugin to add Google sign in option to my Flutter application.
Everything was working fine until I add onActivityResult() method in my Android MainActivity class.
After debugging native code I found that the result is captured in onActivityResult() method. Hence googleSignIn.signIn() never returns anything.
I don't think how to solve this now. As a temporary solution I'm capturing the result in onActivityResult() and sending it back to flutter using MethodChannel but this is not the right way.
So please let me know if there is a way to figure this out.
Have you checked that you're checking against the request code you submitted and allowing everything else to carry on as normal?
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == MY_REQUEST_CODE) {
// Write your code here.
} else
super.onActivityResult(requestCode, resultCode, data);
}

Android Developer Options causing the app to work improperly

I have created an android app for the Portuguese (Brasil). This is one of my client's app. The client is getting feedback from the app users that they are not able to use the app properly or it goes back to start screen when they click on the button to import a contact from the Phonebook.
i.e. In the app, there are various places where I start the activity to get the result.
startActivityForResult(intent, requestCode);
Generally, I'm doing this from Fragments. And to pass the result from Activity to its Fragment, I'm doing like following:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (getSupportFragmentManager() != null) {
Fragment fragment = getFragment();
if (fragment != null)
fragment.onActivityResult(requestCode, resultCode, data);
}
}
So to check this problem We asked some of the users to check if they have Developer options enabled on their device. And Yes, they have it enabled on their devices. So we asked them to disable this and try the app and believe me it works.
I also have this option enabled on my device to test the app (Debugging) and I haven't faced any problem like this while using the app.
I don't understand this issue and I need to find the appropriate solution.
So I need your help to solve this problem.
Looking for the positive responses.
Thanks.
Try fragment context instead of getActivity() as you are starting activity from the fragment and result should be returnned to fragment.
Intent intent=new Intent(fragment.getContext(), Activity.class)
fragment.startActivityForResult(intent,REQUEST_CODE);
Finally, after a very long time, the issue is resolved.
When we have Don't keep Activities option enabled on the device and as soon as you leave the activity, it gets destroyed.
And in the onCreate, I was adding the initial fragment again.
But now I have added a check of
if(savedInstanceState == null)
// initial fragment here
else
// nothing to do
This check resolved the issue in my app. Hope it helps the others too.

How to distinguish what cancelled Game Services sign in?

Using GameHelper in my game, I paid attention that onActivityResult() if I get Activity.RESULT_CANCELED - the assumption is that user cancelled the sign in. In the other hand, according to Android documentation:
If a child activity fails for any reason (such as crashing), the parent activity will receive a result with the code RESULT_CANCELED.
For me, it seems that in some old devices, I get RESULT_CANCELED as a result of some crash on low connectivity, and it makes me some issues.
The question is - can be RESULT_CANCELED as a result of crash, and if it can, how can i differ between user cancelled and crash?
Thanks in advance
You can use requestCode parameter of onActivityResult method :
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode == GOOGLE_PLUS_LOGIN_REQ) {
// TODO : implement your logic
}
}
You need to learn value of requestCode by trying out sign in cancel scenarios or looking into GameHelper.java source code. After that you can set this value to a static final GOOGLE_PLUS_LOGIN_REQ variable and use as stated above.

finish() on an Activity closes app then briefly shows previous Application

In my App, Activity1 launches Activity2 with "startActivityForResult()".
When Activity2 is done, the following code is called:
Activity2.java
private void finishActivity(final boolean accepted)
{
Intent returnIntent = new Intent();
setResult(accepted ? RESULT_OK : RESULT_CANCELED, returnIntent);
finish();
}
Activity1 receives this callback, and if the result is not RESULT_OK, it also finishes.
Activity1.java
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == Globals.REQUEST_CODE_TOS)
{
if (resultCode != RESULT_OK)
finish();
}
}
After Activity1 finishes the app closes, as expected.
THE PROBLEM --
However, after my app closes, instead of going to the home screen, a previous application on the stack briefly launches forward, then closes also! Then I get to the home screen.
In the Android bug tracker, I see a similar bug listed for the case when the back button is pressed, which I believe is the same as calling finish():
https://code.google.com/p/android/issues/detail?id=71067
I'm seeing this on a Nexus 5, running 4.4.4.
Is this just a bug? Or are there any workarounds for the behavior?
EDIT --
To clarify the behavior I desire:
In Google Maps, if you decline the TOS popup, the app closes and you go directly to the home screen. There is no awkward flash to some previously opened app.
This is decidedly the same issue as the one you linked in your question (I've been following it for months, as I own a Nexus 5 myself). It was actually fixed in the AOSP, but that particular fix doesn't seem to have found its way into the N5 yet. I've got my fingers crossed for a fix in Lollipop, but we'll see when that rolls out.
As for a workaround, I don't think any exists at the moment, although if I'm wrong on that I would love to know - I work on an app myself which does something similar (manually calls finish() the bottom-most activity in the stack when closed via the back button).
Might be the empty Intent you return via setResult(). Have you tried null here, instead?

Get Back Result from Android native Calculator

I'm invoking android native calculator from my app, how do i get result data from it.. means i started native calender like this, after finishing calculation i press back onActivityResult is executed and data returned is null, how to get calculated data.. Help me
Intent i = new Intent();
i.setClassName("com.android.calculator2",
"com.android.calculator2.Calculator");
startActivityForResult(i, 1);
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == 1){
Log.i("CALCULATOR", "Result Data is"+ data);
}
}
After some testing, I'm starting to think that you can't really get something back from the calculator. Calling something with startActivityForResult doesn't mean it's going to return something other than null and since there's no way of getting out of the calculator other than pressing the back key, I think this is one of those cases.
The native calculator doesn't seem to be calling setResult(RESULT_SUCESS,intent_with_data) which is the step needed to be able to retrieve this result. Easiest thing I can think of, since you're wanting to do some calculation is to implement your own calculator class and call that one instead of the native one.
Calculators are easy to make and you have a zillion examples on the net. Just make sure you have an OK button that calls setResult(RESULT_SUCESS, intent_with_data) after you put extras to the intent with the result.
Warning
Be aware that you're hardcoding a class name instead of calling an intent by specifying an action and URI. This may call the original calculator on the emulator and standard versions of Android, but manufacturers change those kinds of things and since no one is supposed to be calling them like you intend to with your intent, you may end up crashing the app.

Categories

Resources