I need to connect my Android application with Facebook Analytics, using custom events.
I followed official documentation on https://developers.facebook.com/docs/analytics/
Added facebook SDK into the project:
implementation 'com.facebook.android:facebook-android-sdk:5.15.3'
Generated all the necessary hashes, put everything necessary in the Manifest, all good.
App was built and launched, however, events were never showing up in the Analytics Console.
After hours and hours of debugging, I've found the problem.
Inside Facebook SDK library code, when postRequest to server is created, it has (among others) parameter called "extInfo". This parameter should contain json array with strings, in certain order.
Now, that's how Facebook SDK postRequest looks, when sent from the application:
As you can see, extinfo json array is all contaminated with backslashes. When I replicated this request manually in Postman, server returned error:
"message": "(#100) Field extinfo must be a valid json object with string keys"
So, in Postman, I modified extinfo parameter - cleaned it out of backslashes:
Result from server in this case is: "success": true. Events started appearing inside Analytics Dashboard.
Wonderful. But.
How to send events with the help of Facebook SDK, considering this bug? Is there sdk version where this bug doesn't appear? Is there a way to tune sdk so that it doesn't send extinfo at least?
Any other possible solution, except for sending requests without help of Facebook SDK (that's a whole load to write, besides, if they change request structure, code has to be re-written)?
I haven't found metions of this bug anywhere in the Internet. If there is, please share a link. Thank you.
Edit: tried with implementation 'com.facebook.android:facebook-core:7.1.0' too. No luck.
I've found the solution. In my case, problem was inside the project and had nothing to do with Facebook SDK.
Previous developer created validation for hosts that application can use:
HttpsURLConnection.setDefaultSSLSocketFactory(socketFactory)
val verify = fun(ip: String, _: SSLSession): Boolean {
println(ip)
return ip.contains("crashlytics", true) ||
ip.contains("firebase", true) ||
ip.contains("maps.googleapis.com", true) ||
ip.contains("facebook.com", true)
}
HttpsURLConnection.setDefaultHostnameVerifier(verify)
Once I added facebook.com in the list, error was gone. However, I still don't understand why in the log "extinfo" parameter was generated with backslashes.
Related
For example if I executed code like this:
Firebase.auth.signInWithEmailAndPassword(email, password)
.addOnCompleteListener { task -> signInCompletedTask(task) }
I would like to see what http request (and with what headers) is actually sent to Firebase backend.
What I tried:
To find anything useful in logs, but I didn't see any information about this.
To run application with debugger, but inside FirebaseAuth.class everything went so complicated that I still couldn't figure out where is the actual http request made.
I tried to look for a source code for com.google.firebase.auth.FirebaseAuth.java, I found this https://github.com/firebase/firebase-admin-java/blob/master/src/main/java/com/google/firebase/auth/FirebaseAuth.java but this class seems wrong, it doesn't even have signInWithEmailAndPassword(..) method
In firebase doc I find this link https://firebase.google.com/docs/reference/rest/auth#section-sign-in-email-password, but I'm not sure is this the same thing or not.
So bottom line, how can I debug what data is moving between my android application and Firebase backend?
firebaser here
The source code you looked at is for the Admin SDK for Java backends, which doesn't have a way to sign in, but has lots of other useful calls for administrative/backend functionality.
For the Firebase Authentication Android SDK the code is in this repo firebase-android-sdk, but you'll find that the Authentication SDK is not in there (yet). If I recall correctly it was too entangled with Play to release it.
The Authentication SDK makes calls to the REST API though, and those endpoints are all documented here, like the API to sign in with email+password.
I am trying to get an object from my bucket but I always get the "signature does not match" error. I got my signature generation function from AWS sample code so I am sure that this works. I also tested the upload function and it works. I am only having trouble with the get object function. I spent a huge amount of hours verifying all scenarios/answers in this post but nothing worked. So here I am seeking your help.
Am I missing something in the headers? Here is a sample canonical request that gets created:
GET
/index.html
host:<bucketname>.s3.amazonaws.com
x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
x-amz-date:20211127T120453Z
host;x-amz-content-sha256;x-amz-date
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
EDIT1:
I tried the AWS sample code by compiling it using javac, then ran it, the get object function works fine. But when added into my Android project, it does not work. To make sure that I copy the sample code as is, I generated its jar file and included the resulting jar file in my project. Still, same issue. This is frustrating. Argg!
EDIT2: Minimal reproducible example
Download the sample code from the link above
Add the code into your Android project except for com.amazonaws.services.s3.sample.RunAllSamples class.
Add this call in one of your activities: GetS3ObjectSample.getS3Object(<bucketName>, <regionName>, <awsAccessKey>, <awsSecretKey>);
This is an interesting one, and basically it boils down to the Android implementation of HttpURLConnection:
com.squareup.okhttp.internal.huc.HttpURLConnectionImpl
behaving differently to the JVM provided implementation:
sun.net.www.protocol.http.HttpURLConnection
The relevant difference here, is that around line 323 the Android implementation checks both:
whether the doOutput flag has been set, and
whether the method field is "GET"
If both these are true, it "helpfully" changes the method to "POST", which means the signature, based on the canonical request which includes the request method, is no longer valid. This is why the other samples work without issue; as they are already using a request method besides "GET", it isn't changed.
In the AWS sample code, the doOutput field is set at:
com/amazonaws/services/s3/sample/util/HttpUtils.java:86
so what I would suggest going forward is to use the definition of:
com.amazonaws.services.s3.sample.GetS3ObjectSample.getS3Object(...)
as a guide to how to calculate the required Authorization header, but use your preferred sane HTTP client instead of the:
com.amazonaws.services.s3.sample.util.HttpUtils
class provided with the samples.
I'm making a simple HTTP POST request using Tasker app, it's working fine but somehow it's not sending my arguments. HTTP GET is working fine. What am I doing wrong?
The only thing the server does is JSON stringify all received parameters and return them like: Text: { parameters }
HTTP GET is working:
HTTP POST works, it returns the response "text: {}" but doesn't return any parameter:
Now sometimes it shows "Bad Request Error 400"
I've tested it with another server and this issue persists...
Here's a fiddle to send get and post requests to the same server and both work.
I've exported my task as xml for you to test: You can download it here
Thanks in advance guys!
I have done a little testing with what you have supplied. It appears that your post parameters are making it to the server but %HTTPR is not getting populated. The Tasker documentation says that this variable will be populated if the response is "text-based", but this does not seem to be the case. I may not know what Tasker considers to be "text-based", but I have tried "text/plain" and "text/html" with no luck.
The work-around that I have come up with is to put the response into a file using the "Output File" field of the post task. (Leave "Content Type" blank or this won't work.) You can then read the file into a variable and do what you need to.
This is either a defect in Tasker, incorrect documentation, or just a misunderstanding of what it takes to make it work. This work-around, however, will get you what you need.
Here is a link to a GitHub repository with the updated task export. You may need to change the output file name/location to work with your device.
Update:
Since I posted the above solution, I have run across a Tasker plugin called "RESTask for Tasker". Evidently, Tasker has enough issues with HTML requests that a separate plugin was needed. I have tested this plugin with POST and it does work, so this is another way to go. The plugin is available on the Google Play store.
When i try submit scores from Android Unity game i receive next error:
You are trying to load data from a www stream which had the following error when downloading.
ava.io.FileNotFoundException: https://graph.facebook.com/me/scores
FB.Login("publish_actions", OnLoginComplete);
var query = new Dictionary<string, string>();
query["score"] = "110";
FB.API("/me/scores", Facebook.HttpMethod.POST, delegate(FBResult r) { Debug.Log("!!!! Score submit result: " + r.Text); }, query);
Facebook sdk version 5.1.0
Unity version 4.5.2f1
For posterity, the most common cause of this error is not having your app configured as a "Game" in the app settings on Facebook. OP and I talked elsewhere, earlier, and ruled that out in this case, but for anyone else finding this post via search, make sure you check that.
To clarify, the code starting with "var query" - is it possible that it is running before OnLoginComplete is called? If you've ruled that out, could you verify whether the problem might be with the grant of permissions? An easy way to do that would be to log the value of the access token right when you make the call to FB.API, then copy-paste that into the access token debugging tool at https://developers.facebook.com/tools/debug and verify that it actually has publish_actions. You could also just take that token and use it in curl in verbose mode (curl -kv "https://graph.facebook.com/me/scores?score=110&access_token=TOKEN"), and see if the headers or response body gives any additional clues.
I am working on an application in which I had to make a new project from existing code. The parent project contains Twitter support classes and Twitter is working fine in that application. But in the newly created project, the Twitter throws following error:
oauth.signpost.exception.OAuthNotAuthorizedException: Authorization failed (server replied
with a 401). This can happen if the consumer key was not correct or the signatures did not
match.
This is quite strange for me. Twitter does not work. However if i run the old snippet it works...Why not on the new one? when there is no difference between the Twitter implementation in the both projects. I have verified date/time on the devices..but that is not issue. Any help please..???
With what you have posted it is nearly impossible to help you. i can just provide some help:
First check the keys (secret and id) you got from twitter.
Check your permissions (probably have this right since it is a response from twitter)
Then check if your Auth process is going ok. that is if the Request is signed right,
then check the auth callback, if it was processed correctly (how does your implementation return the oauth token?).