안드로이드 App에서 Kakao 로그인 연동
너무 간간히 연동 하다보니 할때마다 항상 새롭다.
당연히 삽질도 새롭게 다시 시작하고...
또 잊어버리기 전에 기록 해두어야겠다.
1. 프로젝트 등록 (카카오 개발자 콘솔)
관련 내용 설명 : http://firstblog912.tistory.com/8
2. 라이브러리 설정 (gradle 파일)
- Project > App > build.gradle 파일에 추가한다.
android {
.............................
packagingOptions {
exclude 'META-INF/services/javax.annotation.processing.Processor'
exclude 'META-INF/NOTICE.txt'
exclude 'META-INF/NOTICE'
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/LICENSE'
exclude 'META-INF/DEPENDENCIES'
}
repositories {
jcenter()
maven { url 'http://devrepo.kakao.com:8088/nexus/content/groups/public/' }
}
repositories {
mavenCentral()
}
}
dependencies {
.............................
compile 'com.squareup.picasso:picasso:2.3.2'
compile group: 'com.kakao.sdk', name: 'usermgmt', version: '1.11.1'
}
compile 'com.squareup.picasso:picasso:2.3.2' <- 이 라이브러리는 프로필 이미지를 보여주기 위한 용도로 필수적이지 않다.
3. 카카오 로그인 연동
레이아웃 파일 이외에 세개의 파일을 생성한다.
MainActivity.java
GlobalApplication.java
KakaoSDKAdapter.java
MainActivity 는 로그인 화면과 프로세서 처리를 담당한다.
KakaoSDKAdapter와 GlobalApplication 은 마치 서비스 처럼 동작하여 Kakao Session류의 처리를 담당한다.
- Layout xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.ubuno.kakaologinsample.MainActivity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/login_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="카카오톡 로그인"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="로그인해주세요"
android:id="@+id/tv_user_id"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="로그인해주세요"
android:id="@+id/tv_user_name"
android:layout_below="@+id/tv_user_id"
android:layout_centerHorizontal="true" />
<ImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:id="@+id/iv_user_profile"
android:layout_above="@+id/tv_user_id"
android:layout_centerHorizontal="true" />
</RelativeLayout>
</android.support.constraint.ConstraintLayout>
- MainActivity.java
실제 구동되는 메인 액티비티
public class MainActivity extends AppCompatActivity {
private SessionCallback mKakaocallback;
// view
private Button login_button;
private TextView tv_user_id;
private TextView tv_user_name;
private ImageView iv_user_profile;
private String userName;
private String userId;
private String profileUrl;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 헤쉬키를 가져온다
getAppKeyHash();
tv_user_id = (TextView) findViewById(R.id.tv_user_id);
tv_user_name = (TextView) findViewById(R.id.tv_user_name);
iv_user_profile = (ImageView) findViewById(R.id.iv_user_profile);
login_button = (Button) findViewById(R.id.login_button);
login_button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 카카오 로그인 요청
isKakaoLogin();
}
});
}private void isKakaoLogin() {
// 카카오 세션을 오픈한다
mKakaocallback = new SessionCallback();
com.kakao.auth.Session.getCurrentSession().addCallback(mKakaocallback);
com.kakao.auth.Session.getCurrentSession().checkAndImplicitOpen();
com.kakao.auth.Session.getCurrentSession().open(AuthType.KAKAO_TALK_EXCLUDE_NATIVE_LOGIN, MainActivity.this);
}protected void KakaorequestMe() {
UserManagement.getInstance().requestMe(new MeResponseCallback() {
@Override
public void onFailure(ErrorResult errorResult) {
int ErrorCode = errorResult.getErrorCode();
int ClientErrorCode = -777;
if (ErrorCode == ClientErrorCode) {
Toast.makeText(getApplicationContext(), "카카오톡 서버의 네트워크가 불안정합니다. 잠시 후 다시 시도해주세요.", Toast.LENGTH_SHORT).show();
} else {
Log.d("TAG" , "오류로 카카오로그인 실패 ");
}
}
@Override
public void onSessionClosed(ErrorResult errorResult) {
Log.d("TAG" , "오류로 카카오로그인 실패 ");
}
@Override
public void onSuccess(UserProfile userProfile) {
profileUrl = userProfile.getProfileImagePath();
userId = String.valueOf(userProfile.getId());
userName = userProfile.getNickname();
Log.i(TAG, "prifileUrl:" + profileUrl);
Log.i(TAG, "userId:" + userId);
Log.i(TAG, "userName:" + userName);
setLayoutText();
}
@Override
public void onNotSignedUp() {
// 자동가입이 아닐경우 동의창
}
});
}private void setLayoutText(){
tv_user_id.setText(userId);
tv_user_name.setText(userName);
Picasso.with(this)
.load(profileUrl)
.fit()
.into(iv_user_profile);
}
private void getAppKeyHash() {
try {
PackageInfo info = getPackageManager().getPackageInfo(getPackageName(), PackageManager.GET_SIGNATURES);
for (Signature signature : info.signatures) {
MessageDigest md;
md = MessageDigest.getInstance("SHA");
md.update(signature.toByteArray());
String something = new String(Base64.encode(md.digest(), 0));
Log.d(TAG, "getAppKeyHash > Hash key:" + something);
}
} catch (Exception e) {
// TODO Auto-generated catch block
Log.e(TAG, "getAppKeyHash > name not found : " + e.toString());
}
}
private class SessionCallback implements ISessionCallback {
@Override
public void onSessionOpened() {
// 사용자 정보를 가져옴, 회원가입 미가입시 자동가입 시킴
KakaorequestMe();
}
@Override
public void onSessionOpenFailed(KakaoException exception) {
if(exception != null) {
Log.d(TAG, "Session CallBack Error > " + exception.getMessage());
}
}
}
}
onSuccess 함수에서 보듯 getProfileImagePath(), getId(), getNickname() 함수를 통해 사용자 정보를 가져온다.
- GlobalApplication.java
서비스처럼 동작하기 위한 프로세서
public class GlobalApplication extends Application {
private static GlobalApplication mInstance;
private static volatile Activity currentActivity = null;
public static Activity getCurrentActivity() {
Log.d("TAG", "++ currentActivity : " + (currentActivity != null ? currentActivity.getClass().getSimpleName() : ""));
return currentActivity;
}
public static void setCurrentActivity(Activity currentActivity) {
GlobalApplication.currentActivity = currentActivity;
}
public static GlobalApplication getGlobalApplicationContext() {
if(mInstance == null)
throw new IllegalStateException("this application does not inherit GlobalApplication");
return mInstance;
}
@Override
public void onCreate() {
super.onCreate();
mInstance = this;
KakaoSDK.init(new KakaoSDKAdapter());
}
}
- KakaoSDKAdapter.java
Application 서비스 초기화
public class KakaoSDKAdapter extends KakaoAdapter {
@Override
public ISessionConfig getSessionConfig() {
return new ISessionConfig() {
@Override
public AuthType[] getAuthTypes() {
return new AuthType[] {AuthType.KAKAO_LOGIN_ALL};
}
@Override
public boolean isUsingWebviewTimer() {
return false;
}
@Override
public boolean isSecureMode() { return true; }
@Override
public ApprovalType getApprovalType() {
return ApprovalType.INDIVIDUAL;
}
@Override
public boolean isSaveFormData() {
return true;
}
};
}
@Override
public IApplicationConfig getApplicationConfig() {
return new IApplicationConfig() {
@Override
public Context getApplicationContext() {
return GlobalApplication.getGlobalApplicationContext();
}
};
}
}
4. 메니페스트에 카카오 서비스 등록
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="PACKAGE_NAME">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:name=".GlobalApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<meta-data
android:name="com.kakao.sdk.AppKey"
android:value="eabf3c2485cd80a68e1b30989e6f77a2" />
</application>
</manifest>
application > android:name=".GlobalApplication" <- 여기에 파일을 등록해 줘야 한다.