Updating Facebook from Android - java

I have the below script running and it works perfectly. What I am wondering is. Why does facebook give me a secret key if I dont have to implement it as I have not below.
Facebook facebook = new Facebook("APP_ID"); // Application ID of your app at facebook
boolean isLoggedIn = false;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//Implementing SSO
facebook.authorize(this, new String[]{"publish_stream"}, new DialogListener(){
#Override
public void onComplete(Bundle values) {
//control comes here if the login was successful
// Facebook.TOKEN is the key by which the value of access token is stored in the Bundle called 'values'
Log.d("COMPLETE","AUTH COMPLETE. VALUES: "+values.size());
Log.d("AUTH TOKEN","== "+values.getString(Facebook.TOKEN));
updateStatus(values.getString(Facebook.TOKEN));
}
#Override
public void onFacebookError(FacebookError e) {
Log.d("FACEBOOK ERROR","FB ERROR. MSG: "+e.getMessage()+", CAUSE: "+e.getCause());
}
#Override
public void onError(DialogError e) {
Log.e("ERROR","AUTH ERROR. MSG: "+e.getMessage()+", CAUSE: "+e.getCause());
}
#Override
public void onCancel() {
Log.d("CANCELLED","AUTH CANCELLED");
}
});
}
//updating Status
public void updateStatus(String accessToken){
try {
Bundle bundle = new Bundle();
bundle.putString("message", "test update"); //'message' tells facebook that you're updating your status
bundle.putString(Facebook.TOKEN,accessToken);
//tells facebook that you're performing this action on the authenticated users wall, thus
// it becomes an update. POST tells that the method being used is POST
String response = facebook.request("me/feed",bundle,"POST");
Log.d("UPDATE RESPONSE",""+response);
} catch (MalformedURLException e) {
Log.e("MALFORMED URL",""+e.getMessage());
} catch (IOException e) {
Log.e("IOEX",""+e.getMessage());
}
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.d("onActivityResult","onActivityResult");
facebook.authorizeCallback(requestCode, resultCode, data);
}

The most likely reason is that you had already logged on for this app, or had previously logged on with the Facebook app, as a result of which Facebook had allocated you an access token - which is then valid until the app explicitly signs off, or the user disables app access (in the Facebook server-side user profile).
So when you do the authorize, the underlying Facebook SDK simply retrieves the access token, and you do not need to login.
You can disable the access token by going to Facebook for your user and doing Account settings (drop down at top right), then Apps (at left) and disabling your app's access. At which point, when you next run your app, the user will have to log in to Facebook and authorize your app.

Related

Unexpected call to LoginManager.onActivityResult Facebook SDK v3.2

