สร้าง Facebook Login ด้วย Android Studio

Published on
Android
2014/05/facebook-sdk-for-android-using-android-studio
Discord

จากบทความที่แล้ว เขียนเกี่ยวกับ Facebook SDK for Android สร้างปุ่ม Login โดยใช้ Eclipse กันไป วันนี้ก็เลยมาเขียนบทความโดยใช้ Android Studio ครับ เผื่อบางคนใช้ Android Studio แล้วงงๆ กับตอน import Library Facebook จากบทความก่อน ผมจะข้าม Step1 ไปเลยครับเนื่องจากเป็นการเตรียมตัว การ Setup ซึ่งเหมือนกัน มาเริ่มที่ Step 2 การ สร้างโปรเจ็คเลย

เริ่มสร้างโปรเจ็ค

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

Create New Project

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

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

Choose launcher icon

Create New Project 3

Create New Project 4

เมื่อทำการสร้างโปรเจ็คเสร็จแล้ว ก็จะได้ไฟล์ MainActivity.java และ activity_main.xml ซึ่งเหมาะกับมือใหม่ดี จะได้ไม่ต้องงงๆกับ fragment เหมือนอย่างตอนสร้างโปรเจ็คใหม่บน Eclipse ครับ :)

Import Facebook Library

ทำการ import module ของ Facebook SDK ที่ดาวน์โหลดมา ลองดู Step1: เตรียมเครื่องมือ ประกอบครับ หรือหากต้องการโหลด Facebook SDK for Android โดยตรง ก็โหลดตามนี้ ปัจจุบันเวอร์ชั่น 3.14 แล้ว

กลับมาที่โปรเจ็คของ Android Studio คลิ๊กขวา -> เลือก New -> Module จากนั้นเลือก Import Existing Project

Import Existing Project

ที่ source directory เลือกไปยัง Facebook SDK ที่ดาวน์โหลดมา (ต้องทำการแตกไฟล์zip ออกมาซะก่อนนะ)

Source Directory

สังเกตว่าเลือก folder facebook ภายในโฟลเดอร์ facebook-android-sdk-3.14 อีกที

จะได้แบบนี้ คลิ๊ก Finish

Source Directory2

เมื่อทำการ import Library เสร็จ ปรากฎว่า Gradle build failed ซะงั้น

Gradle Build Failed

จริงๆ หากใครมี Build Tools เวอร์ชั่น 19.0.0 ในเครื่อง มันก็จะไม่ error หรอก แต่พอดีเครื่องนี้ไม่มี จึงทำให้เกิด error เนื่องจาก ไฟล์ build.gradle ของ Facebook SDK นั้นตั้งค่า build tool เป็น 19.0.0

วิธีแก้ก็มี 2 วิธีคือ ดาวน์โหลด Build Tool เวอร์ชั่น 19.0.0 มาซะ ผ่าน Android SDK Manager (แต่ไม่แนะนำ ควรใช้เวอร์ชั่นล่าสุดดีกว่า เวอร์ชั่น 19.0.3) และวิธีที่สอง คือ เปลี่ยนค่าที่ config ไว้ใน build.gradle เป็น 19.0.3 ซะ ดังนี้

เปิด build.gradle ใน facebook

build.gradle file

แล้วแก้เป็นแบบนี้

apply plugin: 'android-library'

dependencies {
    compile 'com.android.support:support-v4:13.0.+'
    compile files('libs/bolts.jar')
}

android {
    compileSdkVersion 19
    buildToolsVersion "19.0.3"

    defaultConfig {
        minSdkVersion 8
        targetSdkVersion 19
    }

    lintOptions {
        abortOnError false
    }

    sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src']
            res.srcDirs = ['res']
        }
    }
}

กด Try Again หรือเข้า Tools -> Android -> Sync Project with Gradle Files เป็นอันเรียบร้อย

จากนั้น ไปที่ app/build.gradle เพื่อทำการเพิ่ม Module Library ของ Facebook ที่เพิ่มมาเมื่อกี้ซะ โดยเพิ่ม compile project(':facebook') ไว้ในแท็ก dependencies ดังนี้

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    compile 'com.android.support:appcompat-v7:19.+'
    compile project(':facebook')
}

หรืออีกวิธีนึง เหมือนกันนั่นแหละ ถ้าไม่ได้ใช้วิธีเพิ่มโค๊ดไปเองใน build.gradle ก็ใช้วิธีเพิ่มแบบ GUI คือ คลิ๊กขวาที่ app เลือก Open Module Settings เลือกไปที่แท็ป dependencies จากนั้นเลือกปุ่ม + -> Module Dependency และก็เลือก :facebook คลิ๊ก apply -> OK

Facebook Module Library

ทำการ Sync Project with Gradle อีกครั้ง

หากใครมีปัญหา gradle ลองเปลี่ยน targetSDKVersion ใน build.gradle ของ facebook ให้เท่ากับหรือน้อยกว่าใน build.gradle ของ app ดูครับ

สร้างปุ่ม Facebook Login

ทำการแก้ไขไฟล์ 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>

จะได้หน้าตาแบบนี้

Facebook Login

รู้สึกจะมีปัญหาตอน Rendering XML ไม่แ่น่ใจว่าเป็นที่ Facebook SDK เวอร์ชั่น 3.14 หรือไม่ ทำให้ไม่สามารถดู Preview ในหน้า Graphic 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.sample" >

    <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.sample.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>

ส่วนวิธีการอื่นๆ ก็เหมือนจากบทความที่แล้วเลย เพียงแค่เปลี่ยนเครื่องมือเขียนเท่านั่นเอง อ่านได้ที่นี่

ไฟล์ทั้งหมดก็จะได้แบบนี้ อาจมีความแตกต่างกันบ้างเล็กน้อย เช่น ActionBarActivity ซึ่งเป็นค่าเริ่มต้นเวลาสร้างโปรเจ็คใหม่บท Android Studio ถ้าเป็น Eclipse จะเป็น FragmentActivity แล้วก็ MainFragment ซึ่งถ้าเป็น Android Studio ผมได้ทำการสร้างขึ้นมาเอง ส่วนถ้าเป็น Eclipse ในบทความเก่า จะถูกสร้างมาให้อัตโนมัติชื่อว่า PlaceholderFragment พร้อมกับ fragment_main.xml

โค๊ดทั้งหมด

ไฟล์ MainActivity.java

package com.devahoy.facebooksdk.sample;

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.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 MainFragment mainFragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        if (savedInstanceState == null) {
            // Add the fragment on initial activity setup
            mainFragment = new MainFragment();
            getSupportFragmentManager()
                    .beginTransaction()
                    .add(android.R.id.content, mainFragment)
                    .commit();
        } else {
            // Or set the fragment from restored state info
            mainFragment = (MainFragment) getSupportFragmentManager()
                    .findFragmentById(android.R.id.content);
        }
    }


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

    public static class MainFragment extends Fragment {
        private static final String TAG = MainFragment.class.getName();

        private UiLifecycleHelper uiHelper;

        private Session.StatusCallback callback = new Session.StatusCallback() {
            @Override
            public void call(Session session, SessionState state, Exception exception) {
                onSessionStateChange(session, state, exception);
            }
        };

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

                Request request = Request.newMeRequest(session, new Request.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.activity_main, container,
                    false);

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


ไฟล์ activity_main.java

<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>
Buy Me A Coffee
Authors
Discord