This is my first time using the Android-Facebook SDK. I am trying to post a bitmap but I keep on getting this message:
Warning: Error: com.facebook.FacebookException: Failed to copy image.
I am able to post simple links, but not the ones with photos.
How should I fix this? Also, one thing I noticed is that the StatusCallback.call() is not being called.
public abstract class FacebookReadyBaseActivity extends Activity {
private static final String TAG = "FacebookReadyBaseActivity";
private UiLifecycleHelper uiHelper;
protected PendingAction pendingAction = PendingAction.NONE;
private static final String PERMISSION = "publish_actions";
protected boolean canPresentShareDialogWithPhotos;
private boolean canPresentShareDialog;
private GraphUser user;
private GraphPlace place;
private List<GraphUser> tags;
protected Bitmap pendingBitmap;
protected enum PendingAction {
NONE, POST_PHOTO, POST_STATUS_UPDATE
}
private Session.StatusCallback callback = new Session.StatusCallback() {
#Override
public void call(Session session, SessionState state,
Exception exception) {
onSessionStateChange(session, state, exception);
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
uiHelper = new UiLifecycleHelper(this, callback);
uiHelper.onCreate(savedInstanceState);
canPresentShareDialog = FacebookDialog.canPresentShareDialog(this,
FacebookDialog.ShareDialogFeature.SHARE_DIALOG);
canPresentShareDialogWithPhotos = FacebookDialog.canPresentShareDialog(
this, FacebookDialog.ShareDialogFeature.PHOTOS);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
uiHelper.onActivityResult(requestCode, resultCode, data,
new FacebookDialog.Callback() {
#Override
public void onError(FacebookDialog.PendingCall pendingCall,
Exception error, Bundle data) {
Log.e(TAG, String.format("Error: %s", error.toString()));
}
#Override
public void onComplete(
FacebookDialog.PendingCall pendingCall, Bundle data) {
Log.i(TAG, "Success!");
}
});
}
#Override
protected void onResume() {
super.onResume();
uiHelper.onResume();
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
uiHelper.onSaveInstanceState(outState);
}
#Override
public void onPause() {
super.onPause();
uiHelper.onPause();
}
#Override
public void onDestroy() {
super.onDestroy();
uiHelper.onDestroy();
}
protected UiLifecycleHelper getFacebookUiHelper() {
return uiHelper;
}
protected void performPublish(PendingAction action, boolean allowNoSession) {
Session session = Session.getActiveSession();
if (session != null) {
pendingAction = action;
if (hasPublishPermission()) {
// We can do the action right away.
handlePendingAction();
return;
} else if (session.isOpened()) {
// We need to get new permissions, then complete the action when
// we get called back.
session.requestNewPublishPermissions(new Session.NewPermissionsRequest(
this, PERMISSION));
return;
}
}
if (allowNoSession) {
pendingAction = action;
handlePendingAction();
}
}
private boolean hasPublishPermission() {
Session session = Session.getActiveSession();
return session != null
&& session.getPermissions().contains("publish_actions");
}
#SuppressWarnings("incomplete-switch")
private void handlePendingAction() {
PendingAction previouslyPendingAction = pendingAction;
// These actions may re-set pendingAction if they are still pending, but
// we assume they
// will succeed.
pendingAction = PendingAction.NONE;
switch (previouslyPendingAction) {
case POST_PHOTO:
postPhoto();
break;
case POST_STATUS_UPDATE:
postStatusUpdate();
break;
}
}
private void postPhoto() {
if (canPresentShareDialogWithPhotos) {
FacebookDialog shareDialog = createShareDialogBuilderForPhoto(
pendingBitmap).build();
uiHelper.trackPendingDialogCall(shareDialog.present());
} else if (hasPublishPermission()) {
Request request = Request.newUploadPhotoRequest(
Session.getActiveSession(), pendingBitmap,
new Request.Callback() {
#Override
public void onCompleted(Response response) {
InfoDialog.newInstance(
FacebookReadyBaseActivity.this, "Done",
"Photo share finished.", null).show();
}
});
request.executeAsync();
} else {
pendingAction = PendingAction.POST_PHOTO;
}
}
private void postStatusUpdate() {
if (canPresentShareDialog) {
FacebookDialog shareDialog = createShareDialogBuilderForLink()
.build();
uiHelper.trackPendingDialogCall(shareDialog.present());
} else if (user != null && hasPublishPermission()) {
// TODO fixme
final String message = "Status update finished.";
Request request = Request.newStatusUpdateRequest(
Session.getActiveSession(), message, place, tags,
new Request.Callback() {
#Override
public void onCompleted(Response response) {
InfoDialog.newInstance(
FacebookReadyBaseActivity.this, "Done",
message, null).show();
}
});
request.executeAsync();
} else {
pendingAction = PendingAction.POST_STATUS_UPDATE;
}
}
private FacebookDialog.PhotoShareDialogBuilder createShareDialogBuilderForPhoto(
Bitmap... photos) {
return new FacebookDialog.PhotoShareDialogBuilder(this)
.addPhotos(Arrays.asList(photos));
}
private FacebookDialog.ShareDialogBuilder createShareDialogBuilderForLink() {
return new FacebookDialog.ShareDialogBuilder(this)
.setName("Hello Facebook")
.setDescription(
"The 'Hello Facebook' sample application showcases simple Facebook integration")
.setLink("http://developers.facebook.com/android");
}
private void onSessionStateChange(Session session, SessionState state,
Exception exception) {
if (pendingAction != PendingAction.NONE
&& (exception instanceof FacebookOperationCanceledException || exception instanceof FacebookAuthorizationException)) {
InfoDialog.newInstance(FacebookReadyBaseActivity.this, "Failed",
"Not granted.", null).show();
pendingAction = PendingAction.NONE;
} else if (state == SessionState.OPENED_TOKEN_UPDATED) {
handlePendingAction();
}
}
}
Finally got it to work!
In the provided HelloFacebookSample project I saw this in the manifest:
<provider android:authorities="com.facebook.app.NativeAppCallContentProvider355198514515820"
android:name="com.facebook.NativeAppCallContentProvider"
android:exported="true"/>
I simply changed the number part using my own Facebook application ID. Not sure why I didn't see this in the documentation.
EDIT
Found this afterwards: https://developers.facebook.com/docs/reference/android/current/class/NativeAppCallContentProvider/
Related
Working on Facebook for android application. Unable to get publish permission.
When i request for permission it get added to decline permissions. Any suggestions.
public class MainActivity extends Activity implements OnClickListener {
private static final String PERMISSION_PUBLISH = "publish_actions";
private TextView textView;
private Button check;
private Button ask;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
textView = (TextView) findViewById(R.id.textView1);
check = (Button) findViewById(R.id.check_per);
ask = (Button) findViewById(R.id.get_per);
check.setOnClickListener(this);
ask.setOnClickListener(this);
findViewById(R.id.post).setOnClickListener(this);
Session.openActiveSession(this, true, new StatusCallback() {
#Override
public void call(Session session, SessionState state, Exception exception) {
if (session != null && session.isOpened()) {
session.refreshPermissions();
Request.newMeRequest(session, new GraphUserCallback() {
#Override
public void onCompleted(GraphUser user, Response response) {
updateUi(user);
}
}).executeAsync();
}
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Session session = Session.getActiveSession();
if (session != null) {
session.onActivityResult(MainActivity.this, requestCode, resultCode, data);
session.refreshPermissions();
}
super.onActivityResult(requestCode, resultCode, data);
}
private void showToast(String msg) {
Toast.makeText(MainActivity.this, msg, Toast.LENGTH_LONG).show();
}
public void updateUi(GraphUser graphUser) {
textView.setText(graphUser.getFirstName());
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.check_per:
checkForPermission();
break;
case R.id.get_per:
getPermission();
break;
case R.id.post:
post();
break;
default:
break;
}
}
private void checkForPermission() {
Session session = Session.getActiveSession();
if (session != null && session.isOpened()) {
// --- Shows PEMISSION_PUBLISH in declined permission not in
// permission granted
List<String> permissions = session.getDeclinedPermissions();
showToast("size : " + permissions.size());
for (int i = 0; i < session.getDeclinedPermissions().size(); i++) {
showToast("Has permission : " + permissions.get(i));
}
}
}
private void getPermission() {
Session session = Session.getActiveSession();
if (session != null && session.isOpened()) {
NewPermissionsRequest newPermissionsRequest = new Session.NewPermissionsRequest(MainActivity.this, PERMISSION_PUBLISH);
session.requestNewPublishPermissions(newPermissionsRequest);
}
}
private void post() {
Request.newStatusUpdateRequest(Session.getActiveSession(), "Status Update", new Request.Callback() {
#Override
public void onCompleted(Response response) {
if (response != null)
showToast(response.toString());
}
}).executeAsync();
}
}
You should go to app settings on developers.facebook.com to Status&Review tab and send request for Facebook review team, see https://developers.facebook.com/docs/apps/review/ for details.
In my application I am trying to checkin with specific location.
But everytime I have this error
{Response: responseCode: 403, graphObject: null, error: {HttpStatus: 403, errorCode: 200, errorType: OAuthException, errorMessage: (#200) Requires extended permission: publish_actions}, isFromCache:false}
I am do sure that I put publish_actions permission in my permission list.
What I did wrong here? and why I have such of error everytime?
Here is my code:
private Session.StatusCallback statusCallback = new SessionStatusCallback();
private class SessionStatusCallback implements Session.StatusCallback {
#Override
public void call(Session session, SessionState state, Exception exception) {
if (session.isOpened()){
checkIn(session);
PrefsCacheManager.getInstance().putInCashe("accessToken" , session.getAccessToken());
}
}
}
private UiLifecycleHelper uiHelper;
private LocationManager locationManager;
private Location lastKnownLocation;
private UiLifecycleHelper lifecycleHelper;
private Location pickPlaceForLocationWhenSessionOpened = null;
private static final int PLACE_ACTIVITY = 1;
private String mPlaceId;
private static final Location LOCATION = new Location("") {{}};
private Session.StatusCallback callback = new Session.StatusCallback() {
#Override
public void call(Session session, SessionState state,
Exception exception) {
}
};
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
uiHelper = new UiLifecycleHelper(this, callback);
uiHelper.onCreate(savedInstanceState);
lifecycleHelper = new UiLifecycleHelper(this, new Session.StatusCallback() {
#Override
public void call(Session session, SessionState state, Exception exception) {
onSessionStateChanged(session, state, exception);
}
});
lifecycleHelper.onCreate(savedInstanceState);
ensureOpenSession();
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
init();
}
#Override
public void onStart() {
super.onStart();
mTracker.activityStart(this);
}
#Override
public void onStop() {
super.onStop();
mTracker.activityStop(this);
}
private boolean ensureOpenSession() {
if (Session.getActiveSession() == null ||
!Session.getActiveSession().isOpened()) {
Session.openActiveSession(this, true, new Session.StatusCallback() {
#Override
public void call(Session session, SessionState state, Exception exception) {
onSessionStateChanged(session, state, exception);
}
});
return false;
}
return true;
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
uiHelper.onActivityResult(requestCode, resultCode, data, new FacebookDialog.Callback() {
#Override
public void onError(FacebookDialog.PendingCall pendingCall, Exception error, Bundle data) {
Toast.makeText(FacebookCheckIn.this, getString(R.string.fb_share_failed), Toast.LENGTH_LONG).show();
}
#Override
public void onComplete(FacebookDialog.PendingCall pendingCall, Bundle data) {
}
});
lifecycleHelper.onActivityResult(requestCode, resultCode, data);
if (requestCode == PLACE_ACTIVITY && resultCode == Activity.RESULT_OK){
displaySelectedPlace(resultCode);
} else if (requestCode == PLACE_ACTIVITY && resultCode == Activity.RESULT_CANCELED){
finish();
}
}
private void displaySelectedPlace(int resultCode) {
String results = "";
SmartBonusApplication application = (SmartBonusApplication) getApplication();
GraphPlace selection = application.getSelectedPlace();
if (selection != null) {
GraphLocation location = selection.getLocation();
mPlaceId = selection.getId();
checkFacebookSession();
}
}
private void setLocation() {
try {
LOCATION.setLatitude(mBrench.getLat());
LOCATION.setLongitude(mBrench.getLng());
startPickPlaceActivity(LOCATION);
} catch (Exception ex) {
onError(ex);
}
}
private void onError(Exception exception) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Error").setMessage(exception.getMessage()).setPositiveButton("OK", null);
builder.show();
}
private void checkFacebookSession() {
final String[] PERMISSION_ARRAY_READ = {"publish_actions" , "user_checkins"};
final List<String> permissionList = Arrays.asList(PERMISSION_ARRAY_READ);
new Session.NewPermissionsRequest(FacebookCheckIn.this, permissionList);
Session session = Session.getActiveSession();
if (session != null){
if (!session.isOpened() && !session.isClosed()) {
session.openForRead(new Session.OpenRequest(this).setCallback(statusCallback));
}else {
Session.openActiveSession(this, true, statusCallback);
}
} else {
Session.openActiveSession(this, true, statusCallback);
}
}
private void checkIn(final Session pSession) {
Bundle params = new Bundle();
if (pSession.getAccessToken() != null) {
params.putString("place", String.valueOf(mPlaceId));
params.putString("message", mBrench.getCompany() + " " + mBrench.getAddress());
params.putString("coordinates", "{\"longitude\":" + mBrench.getLng() + ",\"latitude\":" + mBrench.getLat() + "}");
Request.Callback callback6 = new Request.Callback() {
public void onCompleted(Response response) {
checkInSuccess();
}
};
Request request6 = new Request(pSession, "me/checkins", params, HttpMethod.POST, callback6);
RequestAsyncTask task6 = new RequestAsyncTask(request6);
task6.execute();
}
}
private void checkInSuccess() {
Intent intent = new Intent(FacebookCheckIn.this, CheckinSuccessActivity.class);
intent.putExtra("branche", mBrench);
intent.putExtra("type", VKONTAKTE);
startActivity(intent);
finish();
overridePendingTransition(0, 0);
}
#Override
public void onBackPressed() {
super.onBackPressed();
finish();
overridePendingTransition(0, 0);
}
private void init() {
mTracker = EasyTracker.getInstance(this);
mBrench = getIntent().getParcelableExtra("branche");
setLocation();
}
private void onSessionStateChanged(Session session, SessionState state, Exception exception) {
if (pickPlaceForLocationWhenSessionOpened != null && state.isOpened()) {
Location location = pickPlaceForLocationWhenSessionOpened;
pickPlaceForLocationWhenSessionOpened = null;
startPickPlaceActivity(location);
}
}
private void startPickPlaceActivity(Location location) {
if (ensureOpenSession()) {
SmartBonusApplication application = (SmartBonusApplication) getApplication();
application.setSelectedPlace(null);
Intent intent = new Intent(this, PickPlaceActivity.class);
PickPlaceActivity.populateParameters(intent, location, null);
startActivityForResult(intent, PLACE_ACTIVITY);
} else {
pickPlaceForLocationWhenSessionOpened = location;
}
}
}
You must have added the permission later. and since the session has already been created it's not asking for the publish_action permission.
So, destroy the session by logging-out of the facebook and then login again; or remove the application from your settings and then try. This way, it will ask for the publishing permission and you'll be able to publish successfully!
Edit:
Publishing with /checkins is now deprecated. Check - /{user-id}/checkins
You have to use the Open Graph now to publish stories with location.
You have to use
POST /{user_id}/feed
as described here: https://developers.facebook.com/docs/graph-api/reference/post#publishing
There you can add the place_id as parameter.
if (state.isOpened()) {
// Request user data and show the results
Request.executeMeRequestAsync(session, new Request.GraphUserCallback() {
#Override
public void onCompleted(GraphUser user, Response response) {
if (user != null) {
// Display the parsed user info
}
}
});
}
I have tried follow the facebook doc to get the user info when at the onSessionStateChange function, the problem is , it is weird that I follow the offical doc and it shows
Request.executeMeRequestAsync is depreciate , so I wonder how to implement get the user info in latest facebook sdk 3.6 ? What I would like to do is get the user info if the user logined. Thanks a lot
Update:
Anyway I would also like to ask whether this way to implement login is correct? There are two place in my app need to login
The first one is inside a fragment
public class Home extends Fragment {
public View rootView;
public ImageView HomeBg;
public ImageView buttonLoginLogout;
public TextView chi;
public TextView eng;
public ColorStateList oldColor;
public SharedPreferences prefs;
public EasyTracker tracker = null;
//Facebook login
private Session.StatusCallback statusCallback = new SessionStatusCallback();
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
tracker = EasyTracker.getInstance(getActivity());
getActivity().getActionBar().hide();
rootView = inflater.inflate(R.layout.home, container, false);
buttonLoginLogout = (ImageView) rootView.findViewById(R.id.home_connectFB);
eng = (TextView) rootView.findViewById(R.id.btn_eng);
chi = (TextView) rootView.findViewById(R.id.btn_chi);
if (Utility.getLocale(getActivity()).equals("TC")) {
chi.setTextColor(getActivity().getResources().getColor(
android.R.color.white));
oldColor = eng.getTextColors();
} else {
eng.setTextColor(getActivity().getResources().getColor(
android.R.color.white));
oldColor = chi.getTextColors();
}
eng.setOnClickListener(setChangeLangListener("EN"));
chi.setOnClickListener(setChangeLangListener("TC"));
//Facebook login
Settings.addLoggingBehavior(LoggingBehavior.INCLUDE_ACCESS_TOKENS);
Session session = Session.getActiveSession();
if (session == null) {
if (savedInstanceState != null) {
session = Session.restoreSession(getActivity(), null, statusCallback, savedInstanceState);
}
if (session == null) {
session = new Session(getActivity());
}
Session.setActiveSession(session);
if (session.getState().equals(SessionState.CREATED_TOKEN_LOADED)) {
session.openForRead(new Session.OpenRequest(this).setCallback(statusCallback));
}
}
updateView();
return rootView;
}
#Override
public void onStart() {
super.onStart();
Session.getActiveSession().addCallback(statusCallback);
tracker.set(Fields.SCREEN_NAME, "Landing Page " + Utility.getLocale(getActivity()));
tracker.send(MapBuilder.createAppView().build());
}
#Override
public void onStop() {
super.onStop();
Session.getActiveSession().removeCallback(statusCallback);
EasyTracker.getInstance(getActivity()).activityStop(getActivity());
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Session.getActiveSession().onActivityResult(getActivity(), requestCode, resultCode, data);
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Session session = Session.getActiveSession();
Session.saveSession(session, outState);
}
private void updateView() {
Session session = Session.getActiveSession();
if (session.isOpened()) {
buttonLoginLogout.setImageResource(R.drawable.landing_btn_take_a_selfie);
buttonLoginLogout.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
((LandingPage)getActivity()).tabHost.setCurrentTab(2);
}
});
} else {
buttonLoginLogout.setImageResource(R.drawable.landing_btn_connect_facebook);
buttonLoginLogout.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) { onClickLogin(); }
});
}
}
private void onClickLogin() {
Session session = Session.getActiveSession();
if (!session.isOpened() && !session.isClosed()) {
session.openForRead(new Session.OpenRequest(this).setCallback(statusCallback));
} else {
Session.openActiveSession(getActivity(), this, true, statusCallback);
}
}
private class SessionStatusCallback implements Session.StatusCallback {
#Override
public void call(Session session, SessionState state, Exception exception) {
updateView();
}
}
public OnClickListener setChangeLangListener(final String lang) {
OnClickListener changeLangListener = new OnClickListener() {
#Override
public void onClick(View arg0) {
Configuration config = new Configuration(getResources().getConfiguration());
if (Utility.getLocale(getActivity()).equals("TC") && lang.equals("EN")) {
tracker.send(MapBuilder.createEvent("menu_click","language", "switchEN", null).build());
config.locale = Locale.ENGLISH;
chi.setTextColor(oldColor);
eng.setTextColor(getActivity().getResources().getColor(
android.R.color.white));
} else if (Utility.getLocale(getActivity()).equals("EN") && lang.equals("TC")) {
tracker.send(MapBuilder.createEvent("menu_click","language", "switchTC", null).build());
config.locale = Locale.TRADITIONAL_CHINESE;
eng.setTextColor(oldColor);
chi.setTextColor(getActivity().getResources().getColor(
android.R.color.white));
}
getResources().updateConfiguration(config,getResources().getDisplayMetrics());
onConfigurationChanged(config);
}
};
return changeLangListener;
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Intent intent = getActivity().getIntent();
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
getActivity().finish();
startActivity(intent);
}
#Override
public void onResume() {
super.onResume();
AppEventsLogger.activateApp(getActivity(),getResources().getString(R.string.app_id));
}
}
The other one is inside another activity
public class SharePicForm extends Activity {
private final String TAG = "SharePicForm";
public ImageView photoArea;
public ImageView sharePhotoBtn;
public EditText shareContent;
public Bitmap mBitmap;
public Context ctx;
public String shareTxt;
public String fileUri;
public static boolean isShowForm = true;
public ProgressDialog pd;
public EasyTracker tracker = null;
//Facebook share
private PendingAction pendingAction = PendingAction.NONE;
private enum PendingAction {
NONE, POST_PHOTO
}
private Session.StatusCallback callback = new Session.StatusCallback() {
#Override
public void call(Session session, SessionState state, Exception exception) {
onSessionStateChange(session, state, exception);
}
};
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
tracker = EasyTracker.getInstance(this);
setContentView(R.layout.share_pic_form);
ctx = this;
Utility.setHeader(this,R.string.selfie_header,false);
Session session = Session.getActiveSession();
if (session == null) {
if (savedInstanceState != null) {
session = Session.restoreSession(this, null, callback, savedInstanceState);
}
if (session == null) {
session = new Session(this);
}
Session.setActiveSession(session);
if (session.getState().equals(SessionState.CREATED_TOKEN_LOADED)) {
session.openForRead(new Session.OpenRequest(this).setCallback(callback));
}
}
photoArea = (ImageView) findViewById(R.id.photo_area);
shareContent = (EditText) findViewById(R.id.share_content);
if (getIntent() != null) {
Intent intent = getIntent();
fileUri = (String) intent.getStringExtra("photo");
} else if (savedInstanceState != null){
mBitmap = (Bitmap) savedInstanceState.getParcelable("bitmap") == null ? null : (Bitmap) savedInstanceState.getParcelable("bitmap");
}
FileInputStream inputStream;
try {
File imgSelected = new File(fileUri);
if (imgSelected.exists()) {
inputStream = new FileInputStream(imgSelected);
mBitmap = Utility.decodeBitmap(inputStream, 1280, 960);
photoArea.setImageBitmap(mBitmap);
sharePhotoBtn = (ImageView) findViewById(R.id.share_submit);
sharePhotoBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (mBitmap != null && FormValidation.hasText(shareContent)) {
try {
File imageToShare = saveBitmapToStorage();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
shareTxt = shareContent.getText().toString();
performPublish(PendingAction.POST_PHOTO);
//new FormSubmit(ctx,easyTracker).execute("shareImg",imageToShare, textToShare);
}
}
});
} else {
Toast.makeText(ctx, ctx.getResources().getString(R.string.get_photo_error), Toast.LENGTH_SHORT).show();
finish();
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private File saveBitmapToStorage () throws IOException{
String path = Environment.getExternalStorageDirectory().toString();
File outputFile = new File(path, "temp.jpg");
FileOutputStream out = new FileOutputStream(outputFile);
mBitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
return outputFile;
}
//Facebook share
private void onSessionStateChange(Session session, SessionState state, Exception exception) {
if (pendingAction != PendingAction.NONE &&
(exception instanceof FacebookOperationCanceledException ||
exception instanceof FacebookAuthorizationException)) {
new AlertDialog.Builder(SharePicForm.this)
.setTitle(ctx.getResources().getString(R.string.error))
.setMessage(ctx.getResources().getString(R.string.get_permission_error))
.setPositiveButton(ctx.getResources().getString(R.string.close), null)
.show();
pendingAction = PendingAction.NONE;
} else if (state == SessionState.OPENED_TOKEN_UPDATED) {
handlePendingAction();
}
}
private boolean hasPublishPermission() {
Session session = Session.getActiveSession();
return session != null && session.getPermissions().contains("publish_actions");
}
private void handlePendingAction() {
PendingAction previouslyPendingAction = pendingAction;
// These actions may re-set pendingAction if they are still pending, but we assume they will succeed.
pendingAction = PendingAction.NONE;
if (previouslyPendingAction == PendingAction.POST_PHOTO)
postPhoto();
}
private void performPublish(PendingAction action) {
Log.d(TAG,"Perform publish");
Session session = Session.getActiveSession();
if (session != null) {
Log.d(TAG,"Session != null");
pendingAction = action;
if (hasPublishPermission()) {
Log.d(TAG,"Has permission");
// We can do the action right away.
handlePendingAction();
return;
} else if (session.isOpened()) {
Log.d(TAG,"Open session");
// We need to get new permissions, then complete the action when we get called back.
session.requestNewPublishPermissions(new Session.NewPermissionsRequest(this, "publish_actions"));
return;
} else {
onClickLogin();
}
} else{
Log.d(TAG,"Session == null");
}
}
private void onClickLogin() {
Session session = Session.getActiveSession();
if (!session.isOpened() && !session.isClosed()) {
session.openForRead(new Session.OpenRequest(this).setCallback(callback));
} else {
Session.openActiveSession(this, true, callback);
}
}
private void postPhoto() {
Log.d(TAG,"postPhoto: " + hasPublishPermission());
if (hasPublishPermission()) {
if (mBitmap != null) {
Request request = Request.newUploadPhotoRequest(
Session.getActiveSession(),mBitmap, new Request.Callback() {
#Override
public void onCompleted(Response response) {
pd.dismiss();
if (response.getError() == null) {
Utility.showDialog(ctx,"success_photo",tracker);
} else {
Log.d(TAG,response.getError().getErrorMessage());
Toast.makeText(ctx, response.getError().getErrorMessage(), Toast.LENGTH_LONG).show();
Utility.showDialog(ctx,"error",tracker);
}
}
});
Bundle params = request.getParameters();
if (shareTxt != null)
params.putString("message", shareTxt);
request.setParameters(params);
request.executeAsync();
pd = ProgressDialog.show(ctx, ctx.getResources().getString(R.string.sys_info),ctx.getResources().getString(R.string.publishing));
}
} else {
pendingAction = PendingAction.POST_PHOTO;
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable("bitmap", mBitmap);
Session session = Session.getActiveSession();
Session.saveSession(session, outState);
}
#Override
public void onStart() {
super.onStart();
Session.getActiveSession().addCallback(callback);
EasyTracker.getInstance(this).activityStart(this);
tracker.set(Fields.SCREEN_NAME, "Image_entryForm " + Utility.getLocale(this));
tracker.send(MapBuilder.createAppView().build());
}
#Override
public void onStop() {
super.onStop();
Session.getActiveSession().removeCallback(callback);
EasyTracker.getInstance(this).activityStop(this);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Session.getActiveSession().onActivityResult(this, requestCode, resultCode, data);
}
#Override
public void onResume() {
super.onResume();
AppEventsLogger.activateApp(this,getResources().getString(R.string.app_id));
}
}
Should I implement the get user info code in all activities? thanks
Okay, Use below code.
//Define textview to print detail
TextView mfirstname, mlastname, middlename, mfullname, mbirthdate,
mfacebookLink, mfacebookId, mfacebookUnm, mgender, mEmail;
// Code to retrieve data from FB
Session.openActiveSession(this, true, new Session.StatusCallback() {
// callback when session changes state
#Override
public void call(Session session, SessionState state,
Exception exception) {
if (session.isOpened()) {
// make request to the /me API
Request.executeMeRequestAsync(session,
new Request.GraphUserCallback() {
#Override
public void onCompleted(GraphUser user,
Response response) {
if (user != null) {
mfirstname.setText(user.getFirstName());
mlastname.setText(user.getLastName());
middlename.setText(user.getMiddleName());
mfullname.setText(user.getName());
mbirthdate.setText(user.getBirthday());
mfacebookLink.setText(user.getLink());
mfacebookId.setText(user.getId());
mfacebookUnm.setText(user.getUsername());
String gender = user.asMap()
.get("gender").toString();
String email = user.asMap()
.get("email").toString();
mgender.setText(gender);
mEmail.setText(email);
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
.permitAll().build();
StrictMode.setThreadPolicy(policy);
} else {
Toast.makeText(getApplicationContext(), "Error...",
Toast.LENGTH_LONG);
}
}
});
I'm trying to allow the users of my app to publish stories on their walls from my application for things such as Achievements(for example) within my application. Here is the activity code, adapted from the HelloFacebookActivitySample:
With both activities, I can see my app name, description, and link no problem when I post. Using the latest version of the FB SDK. However, the string (message) that I pass through the newStatusUpdateRequest() method is not displayed.
(In this attempt, I'm trying to pass text from a text view)
The first way I tried it:
public class Settings_Facebook extends FragmentActivity {
//Constants
private static final String PERMISSION = "publish_actions";
private final String PENDING_ACTION_BUNDLE_KEY = "com.facebook.MyApp:PendingAction";
//Views
private Button postStatusUpdateButton;
private Button postPhotoButton;
private LoginButton loginButton;
private ProfilePictureView profilePictureView;
private TextView greeting;
//Variables
private PendingAction pendingAction = PendingAction.NONE;
private ViewGroup controlsContainer;
private GraphUser user;
private GraphPlace place;
private List<GraphUser> tags;
private boolean canPresentShareDialog;
private enum PendingAction {
NONE,
POST_PHOTO,
POST_STATUS_UPDATE
}
private UiLifecycleHelper uiHelper;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
uiHelper = new UiLifecycleHelper(this, callback);
uiHelper.onCreate(savedInstanceState);
if (savedInstanceState != null) {
String name = savedInstanceState.getString(PENDING_ACTION_BUNDLE_KEY);
pendingAction = PendingAction.valueOf(name);
}
setContentView(R.layout.activity_settings__facebook);
loginButton = (LoginButton) findViewById(R.id.login_button);
loginButton.setUserInfoChangedCallback(new LoginButton.UserInfoChangedCallback() {
#Override
public void onUserInfoFetched(GraphUser user) {
Settings_Facebook.this.user = user;
updateUI();
// It's possible that we were waiting for this.user to be populated in order to post a
// status update.
handlePendingAction();
}
});
profilePictureView = (ProfilePictureView) findViewById(R.id.profilePicture);
greeting = (TextView) findViewById(R.id.greeting);
postStatusUpdateButton = (Button) findViewById(R.id.postStatusUpdateButton);
postStatusUpdateButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
onClickPostStatusUpdate();
}
});
postPhotoButton = (Button) findViewById(R.id.postPhotoButton);
postPhotoButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
onClickPostPhoto();
}
});
controlsContainer = (ViewGroup) findViewById(R.id.main_ui_container);
canPresentShareDialog = FacebookDialog.canPresentShareDialog(this,
FacebookDialog.ShareDialogFeature.SHARE_DIALOG);
}
private Session.StatusCallback callback = new Session.StatusCallback() {
#Override
public void call(Session session, SessionState state, Exception exception) {
onSessionStateChange(session, state, exception);
}
};
private FacebookDialog.Callback dialogCallback = new FacebookDialog.Callback() {
#Override
public void onError(FacebookDialog.PendingCall pendingCall, Exception error, Bundle data) {
Log.d("HelloFacebook", String.format("Error: %s", error.toString()));
}
#Override
public void onComplete(FacebookDialog.PendingCall pendingCall, Bundle data) {
Log.d("HelloFacebook", "Success!");
}
};
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
uiHelper.onSaveInstanceState(outState);
outState.putString(PENDING_ACTION_BUNDLE_KEY, pendingAction.name());
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
uiHelper.onActivityResult(requestCode, resultCode, data, dialogCallback);
}
private void onSessionStateChange(Session session, SessionState state, Exception exception) {
if (pendingAction != PendingAction.NONE &&
(exception instanceof FacebookOperationCanceledException ||
exception instanceof FacebookAuthorizationException)) {
new AlertDialog.Builder(Settings_Facebook.this)
.setTitle(R.string.cancelled)
.setMessage(R.string.permission_not_granted)
.setPositiveButton(R.string.ok, null)
.show();
pendingAction = PendingAction.NONE;
} else if (state == SessionState.OPENED_TOKEN_UPDATED) {
handlePendingAction();
}
updateUI();
}
private void updateUI() {
Session session = Session.getActiveSession();
boolean enableButtons = (session != null && session.isOpened());
postStatusUpdateButton.setEnabled(enableButtons || canPresentShareDialog);
postPhotoButton.setEnabled(enableButtons);
if (enableButtons && user != null) {
profilePictureView.setProfileId(user.getId());
greeting.setText(getString(R.string.hello_user, user.getFirstName()));
} else {
profilePictureView.setProfileId(null);
greeting.setText(null);
}
}
#SuppressWarnings("incomplete-switch")
private void handlePendingAction() {
PendingAction previouslyPendingAction = pendingAction;
// These actions may re-set pendingAction if they are still pending, but we assume they
// will succeed.
pendingAction = PendingAction.NONE;
switch (previouslyPendingAction) {
case POST_PHOTO:
postPhoto();
break;
case POST_STATUS_UPDATE:
postStatusUpdate();
break;
}
}
private interface GraphObjectWithId extends GraphObject {
String getId();
}
private void showPublishResult(String message, GraphObject result, FacebookRequestError error) {
String title = null;
String alertMessage = null;
if (error == null) {
title = getString(R.string.success);
String id = result.cast(GraphObjectWithId.class).getId();
alertMessage = getString(R.string.successfully_posted_post, message, id);
} else {
title = getString(R.string.error);
alertMessage = error.getErrorMessage();
}
new AlertDialog.Builder(this)
.setTitle(title)
.setMessage(alertMessage)
.setPositiveButton(R.string.ok, null)
.show();
}
private void onClickPostStatusUpdate() {
performPublish(PendingAction.POST_STATUS_UPDATE, canPresentShareDialog);
}
private FacebookDialog.ShareDialogBuilder createShareDialogBuilder() {
return new FacebookDialog.ShareDialogBuilder(this)
.setName("MyApplication")
.setDescription("The description of the app")
.setLink("https://play.google.com/store/");
}
private void postStatusUpdate() {
final EditText simpleEditText = (EditText) findViewById(R.id.editStatus);
final String message = simpleEditText.getText().toString();
Bundle postParams = new Bundle();
postParams.putString("name", "Facebook SDK for Android");
postParams.putString("caption", "Build great social apps and get more installs.");
postParams.putString("description", "The Facebook SDK for Android makes it easier and faster to develop Facebook integrated Android apps.");
postParams.putString("link", "https://developers.facebook.com/android");
postParams.putString("picture", "https://raw.github.com/fbsamples/ios-3.x-howtos/master/Images/iossdk_logo.png");
if (canPresentShareDialog) {
FacebookDialog shareDialog = createShareDialogBuilder().build();
uiHelper.trackPendingDialogCall(shareDialog.present());
}
else if (user != null && hasPublishPermission()) {
Session session = Session.getActiveSession();
Request request = new Request(session,"me/feed",postParams,HttpMethod.POST);
RequestAsyncTask task = new RequestAsyncTask(request);
task.execute();
// .newStatusUpdateRequest(Session.getActiveSession(), message, place, tags, new Request.Callback() {
// #Override
// public void onCompleted(Response response) {
// showPublishResult(message, response.getGraphObject(), response.getError());
// }
// });
// request.executeAsync();
}
else {
pendingAction = PendingAction.POST_STATUS_UPDATE;
}
}
private void onClickPostPhoto() {
performPublish(PendingAction.POST_PHOTO, false);
}
private void postPhoto() {
if (hasPublishPermission()) {
Bitmap image = BitmapFactory.decodeResource(this.getResources(), R.drawable.button_focus);
Request request = Request.newUploadPhotoRequest(Session.getActiveSession(), image, new Request.Callback() {
#Override
public void onCompleted(Response response) {
showPublishResult(getString(R.string.photo_post), response.getGraphObject(), response.getError());
}
});
request.executeAsync();
} else {
pendingAction = PendingAction.POST_PHOTO;
}
}
private boolean hasPublishPermission() {
Session session = Session.getActiveSession();
return session != null && session.getPermissions().contains("publish_actions");
}
private void performPublish(PendingAction action, boolean allowNoSession) {
Session session = Session.getActiveSession();
if (session != null) {
pendingAction = action;
if (hasPublishPermission()) {
// We can do the action right away.
handlePendingAction();
return;
} else if (session.isOpened()) {
// We need to get new permissions, then complete the action when we get called back.
session.requestNewPublishPermissions(new Session.NewPermissionsRequest(this, PERMISSION));
return;
}
}
if (allowNoSession) {
pendingAction = action;
handlePendingAction();
}
}
#Override
public void onPause() {
super.onPause();
uiHelper.onPause();
}
#Override
public void onDestroy() {
super.onDestroy();
uiHelper.onDestroy();
}
#Override
protected void onResume() {
super.onResume();
uiHelper.onResume();
updateUI();
}
}
(in this attempt I'm passing a bundle of parameters)
The second way I tried it(Just the postStatusUpdate() method was changed):
private void postStatusUpdate() {
final EditText simpleEditText = (EditText) findViewById(R.id.editStatus);
final String message = simpleEditText.getText().toString();
Bundle postParams = new Bundle();
postParams.putString("name", "Facebook SDK for Android");
postParams.putString("caption", "Build great social apps and get more installs.");
postParams.putString("description", "The Facebook SDK for Android makes it easier and faster to develop Facebook integrated Android apps.");
postParams.putString("link", "https://developers.facebook.com/android");
postParams.putString("picture", "https://raw.github.com/fbsamples/ios-3.x-howtos/master/Images/iossdk_logo.png");
if (canPresentShareDialog) {
FacebookDialog shareDialog = createShareDialogBuilder().build();
uiHelper.trackPendingDialogCall(shareDialog.present());
}
else if (user != null && hasPublishPermission()) {
Session session = Session.getActiveSession();
Request request = new Request(session,"me/feed",postParams,HttpMethod.POST);
RequestAsyncTask task = new RequestAsyncTask(request);
task.execute();
}
else {
pendingAction = PendingAction.POST_STATUS_UPDATE;
}
}
For achievements, you can either use the Achievements API or Open Graph Actions/Objects. Since the Achievements are only available for games, Open Graph Actions are the way to go. Here are some links to get you started:
https://developers.facebook.com/docs/opengraph/
https://developers.facebook.com/docs/opengraph/getting-started/
https://developers.facebook.com/docs/opengraph/using-actions/
Keep in mind that it may take some hours or even some days until the Open Graph Actions are accepted by Facebook.
You can also publish Open Graph Actions in the background without user confirmation, as long as the user can change the publishing in a settings dialog, for example.
I set a connection to fb in my app: clicking a button the app does the login, posts on the wall and then does logout. Everything works perfect for me with my developer account, but trying with other phones and other accounts, if official FB app is installed, the app doesn't publish anything. I have just changed key-hash, i didn't use debug.keystore but a new keystore..... Anyone can help me????
Thank you very much!
i followed tutorials from fb, this is my login method
private void onClickLogin() {
Session session = Session.getActiveSession();
login=true;
if (session!=null && !session.isOpened() && !session.isClosed()) {
session.openForPublish(new Session.OpenRequest(this)
.setPermissions(Arrays.asList("publish_actions"))
.setCallback(callback));
} else {
Session.openActiveSession(getActivity(), this, true, callback);
}
}
this is all the "interesting" code
boolean login= false;
private Session.StatusCallback callback = new Session.StatusCallback() {
#Override
public void call(Session session, SessionState state, Exception exception) {
onSessionStateChange(session, state, exception);
}
};
private UiLifecycleHelper uiHelper;
private static final List<String> PERMISSIONS = Arrays.asList("publish_actions");
private static final String PENDING_PUBLISH_KEY = "pendingPublishReauthorization";
private boolean pendingPublishReauthorization = false;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
uiHelper = new UiLifecycleHelper(getActivity(), callback);
uiHelper.onCreate(savedInstanceState);
}
public void setEnt(Entry e) {
art=e;
}
#Override
public void onResume() {
super.onResume();
Session session = Session.getActiveSession();
uiHelper.onResume();
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
uiHelper.onActivityResult(requestCode, resultCode, data);
}
#Override
public void onPause() {
super.onPause();
uiHelper.onPause();
}
#Override
public void onDestroy() {
super.onDestroy();
uiHelper.onDestroy();
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
uiHelper.onSaveInstanceState(outState);
}
private void onClickLogin() {
Session session = Session.getActiveSession();
login=true;
if (session!=null && !session.isOpened() && !session.isClosed()) {
session.openForPublish(new Session.OpenRequest(this)
.setPermissions(Arrays.asList("publish_actions"))
.setCallback(callback));
} else {
Session.openActiveSession(getActivity(), this, true, callback);
}
}
private void onSessionStateChange(Session session, SessionState state, Exception exception) {
if (state.isOpened()) {
publishStory();
} else if (state.isClosed()) {
}
}
private void publishStory() {
Session session = Session.getActiveSession();
if(login){
if (session != null){
Bundle postParams = new Bundle();
postParams.putString("name", art.getTitle());
postParams.putString("caption", art.getSection());
postParams.putString("description", "xxx");
postParams.putString("link", "xxx");
postParams.putString("picture", "xxx");
Request.Callback callback= new Request.Callback() {
public void onCompleted(Response response) {
JSONObject graphResponse = response.getGraphObject().getInnerJSONObject();
String postId = null;
try {
postId = graphResponse.getString("id")+" articolo postato";
} catch (JSONException e) {
Log.i(TAG,
"JSON error "+ e.getMessage());
}
FacebookRequestError error = response.getError();
if (error != null) {
Toast.makeText(getActivity()
.getApplicationContext(),
error.getErrorMessage(),
Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getActivity()
.getApplicationContext(),
postId,
Toast.LENGTH_LONG).show();
logout();
}
}
};
Request request = new Request(session, "me/feed", postParams,
HttpMethod.POST, callback);
RequestAsyncTask task = new RequestAsyncTask(request);
task.execute();
Log.v("FB", "FINE");
}
}
}
private void logout(){
login=false;
if (Session.getActiveSession() != null) {
Session.getActiveSession().closeAndClearTokenInformation();
}
Session.setActiveSession(null);
}
private boolean isSubsetOf(Collection<String> subset, Collection<String> superset) {
for (String string : subset) {
if (!superset.contains(string)) {
return false;
}
}
return true;
}
}
I think that your app may be placed in the sandbox mode and which is what causing others not from accessing your app. You may be the admin of the app and with your account you can access the app even in sandbox mode
So disable it to make your app work for others.
Also check whether you have added the keyhash generated using your keystore file
Turn-off the sandbox mode in your App settings.
Click here to go to your App Dashboard