I am integrating the Facebook Login in my Android Application and when I click on the Login button and allow the required permission it gives me
Unexpected call to LoginManager.onActivityResult.
permissions that I am requesting are "public_profile","business_management","read_insights"
I have followed all the instruction as per this question but still facing the same error
Facebook Android SDK v2.3 Unexpected call to LoginManager.onActivityResult
public class FacebookLogIn extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = "FacebookLogIn";
private List<String> permissions = Arrays.asList("public_profile","business_management","read_insights");
private CallbackManager callbackManager;
ViewPager viewPagerFragment;
SplashViewPagerAdapter viewPagerAdapter;
Button btnLogin;
FrameLayout frameLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_log_in);
viewInIt();
viewPagerSetUp();
doAuth();
//automatically logIn if access Token available and not expired else perform doAuth().
AccessToken accessToken = MyTokens.getAccessToken();
boolean isLoggedIn = accessToken != null && !accessToken.isExpired() && accessToken.getPermissions().contains("read_insights") && accessToken.getPermissions().contains("business_management");
if (isLoggedIn){
//if access token not expired and permission granted then start AppSelection Activity
startActivity(new Intent(FacebookLogIn.this, AppSelection.class));
//and close the current activity
finish();
}
}
private void viewInIt(){
btnLogin=findViewById(R.id.btnFbLogin);
btnLogin.setOnClickListener(this);
}
/*
--------------------------------------Login button------------------------------------------------------
*/
#Override
public void onClick(View v) {
LoginManager.getInstance().logInWithReadPermissions(this, permissions);
}
private void doAuth() {
//callbackManager for facebook logIn
callbackManager = CallbackManager.Factory.create();
LoginManager.getInstance().registerCallback(callbackManager, new FacebookCallback<LoginResult>() {
#Override
public void onSuccess(LoginResult loginResult) {
//start AppSelection Activity
startActivity(new Intent(FacebookLogIn.this,AppSelection.class));
//and close the current activity
finish();
}
#Override
public void onCancel() {
}
#Override
public void onError(FacebookException exception) {
exception.printStackTrace();
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
callbackManager.onActivityResult(requestCode, resultCode, data);
}
I am getting this error code when press the Login button allow the permission
W/System.err: Unexpected call to LoginManager.onActivityResult
W/System.err: at com.facebook.login.LoginManager.onActivityResult(LoginManager.java:232)
at com.facebook.login.LoginManager$1.onActivityResult(LoginManager.java:174)
W/System.err: at com.facebook.internal.CallbackManagerImpl.onActivityResult(CallbackManagerImpl.java:91)
at com.greenlab.audiencenetwork.FacebookLogIn.onActivityResult(FacebookLogIn.java:110)
at android.app.Activity.dispatchActivityResult(Activity.java:7121)
at android.app.ActivityThread.deliverResults(ActivityThread.java:4175)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:4222)
at android.app.ActivityThread.-wrap20(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1581)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:163)
at android.app.ActivityThread.main(ActivityThread.java:6238)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:933)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823)
I had the same error, and did a lot til it worked, however I might not be able to say specifically what fixed it, but its probably not code. My best guess is you need to Verify your Dev Account as Individual or Business Account
https://developers.facebook.com/docs/development/release/individual-verification
As written, the changes take effect immediatetely, so when I got the email that my account was verified successfully, I went to my app, tried the oAuth, it worked.
I'll point out other things I did:
Change public_profile permissions to Advanced
Change email permissions to Advanced
Added all the SHA1 fingerprints used in firebase to facebook dev, after Hex to Base 64, https://base64.guru/converter/encode/hex
Added facebook app id in the manifest, since firebase had its own facebook app id, I used tools:replace="android:value" on that meta data
So whether its all of them or one of them, I encourage you to check the list.

GoogleApiClient onConnected callback doesn't get called correctly

