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

จากบทความที่แล้ว เขียนเกี่ยวกับ Facebook SDK for Android สร้างปุ่ม Login โดยใช้ Eclipse กันไป วันนี้ก็เลยมาเขียนบทความโดยใช้ Android Studio ครับ เผื่อบางคนใช้ Android Studio แล้วงงๆ กับตอน import Library Facebook จากบทความก่อน ผมจะข้าม Step1 ไปเลยครับเนื่องจากเป็นการเตรียมตัว การ Setup ซึ่งเหมือนกัน มาเริ่มที่ Step 2 การ สร้างโปรเจ็คเลย
เริ่มสร้างโปรเจ็ค
เริ่มทำการสร้างโปรเจ็คใน Android Studio กันเลยครับ คิดว่าทุกคนคงสร้างกันเป็น ก็ดูตามภาพไปเลยครับ หากไม่เป็นจริงๆ ก็อ่านนี้ สร้างโปรเจ็คด้วย Android Studio
โปรเจ็คใหม่ ผมตั้งชื่อตามนี้ละกัน
- 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
เมื่อทำการสร้างโปรเจ็คเสร็จแล้ว ก็จะได้ไฟล์ 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
ที่ source directory เลือกไปยัง Facebook SDK ที่ดาวน์โหลดมา (ต้องทำการแตกไฟล์zip ออกมาซะก่อนนะ)
สังเกตว่าเลือก folder
จะได้แบบนี้ คลิ๊ก Finish
เมื่อทำการ import Library เสร็จ ปรากฎว่า 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
แล้วแก้เป็นแบบนี้
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
ทำการ 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>
จะได้หน้าตาแบบนี้
รู้สึกจะมีปัญหาตอน 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>
- Authors
-
Chai Phonbopit
เป็น Web Dev ในบริษัทแห่งหนึ่ง ทำงานมา 10 ปีกว่าๆ ด้วยภาษาและเทคโนโลยี เช่น JavaScript, Node.js, React, Vue และปัจจุบันกำลังสนใจในเรื่องของ Blockchain และ Crypto กำลังหัดเรียนภาษา Rust