카카오 로그인 연동
카카오 로그인 연동을 하기 위해서는
사전에 카카오 개발자 센터에서 애플리케이션 등록을
먼저 해주어야 합니다.
(사전 등록 요약) 패키지명, 마켓URL, 키해시
해당 포스팅은 애플리케이션 등록이 완료된 이후에
진행됩니다.
○ 안드로이드 환경 : SDK(안드로이드 API 21 이상), JDK(JDK 11이상), Gradle 빌드
※ 카카오 개발자 센터에서 카카오 로그인 가이드는
'카카오톡'으로 로그인을 권장하고 있음을
참고하시길 바랍니다.
1. 환경 설정
카카오 서버와 통신하기 위해 앱에 인터넷 사용 권한을 설정(AnroidManifest.xml)
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.sample">
<!-- 인터넷 사용 권한 설정-->
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
...
gradle 스크립트에 다음과 같이 추가.(build.gradle)
repositories {
~
maven {url "https://devrepo.kakao.com/nexus/content/groups/public/" }
}
+
implementation "com.kakao.sdk:v2-user:2.20.4" // 카카오 로그인 API 모듈
gradle 설정으로 카카오로그인 SDK를 사용할 수 있는 세팅이 완료되었습니다.
gradle sync 또는 빌드를 해주어 오류가 나는 지 확인해봅시다.
3. 리다이렉트 URI 설정 : 카카오 로그인 기능을 구현하기 위해서는 리다이렉션(Redirection) 을 통해
'인가코드'를 받아야합니다. (AndroidManifest.xml에 액티비티 설정 필요)
<activity
android:name="com.kakao.sdk.auth.AuthCodeHandlerActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- Redirect URI: "kakao${NATIVE_APP_KEY}://oauth" -->
<data android:host="oauth"
android:scheme="kakao${NATIVE_APP_KEY}" />
</intent-filter>
</activity>
2. 초기화 로직: 애플리케이션 상에서 카카오 SDK를 사용할 있게 초기화 선언을 해주어야 합니다.
KakaoSdk.init(this, "{NATIVE_APP_KEY}");
- NATIVE_APP_KEY : 애플리케이션 등록 후 발급받은 네이티브 앱 키
(카카오 개발자 센터 내 애플리케이션에서 확인 )
4. 로그인 로직 : 해당 로직을 통해 로그인을 진행할 수 있습니다.
카카오 개발자 센터에서는 카카오톡 로그인을 권장하고 있습니다.
해당 포스팅에서는
커스텀 로그인 버튼을 이용하여
단말에 카카오톡으로 로그인할 수 있는 경우에는 카카오톡 로그인을
카카오톡으로 로그인할 수 없는 경우에는 일반 카카오 로그인을
구현하도록 하겠습니다.
※ 프로필 정보 얻기, 추가 항목 동의 받기 도 포함되어 있습니다.
4-1. 레이아웃 파일에 로그인 버튼 생성
예시)ImageView를 사용하여 버튼을 만들어줌.
<ImageView
android:id="@+id/kakaoBtn"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
app:srcCompat="@drawable/kakao_login_large_narrow" />
4-2. 액티비티 파일 에로그인 버튼에 대한 로직 추가 :
NaverIdLoginSDK.authenticate() 사용
ImageView k_login_button = findViewById(R.id.kakaoBtn);
~
//버튼 클릭 리스너
k_login_button.setOnClickListener(new View.OnClickListener() {
String TAG = "login_process";
@Override
public void onClick(View view) {
Log.d(TAG, "kakaotalk ok? : " + UserApiClient.getInstance().isKakaoTalkLoginAvailable(AuthActivity.this));
if(UserApiClient.getInstance().isKakaoTalkLoginAvailable(AuthActivity.this)) {
//카카오톡 로그인이 가능하면 카카오톡으로 로그인
UserApiClient.getInstance().loginWithKakaoTalk(AuthActivity.this, (token, err) -> {
if (err != null) {
//로그인 실패
Log.e(TAG, "카카오톡 로그인 실패", err);
Log.e(TAG, "카카오톡 로그인 실패2 : " + err.getMessage());
//사용자가 카카오톡 서치 후 디바이스 권한 요청에서 로그인을 취고한 경우,
//의도적인 로그인 취소로 보고 카카오계정으로 로그인 시도 없이 로그인 취소 처리
UserApiClient.getInstance().loginWithKakaoAccount(AuthActivity.this, (btoken, berr) -> {
if (berr != null) {
Log.e(TAG, "카카오 로그인 실패", berr);
} else {
Log.i(TAG, "카카오 로그인 성공(토큰)1 : " + btoken);
}
return null;
});
} else {
//로그인 성공
Log.i(TAG, "카카오톡 로그인 성공(토큰)2 : " + token);
updateKakaoLogin(token,1);
}
return null;
});
}else{
//카카오톡 로그인이 가능하지 않은 경우, 일반 카카오 로그인
UserApiClient.getInstance().loginWithKakaoAccount(AuthActivity.this, (btoken, berr) -> {
if (berr != null) {
Log.e(TAG, "카카오 로그인 실패", berr);
} else {
Log.i(TAG, "카카오 로그인 성공(토큰)1 : " + btoken);
updateKakaoLogin(btoken,1);
}
return null;
});
}
}
});
부가설명)
- UserApiClient.getInstance().isKakaoTalkLoginAvailable(AuthActivity.this) : 카카오톡으로 로그인 가능한지 여부 확인
- UserApiClient.getInstance().loginWithKakaoTalk : 카카오톡으로 로그인
- UserApiClient.getInstance().loginWithKakaoAccount : 일반 카카오 로그인
5. 프로필 정보 가져오기 : 로그인한 사용자의 프로필 정보를 가져올 수 있습니다.
//프로필 API에 대한 콜백 등록
NidProfileCallback<NidProfileResponse> np_callback = new NidProfileCallback<NidProfileResponse>() {
String TAG = "PROFILE";
@Override
public void onSuccess(NidProfileResponse nidProfileResponse) {
Log.d(TAG, "profile : " + nidProfileResponse.getProfile().getId()); //네이버 서비스ID
Log.d(TAG, "email : " + nidProfileResponse.getProfile().getEmail()); //이메일
Log.d(TAG, "email : " + nidProfileResponse.getProfile().getNickname()); //별명
Log.d(TAG, "mobile : " + nidProfileResponse.getProfile().getMobile()); //전화번호
}
@Override
public void onFailure(int i, @NonNull String s) {
Log.e(TAG, "login error : " + i + "/" + s);
}
@Override
public void onError(int i, @NonNull String s) {
Log.e(TAG, "login error : " + i + "/" + s);
}
};
//프로필 API 호출
NidOAuthLogin nol = new NidOAuthLogin();
nol.callProfileApi(np_callback);
로그인 콜백 성공 시, 프로필 API를 호출하여 프로필 정보를 가져 올 수 있습니다.
○ 프로필 API : UserApiClient.getInstance().me
private void updateKakaoLogin(OAuthToken token, Integer flag){
String TAG = "PROFILE";
UserApiClient.getInstance().me(new Function2<User, Throwable, Unit>() {
@Override
public Unit invoke(User user, Throwable throwable) {
if(flag == 1){
//사용자 동의 항목 체크
//로그인
if(user != null){
List<String> scopes = new ArrayList<>();
Log.d(TAG, "user account : " + user.getKakaoAccount());
if(BooleanUtils.isTrue(user.getKakaoAccount().getEmailNeedsAgreement())){
scopes.add("account_email");
}
if(BooleanUtils.isTrue(user.getKakaoAccount().getPhoneNumberNeedsAgreement())){
scopes.add("phone_number");
}
if(scopes.size() > 0){
Log.d(TAG, "사용자에게 추가 동의 항목을 받기");
getNewScopeProfiles(token, scopes);
}else{
Log.d(TAG, "정보 제공을 하지 않는 사용자에게는 기본 항목만 받기");
// 기존
Log.d(TAG, "id : " + user.getId()); //카카오 서비스 id
Log.d(TAG, "email : " + user.getKakaoAccount().getEmail()); //이메일
Log.d(TAG, "nkname : " + user.getKakaoAccount().getProfile().getNickname()); //별명
Log.d(TAG, "name : " + user.getKakaoAccount().getName()); //이름
Log.d(TAG, "phone info? : " + user.getKakaoAccount().getPhoneNumberNeedsAgreement()); //전화번호필요동의여부
Log.d(TAG, "phone : " + user.getKakaoAccount().getPhoneNumber()); //전화번호
Log.d(TAG, "userTokenScope : " + token.getScopes()); //토큰 범위
finish();
}
}else{
Log.d(TAG, "user not login");
finish();
}
}else{
//로그인
if(user != null){
Log.d(TAG, "정보 제공을 하지 않는 사용자에게는 기본 항목만 받기");
// 기존
Log.d(TAG, "id : " + user.getId());
Log.d(TAG, "email : " + user.getKakaoAccount().getEmail());
Log.d(TAG, "nkname : " + user.getKakaoAccount().getProfile().getNickname());
Log.d(TAG, "name : " + user.getKakaoAccount().getName());
Log.d(TAG, "phone info? : " + user.getKakaoAccount().getPhoneNumberNeedsAgreement());
Log.d(TAG, "phone : " + user.getKakaoAccount().getPhoneNumber());
}else{
Log.d(TAG, "user not login");
}
finish();
}
return null;
}
});
}
추가설명) 프로필 API 호출 시 가져올 수 있는 프로필 정보는
아래와 같이 애플리케이션 설정에서 확인 가능합니다.
※ 검수과정 필요.
6. 추가 항목 동의 받기
private void getNewScopeProfiles(OAuthToken token, List<String> scopes) {
String TAG = "kakaoNewScopes";
UserApiClient.getInstance().loginWithNewScopes(AuthActivity.this, scopes, null, new Function2<OAuthToken, Throwable, Unit>() {
@Override
public Unit invoke(OAuthToken oAuthToken, Throwable throwable) {
if(oAuthToken != null){
updateKakaoLogin(oAuthToken, 2);
}else{
Log.d(TAG, "user not login");
finish();
}
return null;
}
});
}
7. 구현동작 확인.
카카오 로그인 버튼 클릭.
카카오 로그인 화면 진입
애플리케이션 카카오 로그인 처음 진입 시,
동의 팝업 노출
2024.08.27 - [스마트웹앱콘텐츠전문가/안드로이드] - 네이버 로그인 연동(네아로)
2024.08.27 - [스마트웹앱콘텐츠전문가/안드로이드] - 페이스북 로그인 연동
2024.08.28 - [스마트웹앱콘텐츠전문가/안드로이드] - 구글 로그인 연동(with 파이어베이스)