สร้างปุ่ม Facebook Login บน Android

Published on
Android
2014/04/facebook-sdk-for-android-login-button
Discord

Cover Image : https://developers.facebook.com/docs/android

ปัจจุบันนับว่า Facebook นั้นมีอิทธิพลต่อวงการเว็บ มือถือ และ โซเชียลเนตเวิร์คอย่างมาก แทบทุกเว็บ มักจะเห็นปุ่ม Like ปุ่ม Share หรือปุ่มล็อคอินด้วย Facebook ต่างๆ มากมาย

วันนี้ผมเลยจะมาพูดถึงวิธีการสร้างแอพแอนดรอยส์ให้เชื่อมต่อกับ Facebook เลยครับ จำได้ว่าเคยศึกษาตอนช่วย SDK 2 กว่าๆ ปัจจุบัน SDK 3.8 ซะแล้ว เมธอดต่างๆ หรือฟังค์ชั่นบางอย่าง ก็ถูก deprecated ไปเรียบร้อยแล้ว

ทั้งหมดนี้จะเป็นตัวอย่างขั้นตอนการเขียนแอพพลิเคชันแอนดรอยส์ล็อคอิน Facebook ครับ ขั้นตอนทั้งหมดก็มีดังนี้

Step 1: เตรียมเครื่องมือให้พร้อม

ขั้นตอนแรก คือเครื่องมือและสิ่งต่างๆที่ทุกคนต้องมี

  • ต้องมี Android Studio, Eclipse + Plugin หรือ Android Developer Tool(ADT Bundle) อย่างใดอย่างหนึ่ง
  • ต้องมีแอพ Facebook ก่อน
  • ต้องมี Facebook SDK for Android 3.8
  • ต้องมี Facebook APK สำหรับแอพ Facebook บน Emulator (อันนี้กรณีเทสบน Emulator)

ในส่วน IDE อันนี้ผมจะไม่บอกรายละเอียดการติดตั้งนะครับ คาดว่าทุกคน เมื่อมองหาบทความ Facebook SDK for Android แล้ว คิดว่าทุกคนต้องจับ Android หรือมีพื้นฐานมาบ้างแล้ว หากใครไม่มี หรือยังไม่เคยจับเลย ก็ลองไปอ่านบทความนี้ดูครับ เตรียมเครื่องมือสำหรับเขียนแอพพลิเคชันบนแอนดรอยส์

ส่วนอันที่เหลือ ผมจะค่อยๆ อธิบายไปทีละสเตปแล้วกันครับ

สร้างแอพ Facebook ก่อน

สิ่งแรกคือ จำเป็นต้องสร้างแอพ Facebook ขึ้นมาก่อน หากใครมีแล้ว ก็ข้ามไป ดาวน์โหลด Facebook SDK for Android 3.8

  1. ไปหน้าเว็บ Facebook Developer จากนั้นเลือก Apps -> Create a new App

Create new app

จากนั้นสร้างเสร็จ ก็จะได้หน้าตาประมาณนี้

Created app

  1. เมื่อเรามี App Facebook แล้ว ต่อไป ก็ต้องลงทะเบียนแอพแอนดรอยส์ เพื่อจะใช้เชื่อมต่อกับ Facebook แต่ว่าขั้นตอนนี้เอาไว้แค่นี้ก่อน เพราะว่าเรายังไม่มีตัวแอพแอนดรอยส์เลย ข้ามไปขั้นตอนต่อไปก่อน เดี่ยวจะกลับมาตั้งค่า Facebook App อีกครั้งครับ ตอนนี้จำแค่เลข appId ไว้ก่อนครับ

โหลด Facebook SDK for Android 3.8

ให้ทำการโหลดและติดตั้ง Facebook SDK for Android ก่อน จากนั้นทำการ Extract ไปไว้ Directory ที่ต้องการ

ในบทความนี้ผมจะใช้ ADT Bundle หรือ Eclipse+Plugin หากใครใช้ Android Studio จะบอกวิธีในบทความหน้าแล้วกันครับ

เปิด Eclipse ขึ้นมา คลิ๊กขวา ตรงส่วนว่างๆของ Project Explorer เลือก import จากนั้นเลือก Android -> Existing Android Code into Workspace

