유니티 페이스북 연동 - 안드로이드(로그인&아웃,내사진&글 올리기&정보,친구목록) Unity
2013/06/10 15:56
http://blog.naver.com/psd0217/10170072555
- 페이스북 개발자 및 앱 등록
- 유니티3D 안드로이드 JAR 플러그인 프로젝트 생성
- 페이스북 SDK 설치 및 빌드
- 연동에 필요한 관련 파일 복사 및 AndroidManifest.xml 수정
- 테스트를 위한 페이스북 해시키 생성 및 등록
1. 페이스북 개발자 등록
먼저 페이스북 개발자 등록을 합니다.
2. 페이스북 앱 등록
만들어 서비스할 앱을 페이스북에 등록합니다.
3. 유니티3D 프로젝트 및 안드로이드 페이스북 Jar 플러그인 만들기
유니티3D에서 안드로이드용 외부 SDK 연동을 위해서는 플러그인 JAR 파일을 만들어야하죠. 링크에 있는 내용을 보시고 폴더 설정등 기본 준비작업을 하시면 됩니다. 저는 스샷과 같이 UnityAndroidFacebookJar라고 만들었습니다.
4. 페이스북 안드로이드 SDK 설치 및 임포트
페이스북 개발자 페이지의 안드로이드 SDK를 다운로드합니다. v3.0.1이 현재 최신입니다.
적당한 곳에 다운로드 받은 페이스북 안드로이드 SDK를 압축해제합니다. 제 프로젝트 구성은 위와 같습니다. UnityFacebook은 유니티3D 프로젝트고 AndroidJar에는 위에서 생성한 이클립스 프로젝트가 들어있습니다.
이클립스에서 페이스북 SDK를 임포트합니다. facebook-android-sdk-3.0.1\facebook 에 들어있습니다. 그러면 스샷과 같이 느낌표가 있고 에러가 발생할 듯합니다.
Project 'FacebookSDK' is missing required source folder: 'gen'
The project cannot be built until build path errors are resolved
Unable to resolve target 'android-8'
위와 같은 에러인데 따로 정리를 했으니 링크를 참고하시기 바랍니다.
AndroidManifest와 UnityAndroidFacebook.jar는 위에서 만든 이클립스 프로젝트의 것을 복사했습니다.
페이스북을 연동한 안드로이드 앱을 테스트하려면 페이스북 개발자 페이지에서 등록한 앱에 해시키 값을 위 스샷과 같이 등록해야합니다. 해시키 생성하는 것은 따로 정리 했으니 링크를 참고하시고 만들어진 해시키를 각자가 만드신 앱의 정보 페이지에서 네이티브 Android 앱 부분을 클릭해 Key Hashes 부분에 기입하신 후 변경 내용 저장하면 됩니다.
다음 포스팅에서는 페이스북 SDK 초기화와 로그인, 로그아웃 코드 연동 작업을 정리하겠습니다.
유니티3D 안드로이드 프로젝트에 페이스북 연동을 위한 준비작업을 정리했었습니다. 이번에는 위 링크 내용을 기준으로 페이스북 초기화부터 로그인, 로그아웃 연동 작업에 대해 정리해봅니다.
Prime31이라는 곳에서 각종 플러그인을 유료로 팔고 있네요. 그중에 당연히 페이스북 플러그인도 있긴합니다. 제가 정리하는건 Prime31이 필요없는 직접 구현하는 것에 대한 정리입니다. 즉, without Prime31 이죠. 아래는 소스입니다.
1. Android
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("com.Test.unityandroidfacebookjar", 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 안드로이드 연동 기본사항을 정리해봤습니다. 다음에는 자신의 담벼락에 게시하는 것과 자신의 정보를 얻어와 프로필 사진을 출력해보는 것을 정리해보겠습니다.
유니티3D 안드로이드에 페이스북 초기화, 로그인 로그아웃 연동을 정리했었습니다. 이번에는 아래와 같은 것들을 정리해봅니다.
- 자신의 정보를 얻기
- 자신의 담벼락에 글을 게시
- 자신의 프로필 사진 이미지 출력
1. 자신의 담벼락에 글 게시
public void PostToMeWall_U(final String strMsg) {
runOnUiThread(new Runnable(){
public void run() {
Session session = Session.getActiveSession();
final List<String> PERMISSIONS = Arrays.asList("publish_stream");
if (session != null)
{
NewPermissionsRequest reauthRequest = new Session.NewPermissionsRequest(UnityPlayer.currentActivity, PERMISSIONS);
session.requestNewPublishPermissions(reauthRequest);
}
Bundle postParams = new Bundle();
postParams.putString("message", strMsg);
Request request = new Request(session, "/me/feed", postParams,
HttpMethod.POST, requestCallback);
RequestAsyncTask requestAsyncTask = new RequestAsyncTask(request);
requestAsyncTask.execute();
}
});
}
유니티에서 호출하는 자바 함수입니다. publish_stream 권한은 사실 자신의 담벼락에 게시할 때는 필요하지 않은 듯합니다. 자신 이외에 친구들에게 할 때 필요한 듯보이네요. graph api중 하나에 속하는 message를 추가하고 유니티로부터 받은 스트링을 추가합니다. 요청할때는 /me/feed 라고 했는데 밑에서 알아볼 자신의 숫자로된 페이스북 id를 넣어줘도 됩니다. 친구의 id를 넣어주면 친구의 담벼락에 게시가 되겠죠.
Request.Callback requestCallback = new Request.Callback() {
public void onCompleted(Response response) {
JSONObject graphResponse = response.getGraphObject().getInnerJSONObject();
String postId = null;
try {
postId = graphResponse.getString("id");
} catch (JSONException e) {
Log.i("UnityFacebookTest", "JSON error " + e.getMessage());
}
FacebookRequestError error = response.getError();
if (error != null) {
Log.d("UnityFacebookTest", error.getErrorMessage());
} else {
Log.d("UnityFacebookTest", "success post score to wall. " + postId);
}
}
};
요청에 대한 콜백입니다. 로그 정도만 처리하고 있습니다.
public string strPostMsg = string.Empty;
public void PostToMeWall(string strMsg)
{
curActivity.Call("PostToMeWall_U", strMsg);
}
FacebookManager 컴포넌트의 추가된 내용입니다. 스트링 변수를 하나 추가해주고 자바 호출을 추가해줍니다.
fYpos += 50;
FacebookManager.GetInstance().strPostMsg = GUI.TextField(new Rect(0, fYpos, 300, 50), FacebookManager.GetInstance().strPostMsg);
fYpos += 50;
if (GUI.Button (new Rect(0, fYpos, 100, 50), "Post") == true)
{
FacebookManager.GetInstance().PostToMeWall( FacebookManager.GetInstance().strPostMsg );
}
GUI 쪽 추가된 내용이구요. 텍스트 입력을 위해 텍스트필드를 추가하고 위에 추가했던 변수에 넣어줍니다. Post를 누르면 페이스북메니저를 통해 자바가 호출되겠지요.
test facebook post by unity3d라고 입력했습니다.
제 페이스북 담벼락에 게시된 내용입니다. curl로 담벼락에 게시할 때는 한글이 깨졌었는데 유니티에서는 잘 되네요.
2. 자신의 정보를 얻기
public void requestMe_U() {
runOnUiThread(new Runnable(){
public void run() {
Session session = Session.getActiveSession();
Request.executeMeRequestAsync(session, new Request.GraphUserCallback() {
@Override
public void onCompleted(GraphUser user, Response response) {
// TODO Auto-generated method stub
if (user != null) {
Log.d("UnityFacebookTest", user.getId());
Log.d("UnityFacebookTest", user.getName());
JSONObject jsonObj = new JSONObject();
try {
jsonObj.put(user.getId(), user.getName());
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
}
});
}
자신의 정보를 요청해서 간단히 id와 이름을 출력하는 내용입니다. Request.executeMeRequestAsync를 안쓰고 위 처럼 Request와 Bundle에 직접 graph api 인자들을 넣어서 요청해도 가능합니다. 한가지 접근 api만 있는건 아닌거죠.
///< 페이스북 메니져 컴포넌트에 추가
public void RequestMe()
{
curActivity.Call("requestMe_U");
}
///< GUI 컴포넌트에 추가
fYpos += 50;
if (GUI.Button (new Rect(0, fYpos, 100, 50), "Me") == true)
{
FacebookManager.GetInstance().RequestMe();
}
3. 자신의 프로필 사진 이미지 출력
private Texture2D curDownTex = null;
private Texture2D texMe = null;
fYpos += 50;
if (GUI.Button (new Rect(0, fYpos, 100, 50), "Me") == true)
{
//FacebookManager.GetInstance().RequestMe();
///*
StartCoroutine(MyPicDown("wwforever80"));
//*/
}
fYpos += 50;
if ( texMe != null )
{
GUI.DrawTexture(new Rect(0, fYpos, texMe.width, texMe.height), texMe);
}
private IEnumerator MyPicDown(string strId)
{
yield return StartCoroutine( DownPic(strId) );
texMe = curDownTex;
}
private IEnumerator DownPic(string strFacebookId)
{
string strPicUrl;
strPicUrl = System.String.Format("http://graph.facebook.com/{0}/picture", strFacebookId);
WWW www = new WWW(strPicUrl);
Debug.Log(strPicUrl);
yield return www;
if (www.error != null)
{
Debug.Log("Picture error");
}
else
{
curDownTex = www.texture;
//www.LoadImageIntoTexture(curDownTex);
Debug.Log(www.url);
}
}
페이스북 프로필 이미지를 코루틴과 WWW로 다운받아 Texture2D로 저장하고 출력하는 부분입니다. 전부 GUI 컴포넌트쪽이구요. graph api중 picture인 http://graph.facebook.com/{0}/picture 부분에서 전 제 영문 ID를 바로 넘겨줬는데 위에서 알아낸 숫자 id를 넘겨줘도 됩니다.
이제 빌드 후 실행해보면 위와 같이 페이스북 프로필 사진이 출력됩니다.
다음에는 친구 목록을 얻어와서 친구들의 프로필 사진을 랜덤하게 출력하는 것을 정리해보겠습니다.
유니티3D 페이스북 SDK 안드로이드 연동 관련 자신의 담벼락 게시 및 자신의 프로필 이미지 출력까지 해봤습니다. 이번 포스팅은 페이스북 친구 목록을 얻어와서 친구의 프로필 사진을 유니티3D로 렌더링하는 것까지 정리해보겠습니다.
1. 친구 목록 가져오기
public void requestFriends_U() {
runOnUiThread(new Runnable(){
public void run() {
Session session = Session.getActiveSession();
Request.executeMyFriendsRequestAsync(session, new Request.GraphUserListCallback() {
@Override
public void onCompleted(List<GraphUser> users,
Response response) {
// TODO Auto-generated method stub
if (users != null) {
JSONArray jsonArr = new JSONArray();
for (GraphUser user : users) {
Log.d("UnityFacebookTest", user.getName() + " " + user.getId());
try {
JSONObject jsonObj = new JSONObject();
jsonObj.put("FacebookId", user.getId());
jsonObj.put("Name", user.getName());
jsonArr.put(jsonObj);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
UnityPlayer.UnitySendMessage("FacebookManager", "ResultFriends_J", jsonArr.toString());
}
}
});
}
});
}
먼저 자바쪽입니다. Request.executeMyFriendsRequestAsync를 통해 친구 목록을 요청합니다. Request.GraphUserListCallback의 onCoompleted에서 친구 목록을 JSONObject로 만들어 JSONArray에 쌓고있죠. 마지막에는 유니티3D에 json을 스트링형으로 넘겨줍니다.
결과부터 보면 위와같이 로그로 잘 찍혔습니다. 이제 유니티3D부분을 보겠습니다.
using LitJson;
private Dictionary<string, string> dicFriends;
void Awake()
{
...
this.dicFriends = new Dictionary<string, string>();
}
public void RequestFriends()
{
curActivity.Call("requestFriends_U");
}
public void ResultFriends_J(string jsonFriends)
{
JsonData jData = JsonMapper.ToObject(jsonFriends);
for (int i = 0 ; i < jData.Count ; i++)
{
string strFacebookId = jData[i]["FacebookId"].ToString();
string strFacebookName = jData[i]["Name"].ToString();
Debug.Log("Friend id " + strFacebookId + " Name " + strFacebookName);
this.dicFriends.Add(strFacebookId, strFacebookName);
}
Debug.Log("Friend Count = " + this.dicFriends.Count.ToString());
}
FacebookManager 컴포넌트에 추가된 부분입니다. 친구 목록을 스트링으로 받아와서 JSON 객체로 만든 후 Dictionary에 추가하고 있습니다. C#에서 JSON을 사용하기 위해 저는 LitJson을 사용했습니다. 링크를 참고하세요.
class Friend
{
public Texture2D texFriend = null;
public Rect rtTexPos;
}
List<Friend> listFriend = null;
void OnGUI()
{
...
fYpos += 50;
if (GUI.Button (new Rect(0, fYpos, 100, 50), "Get Friends\nList") == true)
{
FacebookManager.GetInstance().RequestFriends();
}
}
TestGUI 컴포넌트 부분입니다.
2. 친구 프로필 사진 출력하기
위 내용과 아래에 나올 GUI쪽 작업을 하면 위와 같이 생겼습니다. 이번에는 자바쪽은 없고 유니티3D쪽 C# 작업만 있습니다.
public Dictionary<string, string> GetFriends()
{
return this.dicFriends;
}
쌓아둔 친구 목록을 통째로 가져오기 위해 FacebookManager 컴포넌트에 위와같은 함수를 추가합니다.
fYpos += 50;
if (GUI.Button (new Rect(0, fYpos, 100, 50), "Down Friends\nPic") == true)
{
StartCoroutine(DownFriendPic());
}
if (this.listFriend != null)
{
for ( int i = 0 ; i < this.listFriend.Count ; i++)
{
if (this.listFriend[i].texFriend != null)
GUI.DrawTexture(this.listFriend[i].rtTexPos, this.listFriend[i].texFriend);
}
}
TestGUI 컴포넌트 OnGUI에 위와같이 친구의 사진을 다운로드할 버튼을 추가하고 친구 프로필 사진을 그려주는 GUI.DrawTexture를 추가합니다.
private IEnumerator DownFriendPic()
{
Dictionary<string, string> dicFriends;
dicFriends = new Dictionary<string, string>(FacebookManager.GetInstance().GetFriends());
if (dicFriends.Count > 0)
{
Debug.Log ("Friends num " + dicFriends.Count.ToString());
this.listFriend = new List<Friend>();
foreach (KeyValuePair<string, string> pair in dicFriends)
{
Friend friend = new Friend();
yield return StartCoroutine( DownPic(pair.Key) );
friend.rtTexPos = new Rect(
Random.Range(0, Screen.width)
, Random.Range(0, Screen.height)
, 50, 50);
friend.texFriend = curDownTex;
this.listFriend.Add(friend);
}
}
}
코루틴을 사용해서 친구의 프로필 사진을 WWW로 다운받아 Texture2D에 저장합니다. 위치는 랜덤하게 잡아줬습니다.
버튼을 누르면 친구 사진이 다운로드가 됩니다. 코루틴을 사용하기 때문에 비동기로 하나씩 렌더링이 되죠.
친구 프로필 사진이 모두 그려진 상태입니다.
간단히? 유니티3D에 페이스북 안드로이드 연동 포스팅을 해봤습니다. 여기서 더 해나갈지는 두고봐야겠네요.
'TA > Unity' 카테고리의 다른 글
문자를 숫자로/숫자를 문자로 (0) | 2013.09.05 |
---|---|
유니티게임 구글 인앱 결제 붙이기!! (0) | 2013.08.29 |
SDK....빌드셋팅 한방 Xamarin... (0) | 2013.07.23 |
iTween Path collider 충돌시 멈추기 (0) | 2013.06.21 |
ITween Example Tutorial (0) | 2013.06.21 |