I'm trying to use the DriveApi in order to create some folders and upload a text file with some data for a user.
I've tried implementing the quick-start guide from (link), but it has a few fundamental issues:
The api gets connected at onResume so the user will get prompted to give access to the app immediately after he opens the app which is confusing and scary.
If you deny or press the back button at the consent screen, the onResume method will get called again and the consent screen will be shown one more time, leading to an infinite loop.
I would rather like to connect the api when the user actually needs to store data so that will make more sense to the user. I tried doing it like this:
ResultCallback<DriveFolder.DriveFolderResult> folderCreatedCallback = new
ResultCallback<DriveFolder.DriveFolderResult>() {
#Override
public void onResult(#NonNull DriveFolder.DriveFolderResult result) {
clearCurrentAction();
if (!result.getStatus().isSuccess()) {
Log.e(TAG, "Error while trying to create the folder");
return;
}
Log.d(TAG, "Created a folder: " + result.getDriveFolder().getDriveId());
}
};
public DriveApiHelper(GoogleApiClient mGoogleApiClient) {
this.mGoogleApiClient = mGoogleApiClient;
}
public void createBackupsFolder() {
currentAction = DriveActions.CREATING_FOLDER;
if (mGoogleApiClient.isConnected()) {
MetadataChangeSet changeSet = new MetadataChangeSet.Builder()
.setTitle("test").build();
Drive.DriveApi.getRootFolder(mGoogleApiClient).createFolder(
mGoogleApiClient, changeSet).setResultCallback(folderCreatedCallback);
} else {
mGoogleApiClient.connect();
}
}
and this is how my onResume and onConnected methods look like:
#Override
protected void onResume() {
super.onResume();
if (mGoogleApiClient == null) {
// Create the API client and bind it to an instance variable.
// We use this instance as the callback for connection and connection
// failures.
// Since no account name is passed, the user is prompted to choose.
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Drive.API)
.addScope(Drive.SCOPE_FILE)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
mDriveHelper = new DriveApiHelper(mGoogleApiClient);
}
//Log.d(TAG, mDriveHelper.getCurrentAction() + "");
Log.d("test", "Connected " + mGoogleApiClient.isConnected());
}
#Override
public void onConnected(Bundle connectionHint) {
Log.i(TAG, "API client connected.");
switch (mDriveHelper.getCurrentAction()) { //resume the last action
case CREATING_FOLDER:
mDriveHelper.createBackupsFolder();
break;
}
}
I was hoping that keeping a reference of what the user tried to do when the api was asked to connect, I can resume that action after the api successfully connected. This is the closest implementation I've got to fit my needs, but after actually clicking the 'Allow' button from the consent screen none of the api callbacks gets called (onConnected, onConnectionFailed).
I actually need to call the connect method one more time in order to get connected and also fire the onConnected successfully resuming the users' action.
Turns out that I forgot about overriding onActivityResult (it wasn't mentioned in the documentation at that time and I don't know if they included it now)
Just add:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
if (requestCode == REQUEST_CODE_RESOLUTION) {
mGoogleApiClient.connect();
}
} else {
if (requestCode == REQUEST_CODE_RESOLUTION) {
mDriveHelper.dismissStatusDialog();
}
}
}

Google+ sign in for android not working, error code 4