import project

Browse ไปที่ตัวที่ดาวน์โหลดมาก่อนหน้า เลือกโฟลเดอร์ facebook-android-sdk-3.8.0/facebook จากนั้นคลิ๊ก Finish หากไม่เลือกโฟลเดอร์ facebook จะได้ library และ source ทั้งหมดครับ ทั้ง Sample โปรเจ็คด้วย หากต้องการก็ import ได้ครับ ไม่มีปัญหา

Import Project2

หากต้องการก็อปโฟลเดอร์ไปที่ workspace ก็ติ๊กถูกตรง Copy projects into workspace ครับ กรณีไม่ก็อปโฟลเดอร์ไป Eclipse จะทำการลิงค์มายังโฟลเดอร์นี้เอง มีประโยชน์เวลา มี Facebook SDK เวอร์ชั่นใหม่ครับ ก็แค่ import ใหม่ จะได้ไม่กระทบกับของเก่า

จะได้ Facebook SDK มีหน้าตาประมาณนี้ Facebook SDK

ติดตั้งแอพ Facebook ลง Emulator

หากใครใช้การ debug กับเครื่องจริง หรือตัว Emulator มีแอพ Facebook อยู่แล้ว ก็ข้ามขั้นตอนนี้ไปได้ครับ

หากไม่ได้ลงแอพ Facebook ที่เครื่อง ก็สามารถใช้ Facebook Platform ได้เหมือนกัน เพียงแต่เวลาล็อคอิน จะใช้ Webview แทนที่จะเป็นตัว built-in ของ Facebook SDK

เข้าไปที่โฟลเดอร์ facebook-android-sdk-3.8.0/bin จากไฟล์ facebook SDK ที่ดาวน์โหลดมา จะได้ไฟล์ FBAndroid-7.0.0.apk เราจะทำการติดตั้ง apk อันนี้ลง Emulator ครับ (หากใช้ Genymotion ก็ลากวางได้เลย หรือโหลดผ่าน Google Play เอาครับ)

การติดตั้ง บนวินโดว์เปิด cmd แล้วไปที่ ที่ติดตั้ง Android SDK ไว้ โดยทั่วไปน่าจะอยู่ที่ AppData\Local\Android\android-sdk\platform-tools\ ด้วยคำสั่ง

cd path/to/android-sdk-install/platform-tools/ adb install %HOMEPATH%\facebook-android-sdk-3.8\bin\FBAndroid-7.0.0.apk

เอ่อ คำสั่ง change directory บน Windows ผมจำไม่ได้ครับ ไม่รู้ว่าใช้ cd รึเปล่า อันนี้ไปทำเองนะครับ ฮ่าๆ ส่วน adb install ก็เป็น path ที่โหลด facebook sdk มาไว้อะครับ

สำหรับบน Mac หรือ Ubuntu ใช้คำสั่งนี้ (cd ไปที่ platfrom-tools เหมือนกัน)

cd path/to/android-sdk-install/platform-tools/ ./adb install ~/facebook-android-sdk-3.8/bin/FBAndroid-7.0.0.apk

Step 2: สร้าง Project

การสร้างโปรเจคใหม่ คงไม่ต้องมีภาพอธิบายนะครับ ผมอนุมานว่าทุกคนสร้างโปรเจคใหม่เป็นกันนะครับ หากไม่เป็น ก็อ่านได้จากบทความหน้า Android ในเว็บนี้ได้ครับ

โปรเจ็คใหม่ ผมตั้งชื่อตามนี้ละกัน

  • Application Name: AhoyFacebookLogin
  • Project Name: AhoyFacebookLogin
  • Package Name: com.devahoy.facebooksdk.sample
  • Minimum/ Target SDK: อันนี้เลือกตามสะดวกครับ ผมเลือก min: 11, Target: 17, Compile: 19

Create Project

Create Project2

Create Project3

Create Project4

Create Project5

หากใครไม่ชินกับการใช้ fragment ก็อ่านวิธีนี้ได้ครับ http://www.akexorcist.com จริงๆ เว็บนี้ เนื้อหาเยอะ และอธิบายได้ค่อนข้างดี แนะนำให้อ่านครับ

