Unity3D Facebook SDK for Android Integration - 2. Facebook Init, Login, Logout

 유니티3D 안드로이드 프로젝트에 페이스북 연동을 위한 준비작업을 정리했었습니다. 이번에는 위 링크 내용을 기준으로 페이스북 초기화부터 로그인, 로그아웃 연동 작업에 대해 정리해봅니다.

 Prime31이라는 곳에서 각종 플러그인을 유료로 팔고 있네요. 그중에 당연히 페이스북 플러그인도 있긴합니다. 제가 정리하는건 Prime31이 필요없는 직접 구현하는 것에 대한 정리입니다. 즉, without Prime31 이죠. 아래는 소스입니다.

1. Android

package com.Test.unityandroidfacebookjar;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.Signature;
import android.os.Bundle;
import android.util.Base64;
import android.util.Log;
import android.view.Window;
import android.view.WindowManager;

import com.facebook.FacebookException;
import com.facebook.FacebookOperationCanceledException;
import com.facebook.FacebookRequestError;
import com.facebook.HttpMethod;
import com.facebook.Request;
import com.facebook.RequestAsyncTask;
import com.facebook.Response;
import com.facebook.Session;
import com.facebook.Session.NewPermissionsRequest;
import com.facebook.SessionState;
import com.facebook.model.GraphUser;
import com.facebook.widget.WebDialog;
import com.unity3d.player.UnityPlayer;
import com.unity3d.player.UnityPlayerActivity;

public class MainActivity extends UnityPlayerActivity {
 ///< 페이스북 앱 등록용 해시키값
 private String strHash;
 ///< 페이스북에 등록한 앱 ID
 private String strAppId;
 ///< 인스턴스 상태 값
 private Bundle savedInstanceState;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  ///< 인스턴스 상태를 저장한다.
  this.savedInstanceState = savedInstanceState;
 }
 
 public void onActivityResult(int requestCode, int resultCode, Intent data) {
  Session.getActiveSession().onActivityResult(this, requestCode, resultCode, data);
  super.onActivityResult(requestCode, resultCode, data);
 }
 
 protected void onSaveInstanceState(Bundle outState) {
  Session session = Session.getActiveSession();
  Session.saveSession(session, outState);
  super.onSaveInstanceState(outState);
 }
 
 ///< 페이스북 초기화. 유니티에서 호출하는 함수
 public void InitFacebook_U(String strAppId)
 {
  this.strAppId = strAppId;
  
  ///< 해쉬키를 찾는다.
  try {
   PackageInfo info = this.getPackageManager().getPackageInfo(getPackageName(), PackageManager.GET_SIGNATURES);
   for (Signature sig : info.signatures) {
    MessageDigest md = MessageDigest.getInstance("SHA");
    md.update(sig.toByteArray());
    strHash = Base64.encodeToString(md.digest(), Base64.DEFAULT);
   }
  }
  catch (NameNotFoundException e) {
   Log.d("UnityFacebookTest", "Error Hashkey not found");
  }
  catch (NoSuchAlgorithmException e) {
   Log.d("UnityFacebookTest", "Error Hashkey no such algorithm");
  }
  ///< 해시키를 출력. 이 값을 페이스북 개발자 센터의 등록한 앱에 기입
  Log.d("UnityFacebookTest", "Hash : " + this.strHash);
  
  Session session = Session.getActiveSession();
  ///< 세션이 없다면 생성을 하자.
  if (session == null) {
   ///< 세션 복구 시도
   if (this.savedInstanceState != null) {
    session = session.restoreSession(this, null, statusCallback, this.savedInstanceState);
    Log.d("UnityFacebookTest", "Session restoreSession");
   }
   ///< 세션 생성
   if (session == null) {
    session = new Session.Builder(this).setApplicationId(this.strAppId).build();
    Log.d("UnityFacebookTest", "Session Builder");
   }
   
   ///< 세션 저장하고 오픈
   Session.setActiveSession(session);
   if (session.getState().equals(SessionState.CREATED_TOKEN_LOADED)) {
    session.openForRead(new Session.OpenRequest(this).setCallback(statusCallback));
    Log.d("UnityFacebookTest", "Session openForRead");
   }
  }
 }
 
 ///< 로그인. 유니티에서 호출하는 함수
 public void Login_U() {
     Session session = Session.getActiveSession();
     if (session.isOpened() == false && session.isClosed() == false) {
      session.openForRead(new Session.OpenRequest(this).setCallback(statusCallback));
      Log.d("UnityFacebookTest", "Login openForRead");
     } else if (session != null) {
      Session newSession = new Session.Builder(this).setApplicationId(this.strAppId).build();
      Session.setActiveSession(newSession);
      newSession.openForRead(new Session.OpenRequest(this).setCallback(statusCallback));
      Log.d("UnityFacebookTest", "Login new Session");
     } else {
      Log.d("UnityFacebookTest", "Error Session is null");
     }
    }
 ///< 로그아웃
 public void Logout_U() {
  Session session = Session.getActiveSession();
  if (session.isClosed() == false) {
   session.closeAndClearTokenInformation();
   Log.d("UnityFacebookTest", "Logout ClearTokenInfo");
  }
 }
 ///< 세션 처리 콜백
 private Session.StatusCallback statusCallback = new SessionStatusCallback();
    private class SessionStatusCallback implements Session.StatusCallback {
        @Override
        public void call(Session session, SessionState state, Exception exception) {
            if (state.isOpened())
            {
                Log.d("UnityFacebookTest", "Session state opened");
            }
            else
            {
                Log.d("UnityFacebookTest", "Session state closed");
            }
        }
    }
}

 준비과정에서 만들었던 UnityAndroidFacebookJar 프로젝트의 MainActivity.java 소스를 위와같이 수정 및 저장하고 빌드 후 jar 파일로 export합니다. export된 jar 파일은 유니티 프로젝트의 플러그인 디렉터리에 복사해주시구요.

 지난번에는 페이스북 해시키 생성을 위해 콘솔에서 openssl도 설치하고 keytool로 추출을 하는 복잡한 과정을 거쳤는데 이번에는 위와같이 코드로 처리했습니다. 해당 소스는 처음 추출할 때만 필요하고 추출하셨다면 지우셔도 무관합니다.