I have followed the guide on how to setup google+ sign in. I did every step and basically copy and pasted the code.
Here is the scenario. I develop on two different computers. I have two different client-ids in my console. One for computer A and one for computer B.
When i install the application and launch it, it will attempt to sign in and fail with the following error from logcat. If i back out of the app and re-launch, it will then sign in fine. When it fails, it will seem to be trying to launch an Activity but the Activity is never launched. Here is the logcat.
06-04 10:14:57.801 19948-19948/carbon.android.game.legions D/AccountFragment﹕ ResolveSignInError ErrorCode:4
06-04 10:14:57.801 602-823/? I/ActivityManager﹕ START u0 {cmp=com.google.android.gms/.plus.activity.AccountSignUpActivity (has extras)} from pid -1
06-04 10:14:57.811 178-646/? D/audio_hw_primary﹕ select_devices: out_snd_device(2: speaker) in_snd_device(0: )
06-04 10:14:57.811 178-646/? D/ACDB-LOADER﹕ ACDB -> send_afe_cal
06-04 10:14:57.821 602-2816/? I/ActivityManager﹕ START u0 {act=com.google.android.gms.common.account.CHOOSE_ACCOUNT pkg=com.google.android.gms cmp=com.google.android.gms/.common.account.AccountPickerActivity (has extras)} from pid 20027
06-04 10:14:57.941 20027-20031/? D/dalvikvm﹕ GC_CONCURRENT freed 601K, 7% free 9304K/9940K, paused 2ms+2ms, total 19ms
06-04 10:14:58.071 949-959/? W/GLSUser﹕ GoogleAccountDataService.getToken()
What am i doing wrong? I followed the guide word for word and basically copy and pasted the code. The only difference is that i am inside of a Fragment and not an Activity. But, that shouldn't matter.
Here is the code:
public class AccountFragment extends Fragment implements View.OnClickListener,
ConnectionCallbacks,
OnConnectionFailedListener {
private static final int RC_SIGN_IN = 1524;
private GoogleApiClient googleApiClient;
private boolean intentInProgress;
private boolean signInClicked;
private ConnectionResult connectionResult;
private SignInButton signInButton;
public AccountFragment() {}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.d(TAG, "The connection failed: " + connectionResult.getErrorCode());
if (!this.intentInProgress) {
this.connectionResult = connectionResult;
if (this.signInClicked) {
this.resolveSignInError();
}
}
}
#Override
public void onStart() {
super.onStart();
this.googleApiClient.connect();
}
#Override
public void onStop() {
super.onStop();
if (this.googleApiClient.isConnected()) {
this.googleApiClient.disconnect();
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.googleApiClient = new GoogleApiClient.Builder(this.getActivity())
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(Plus.API)
.addScope(Plus.SCOPE_PLUS_PROFILE)
.build();
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.sign_in_button:
if (!this.googleApiClient.isConnecting() && !this.googleApiClient.isConnected()) {
this.signInClicked = true;
this.resolveSignInError();
} else {
Log.d(TAG, "OnClick else");
}
break;
default:
break;
}
}
#Override
public void onConnected(Bundle bundle) {
this.signInClicked = false;
Person currentPerson = Plus.PeopleApi.getCurrentPerson(this.googleApiClient);
Log.d(TAG, "User connected: " + currentPerson.getDisplayName());
Log.d(TAG, "User id: " + currentPerson.getId());
Toast.makeText(this.getActivity(), "User connected: " + currentPerson.getDisplayName(), Toast.LENGTH_SHORT).show();
}
#Override
public void onConnectionSuspended(int i) {
this.googleApiClient.connect();
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == RC_SIGN_IN) {
if (resultCode != Activity.RESULT_OK) {
this.signInClicked = false;
}
this.intentInProgress = false;
if (!this.googleApiClient.isConnecting()) {
this.googleApiClient.connect();
}
}
}
private void resolveSignInError() {
if (GooglePlayServicesUtil.isGooglePlayServicesAvailable(this.getActivity()) != ConnectionResult.SUCCESS) {
Log.e(TAG, "Google Play Services is not available.");
}
Log.d(TAG, "ResolveSignInError ErrorCode:" + this.connectionResult.getErrorCode());
if (this.connectionResult.hasResolution()) {
this.intentInProgress = true;
try {
this.connectionResult.startResolutionForResult(this.getActivity(), RC_SIGN_IN);
} catch (SendIntentException e) {
e.printStackTrace();
this.intentInProgress = false;
this.googleApiClient.connect();
}
}
}
}
I figured out my issue.
There were a couple of issues.
With all my testing, i have been attempting to sign in the whole time. And was successful sometimes. Somehow, i was remaining authenticated even though my app was not signed in. I added the ability to sign out and revoke access. After revoking access and attempting to sign in again, the Activity would launch to resolve any errors.
I was also having the issue that is being discussed here. My host Activity was consuming my onActivityResult(...) from my connectionResult.startResolutionForResult(...);. So, after some trial and error i finally found a solution to that issue as well. The question linked helped but did not fully solve the issue. Please view my answer to that question for how i solved the problem.
Lesson, make sure that you are signing out and revoking access while testing. If you are having these issues, try revoking access and then signing back in.
In my case i solve my problem by doing following step, its old que but others my also having this problem so
Follow these stem in android development Console
Open the Credentials page.
Click Add credentials > OAuth 2.0 client ID.
Select Android.
and fill the fingerprint and package name .
Click Create.
Then there will be successful sing in from google.
Hope this may solve your problem. !!!
Please msg me if any problem occurs.

Callback for Facebook requestNewPublishPermissions - Android