Step 3: เพิ่ม Library

มาถึงขั้นตอนการเพิ่ม library เพื่อใช้งานเจ้า Facebook SDK ครับ คลิกขวาที่ตัวโปรเจ็ค AhoyFacebookLogin เลือก Properties จากนั้นคลิ๊ก Add

Add Facebook Lib

Browse ไปหา Facebook SDK ที่ได้ทำการ import มาก่อนหน้านี้

Add Facebook Lib2

เมื่อทำการ add Library แล้ว ก็กด Apply เลย Add Facebook Lib3

อุ๊ป มีปัญหาเสียแล้ว มันฟ้องว่า All versions of the libraries must be the same at this time. ก็คือ มีปัญหา 2 อย่าง

  1. ไฟล์ android-support-v4.jar มันซ้ำกัน ระหว่าง AhoyFacebookLogin กับ appcompat_v7
  2. ไฟล์ android-support-v4.jar ไม่ตรงกัน ต้องมีอันไหนที่เป็นเวอร์ชั่นเก่ากว่าแน่นอน

Error

วิธีการแก้ปัญหา android-support-v4.jar

ลบไฟล์ android-support-v4.jar ใน appcompat_v7 ออกซะ จะได้ไม่มีปัญหาไฟล์ซ้ำกัน

จากนั้น Project => Clean ซักรอบหนึ่ง

อะฮ่า ยังมีปัญหาอยู่ใช่มั้ยครับ เพราะว่า ไฟล์มันไม่ตรงกันครับ คิดว่า ต้องทำการอัพเดทandroid-support-v4.jar ครับ คลิกขวาที่ โฟลเดอร์ FacebookSDK => Android Tools => Add Support Library

เมื่อมีหน้าจอขึ้นแบบนี้ ก็กด Install ไปครับ Eclipse จะทำการดาวน์โหลด Support Library เวอร์ชั่นใหม่มาครับ

Add support lib

จากนั้นโฟลเดอร์ AhoyFacebookLogin ก็ทำวิธีเดียวกันกับข้างบนครับ Android Tools => Add Support Library จากนั้น Project => Clean เป็นอันเรียบร้อย :)

ตอนนี้มาทดสอบดูว่า เราเพิ่มไลบรารี่ของ Facebook SDK มาแล้วจริงไหม เปิดไฟล์ MainActivity.java ทดลองทำการ import com.facebook.*; ถ้าไม่มีปัญหาอะไร แสดงว่าเพิ่ม library ถูกต้องแล้ว

Step 4: สร้างปุ่ม Facebook Login

มาถึงขั้นตอนการสร้างปุ่มสำหรับ Login ด้วย Facebook ละครับ ขั้นตอนนี้ทำการแก้ไขไฟล์ fragment_main.xml เป็นดังนี้ (หากใครไม่ได้ใช้ fragment ก็แก้ไขไฟล์ activity_main.xml แทน)

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <com.facebook.widget.LoginButton
        android:id="@+id/facebookLoginButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginTop="50dp" />

</LinearLayout>

จะได้หน้าตาดังนี้

Layout

แก้ไขไฟล์ AndroidManifest.xml โดยเพิ่มข้างล่างนี้ลงไป ก่อนปิดแท็ก application

<meta-data
    android:name="com.facebook.sdk.ApplicationId"
    android:value="@string/app_id" />

<activity android:name="com.facebook.LoginActivity" />

โดยค่าของ @string/app_id แก้ไขโดยเปิด /res/value/string.xml จากนั้นนำตัวเลขจาก Facebook App มาใส่ครับ

อ้อ อย่าลืมเพิ่ม permission อินเตอร์เนตด้วยละ

    <uses-permission
        android:name="android.permission.INTERNET" />

สุดท้ายไฟล์ AndroidManifest.xml จะได้ประมาณนี้

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.devahoy.facebooksdk.login"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="11"
        android:targetSdkVersion="17" />

    <uses-permission
        android:name="android.permission.INTERNET" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.devahoy.facebooksdk.login.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <meta-data
            android:name="com.facebook.sdk.ApplicationId"
            android:value="@string/app_id" />

        <activity android:name="com.facebook.LoginActivity" />
    </application>