2. Unity3D

public class FacebookManager : MonoBehaviour
{
static FacebookManager _instance;
private AndroidJavaObject curActivity;

public static FacebookManager GetInstance()
{
if( _instance == null )
{
_instance = new GameObject("FacebookManager").AddComponent<FacebookManager>();
}

return _instance;
}

void Awake()
{
AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
curActivity = jc.GetStatic<AndroidJavaObject>("currentActivity");
}

public void Init(string strAppId)
{
curActivity.Call("InitFacebook_U", strAppId);
}

public void Login()
{
curActivity.Call("Login_U");
}

public void Logout()
{
curActivity.Call("Logout_U");
}
}

 간단한 FacebookManager 싱글턴 컴포넌트입니다. 이제 이것을 사용하는 TestGUI 컴포넌트는 아래와 같습니다.

public class TestGUI : MonoBehaviour
{
 void Start()
 {
  
 }
 
 // Update is called once per frame
 void Update ()
 {
  if (Application.platform == RuntimePlatform.Android)
        {

            if (Input.GetKey(KeyCode.Escape))
            {
                Application.Quit();
                return;
            }
  }  
 }

 void OnGUI()
 {
  float fYpos = 0;
  GUI.Label(new Rect(0, fYpos, 400, 100), "Unity3D Android Facebook Test");
  
  fYpos += 50;
  if (GUI.Button (new Rect(0, fYpos, 100, 50), "Init") == true)
  {///< 자신의 페이스북 앱 ID를 넣어준다.
   FacebookManager.GetInstance().Init("442544649174747");
  }
  
  fYpos += 50;
  if (GUI.Button (new Rect(0, fYpos, 100, 50), "Login") == true)
  {
   FacebookManager.GetInstance().Login();
  }
  
  fYpos += 50;
  if (GUI.Button (new Rect(0, fYpos, 100, 50), "Logout") == true)
  {
   FacebookManager.GetInstance().Logout();
  }
 }
}

 페이스북 초기화, 로그인 등의 버튼을 만드는 GUI 컴포넌트입니다. Main Camera에 붙여줍니다.


3. Facebook R.java Build

 마지막으로 유니티에서 빌드한 후 임시 디렉터리인 Temp/StagingArea/gen/com/Test/unityandroidfacebookjar에 생성되는 Facebook의 R.java를 플러그인에 위 스샷과 같이 jar로 만들어 넣어줘야합니다. 그런데 이 부분에서 java.lang.NoClassDefFoundError: com.facebook.android.R$layout 이슈가 있습니다. 이슈 해결은 링크에도 있지만 완벽한 해결이 아니라는게 좀 걸리네요. 페이스북 SDK 버전이라도 올라간다면 나중에 또 이슈가 생길 수 있습니다.


4. Build and Run

 빌드하고 에이서 A500에서 실행한 스샷입니다.

 Init을 눌러 Facebook을 초기화 한 후 Login을 누르면 위와같이 페이스북 로그인 페이지가 뜹니다. 참고로 전 이 테스트를 위해 태블릿에 깔린 페이스북 앱에서 로그아웃을 한 후 진행했습니다. 이미 로그인이 된 상태라면 조금 다를 수 있습니다. 아마 바로 로그인 되거나 잠깐 로딩 화면이 나오고 다시 유니티 화면으로 전환될 것입니다.

 로그인이 되면 위와같이 UnityFacebook에서 공개 프로필, 친구 리스트에 액세스 권한을 요청하고 있습니다. 라고 뜹니다. 확인을 눌러줍니다.

 이것으로 유니티3D에 페이스북 SDK 안드로이드 연동 기본사항을 정리해봤습니다. 다음에는 자신의 담벼락에 게시하는 것과 자신의 정보를 얻어와 프로필 사진을 출력해보는 것을 정리해보겠습니다.

댓글

이 블로그의 인기 게시물

'xxx.exe' 프로그램을 시작할 수 없습니다. 지정된 파일을 찾을 수 없습니다.

goorm IDE에서 node.js 프로젝트로 Hello World Simple Server 만들어 띄워보기

애드센스 수익을 웨스턴 유니온으로 수표대신 현금으로 지급 받아보자.