I'm trying to get publish permissions from my users in my Android app and I'm succeeding but when I get the permission I want a callback to tell me just that. Here is my code:
private void requestPublishPermissions(Session session) {
Log.d("", "Requesting Publish Permissions...");
if (session != null) {
List<String> publishPermissions = Arrays.asList("publish_actions", "publish_stream");
final int REAUTH_ACTIVITY_CODE = 100;
Session.NewPermissionsRequest reauthRequest = new Session.NewPermissionsRequest(this, publishPermissions).setRequestCode(REAUTH_ACTIVITY_CODE);
reauthRequest.setLoginBehavior(SessionLoginBehavior.SUPPRESS_SSO);
session.requestNewPublishPermissions(reauthRequest);
}
}
Does the session.requestNewPublishPermissions(reauthRequest); have a callback or something that tells me that the permission was accepted?
Thanks for any input
I don't know of a callback for that request, but there's an easy way to get your desired result.
Just add a conditional to the onSessionStateChanged() callback. If you check for the permission in that method by using session.getPermissions().contains("xxx"), you should be able to check in there. Any time the session state changes, it'll call that method, and I think that includes updating permissions.
You can manually add callbacks to your FB session.
Session.getActiveSession().addCallback(new StatusCallback() {
#Override
public void call(Session session, SessionState state, Exception exception) {
if (session.getPermissions().contains("publish_actions")) {
//do stuff
}
}
});
Add the StatusCallback to your session.
private Session.StatusCallback statusCallback = new SessionStatusCallback();
private class SessionStatusCallback implements Session.StatusCallback {
#Override
public void call(final Session session, SessionState state, Exception exception) {
if (session.isOpened()) {
switch (state) {
case OPENED_TOKEN_UPDATED:
// Returns here after you request publish permissions
// So call your publishing actions here
break;
}
}
}
}
Implement onActivityResult() which glues things together.
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Session.getActiveSession().onActivityResult(this, requestCode, resultCode, data);
}

Android - Facebook Cancels

Every time I run my app and it tries to connect to facebook it cancels. It is already authroized and I can connect on my normal Facebook app. I have been looking for a solution for about two days now and can't find any. This is really the only problem holding me back from finishing my app... Hopefully I can get some answers.
I am using this Facebook SDK
Here is my facebook authorize code:
public void authFB(){
Log.i("IN","FB - Authorizing");
fb.authorize(this, new String[]{ "publish_stream" }, new DialogListener(){
#Override
public void onComplete(Bundle values) {
SharedPreferences.Editor editor = prefs.edit();
editor.putString("access_token", fb.getAccessToken());
editor.putLong("access_expires", fb.getAccessExpires());
editor.putString("post_id",values.getString("post_id"));
editor.commit();
Log.i("IN","Login Successful");
checkFB();
}
#Override
public void onFacebookError(FacebookError e) {
Log.i("IN","Login UnSuccessful - fb error");
e.printStackTrace();
checkFB();
}
#Override
public void onError(DialogError e) {
Log.i("IN","Login UnSuccessful - error");
e.printStackTrace();
checkFB();
}
#Override
public void onCancel() {
Log.i("IN","Login UnSuccessful - cancel");
checkFB();
}
});
}
Here is my onCreate:
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
prefs = getPreferences(MODE_PRIVATE);
String access_token = prefs.getString("access_token", null);
//String post_id = prefs.getString("post_id",null);
long expires = prefs.getLong("access_expires",0);
if(access_token != null){
fb.setAccessToken(access_token);
}
if(expires != 0){
fb.setAccessExpires(expires);
}
if(!fb.isSessionValid()){
authFB();
}
I have ZERO ideas about what is wrong. I have tried it on two different phones now and this is the debug I get:
03-07 18:18:43.460: INFO/IN(6741): Login UnSuccessful - cancel
That means onCancel is being called.
CONFUSED.
Thanks.
Fixed it myself.
I kept getting this error because I had this in my manifest for my activities:
android:launchMode="singleInstance"
I am posting this because hopefully it will help someone in the future.
The reason why it created an error is because it tried to create a secondInstance (duh) and that isnt allowed.

Categories