</manifest>

ต่อไปเปิดไฟล์ MainActivity.java ผมประกาศตัวแปร TAG เอาไว้ สำหรับ debug นะครับ

private static String TAG = MainActivity.class.getSimpleName();

โค๊ดส่วนอื่นๆ ไม่ได้แก้ไขอะไรเลย ใช้ที่มีมาตอนเริ่มต้นสร้างโปรเจ็คเลย จากนั้นลองดูที่ inner class ชื่อว่า PlaceHolderFragment (จะอยู่ล่างๆหน่อย) ทำการสร้าง private เมธอดชื่อว่า onSessionStateChange ในคลาสนี้เลยครับ

private void onSessionStateChange(Session session, SessionState state, Exception exception) {
    if (state.isOpened()) {
        Log.i(TAG, "Logged in...");
    } else if (state.isClosed()) {
        Log.i(TAG, "Logged out...");
    }
}

โค๊ดข้างบนเอาไว้ handle พวก state ต่างๆครับ ว่าเปิดหรือปิด ต่อไป ก็ประกาศโค๊ดข้างล่าง เพื่อเวลามีการเปลี่ยนแปลง state ก็จะไปเรียกเมธอด onSessionStateChange

/**
 * A placeholder fragment containing a simple view.
 */
public static class PlaceholderFragment extends Fragment {
    private Session.StatusCallback callback = new Session.StatusCallback() {
        @Override
        public void call(Session session, SessionState state, Exception exception) {
            onSessionStateChange(session, state, exception);
        }
    };
...
}

ต่อมาประกาศตัวแปร UiLifecycleHelper ต่อจากด้านบนครับ

private UiLifecycleHelper uiHelper;

จากนั้น สร้างเมธอด onCreate() ขึ้นมา ใช้การ override จาก Fragment ครับ เพื่อสร้างอ็อปเจ็ค uiLifecycleHelper โดยส่งค่า callback ไป

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    uiHelper = new UiLifecycleHelper(getActivity(), callback);
    uiHelper.onCreate(savedInstanceState);
}

เพื่อให้แน่ใจว่าเรา setup session ได้ถูกต้อง ต้องทำการ override เมธอด ที่เป็น Life Cycle ของแอนดรอยส์ล่างข้างนี้ด้วยครับ

@Override
public void onResume() {
    super.onResume();
    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);
}

โค๊ดด้านบน ตรง onActivityResult จะส่งผลลัพธ์กลับมา กรณีเรากดปุ่ม Login ครับ

ต่อมาที่เมธอด onCreateView() เรายังไม่ได้ทำการ link Button กับไฟล์ xml เลยครับ ใช้ findViewById เพื่อหา id ของ FacebookButton ที่ประกาศไว้ใน fragment_main.xml

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_main, container,
            false);

    LoginButton authButton = (LoginButton) rootView.findViewById(R.id.facebookLoginButton);
    authButton.setFragment(this);
    return rootView;
}

สุดท้ายแก้ไข เมธอด onResume() นิดหน่อย กรณีมีปัญหา state เวลาเปิดแอพผ่าน bookmark link ครับ

@Override
public void onResume() {
    super.onResume();

    Session session = Session.getActiveSession();
    if (session != null &&
           (session.isOpened() || session.isClosed()) ) {
        onSessionStateChange(session, session.getState(), null);
    }

    uiHelper.onResume();
}

เสร็จแล้ว ทดสอบเปิดโปรแกรมเลยครับ Run => Run Android Application จะได้หน้าตาแบบนี้

Ahoy Facebook

ลองกดปุ่ม Login ดูครับ สังเกตว่ามีปัญหาอะไร?

อ้าว กดล็อคอินแล้ว ขอ permission ก็ให้แล้ว ทำไมมันยังกลับมาหน้า Login อีกเนี่ย!!! ปัญหานี้คือ เรายังไมไ่ด้ทำการตั้งค่า Facebook App ครับ ไปขั้นตอนต่อไปเลยฮะ

Step 5 : ตั้งค่า Facebook App

หลังจากสร้างโปรเจ็คแอนดรอยส์ เพิ่ม Facebook SDK เรียบร้อยแล้ว รวมถึงทดสอบโปรแกรม ปรากฎว่า ไม่สามารถล็อคอินหรือทำอะไรได้ เนื่องจากเรายังไม่ได้ทำการตั้งค่า Facebook App ที่สร้างไว้เลยครับ ทีแรกไม่ได้ตั้งค่า เนื่องจากเรายังไม่มีตัวโปรเจคแอนดรอยส์ ตอนนี้มีแล้ว ก็มาถึงขั้นตอนการสร้างเลย

กลับไปที่ Facebook App ที่เราได้สร้างไว้ครับ ttps://developers.facebook.com/apps/ ไปที่แท็ป Settings => Android เลือก Add Platform

Add Platform

เลือก Android

Choose Android

ที่ช่อง Package Name ให้ใส่แพจเกจเนมของเราที่ตั้งไว้ตอนสร้างโปรเจ็ค หากจำไม่ได้ ก็ดูที่ AndroidManifest.xml ครับ ส่วนผมใช้ชื่อ com.devahoy.facebooksdk.login

ส่วนอีกช่อง ให้กรอกชื่อคลาส ที่เราใช้ทำการ Login ครับ com.devahoy.facebooksdk.login.MainActivity

ส่วนช่อง KeyHashes ดูวิธีการหา ข้างล่างครับ

วิธีการหา Key Hash

มาถึงจุดสำคัญ ก็คือ KeyHash นั่นเอง Key Hash นั้นจะใช้ Keytool ซึ่งจะติดมากับ Java JDK อยู่แล้ว แต่ว่าวิธีการหาจะใช้คำสั่ง command line และใน Windows กับ *nix จะไม่เหมือนกันด้วย ผมทำบน Ubuntu มันได้นะครับ แต่บน Windows ไม่แน่ใจ สำหรับใครมีปัญหา ก็อ่านจาก Docs ของ Facebook ครับ

สำหรับ Macs หรือ Ubuntu เปิด Terminal ก็อปคำสั่งนี้ลงไป (อันนี้ใช้ keystore เป็นแบบ debug นะครับ หากอัพลง Google Play จะไม่สามารถลอคอินได้นะ)

keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore | openssl sha1 -binary | openssl base64

สำหรับ Windows

keytool -exportcert -alias androiddebugkey -keystore %HOMEPATH%.android\debug.keystore | openssl sha1 -binary | openssl base64

จะมีหน้าต่างขึ้นมาให้กรอกพาสเวิร์ด ให้ใส่ android จากนั้นกด Enter

Password android

ก็อป Key Hash ที่ได้ไปใส่ ช่อง Key Hash ใน Facebook App เสร็จเรียบร้อย

Save Setting

ทีนี้มาแก้ไข MainActivity.java นิดหน่อย เพื่อให้เวลาล็อคอิน ให้แสดงชื่อของคนล็อคอินเป็น Toast เด้งขึ้นมา

private void onSessionStateChange(Session session, SessionState state, Exception exception) {
    if (state.isOpened()) {

        Request request = Request.newMeRequest(session, new GraphUserCallback() {

            @Override
            public void onCompleted(GraphUser user, Response response) {
                Toast.makeText(getActivity(),
                        "Hello " + user.getName(),
                        Toast.LENGTH_LONG).show();
            }
        });
        request.executeAsync();

    } else if (state.isClosed()) {
        Log.i(TAG, "Logged out...");
    }
}

ข้างบนคือ เมื่อทำการล็อคอินสำเร็จ ก็จะทำการ request เอาชื่อของคนล็อคอินครับ มาแสดง ลองเล่นกับ GraphUser ดูได้ครับ สามารถ get ค่าอื่นๆ ได้อีกเยอะครับ

ทดสอบรันโปรเจ็คอีกครั้ง ลองกด Login แล้วดูผลลัพธ์

Login Permission

Login

เมื่อล็อคอินได้แล้ว ปุ่ม FacebookLogin จะเปลี่ยนเป็น Logout เมื่อกด ก็จะมีป็อปอัพถามว่า ต้องการ Logout ออกหรือไม่

Logout

ทั้งหมดก็มีเท่านี้ครับ นี่เป็นเพียงพื้นฐาน การใช้ Facebook SDK สำหรับ Android นะครับ ตัวอย่างข้างบน จริงๆผมก็ทำตามวิธีที่มีใน Docs แหละครับ อาจจะปรับเปลี่ยนบ้าง เพื่อให้เข้าใจง่ายขึ้น สำหรับใครติดปัญหาตรงไหน ก็อ่านเพิ่มเติมได้ที่ Docs เลยครับ หรือสอบถามมาได้ครับ บทความหน้า ผมจะยกตัวอย่าง การเข้าถึงข้อมูล information ของเราเวลาล็อคอิน รวมถึง get รายชื่อเพื่อนๆของเรากันครับ (แต่อันนี้ต้องขอ permission ก่อนนะ ถ้าจำไม่ผิด)

โค๊ดทั้งหมด

โค๊ดหลักๆ ก็แก้ไขอยู่แค่ 2-3 ไฟล์ครับ ที่เหลือเช่น string.xml ก็เพิ่มเอาเองนะครับ ไม่น่ายาก

AndroidManifest.xml

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.devahoy.facebooksdk.login"
        android:versionCode="1"
        android:versionName="1.0" >

        <uses-sdk
            android:minSdkVersion="11"
            android:targetSdkVersion="17" />

       <uses-permission
            android:name="android.permission.INTERNET" />

        <application
            android:allowBackup="true"
            android:icon="@drawable/ic_launcher"
            android:label="@string/app_name"
            android:theme="@style/AppTheme" >
            <activity
                android:name="com.devahoy.facebooksdk.login.MainActivity"
                android:label="@string/app_name" >
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />

                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>

            <meta-data
                android:name="com.facebook.sdk.ApplicationId"
                android:value="@string/app_id" />

            <activity android:name="com.facebook.LoginActivity" />
        </application>

    </manifest>

`fragment_main.xml`

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <com.facebook.widget.LoginButton
            android:id="@+id/facebookLoginButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="50dp" />

    </LinearLayout>

ไฟล์ MainActivity.java

package com.devahoy.facebooksdk.login;

import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import com.facebook.Request;
import com.facebook.Request.GraphUserCallback;
import com.facebook.Response;
import com.facebook.Session;
import com.facebook.SessionState;
import com.facebook.UiLifecycleHelper;
import com.facebook.model.GraphUser;
import com.facebook.widget.LoginButton;

public class MainActivity extends ActionBarActivity {

    private static String TAG = MainActivity.class.getSimpleName();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (savedInstanceState == null) {
            getSupportFragmentManager().beginTransaction()
                    .add(R.id.container, new PlaceholderFragment()).commit();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    /**
     * A placeholder fragment containing a simple view.
     */
    public static class PlaceholderFragment extends Fragment {
        private UiLifecycleHelper uiHelper;
        private Session.StatusCallback callback = new Session.StatusCallback() {
            @Override
            public void call(Session session, SessionState state, Exception exception) {
                onSessionStateChange(session, state, exception);
            }
        };

        public PlaceholderFragment() {
        }

        private void onSessionStateChange(Session session, SessionState state, Exception exception) {
            if (state.isOpened()) {

                Request request = Request.newMeRequest(session, new GraphUserCallback() {

                    @Override
                    public void onCompleted(GraphUser user, Response response) {
                        Toast.makeText(getActivity(),
                                "Hello " + user.getName(),
                                Toast.LENGTH_LONG).show();
                    }
                });
                request.executeAsync();

            } else if (state.isClosed()) {
                Log.i(TAG, "Logged out...");
            }
        }

        @Override
        public void onResume() {
            super.onResume();

            Session session = Session.getActiveSession();
            if (session != null &&
                   (session.isOpened() || session.isClosed()) ) {
                onSessionStateChange(session, session.getState(), null);
            }

            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);
        }

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            uiHelper = new UiLifecycleHelper(getActivity(), callback);
            uiHelper.onCreate(savedInstanceState);
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.fragment_main, container,
                    false);

            LoginButton authButton = (LoginButton) rootView.findViewById(R.id.facebookLoginButton);
            authButton.setFragment(this);
            return rootView;
        }

    }

}

References:

Buy Me A Coffee
Authors
Discord