일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- StatefulWidget
- BottomNavigationBar
- dart
- 변수
- 정보처리기사
- firebase
- go_router
- java
- setState
- Kotlin
- UserAccountsDrawerHeader
- Null Safety
- 로그인
- 1과목
- 상태관리
- flutter
- 안드로이드
- non-nullable
- IOS
- GetX
- 함수
- Android
- 이메일
- swift
- firebase_auth
- Provider
- 회원가입
- 안드로이드 스튜디오
- auth
- Cocoa touch Framework
- Today
- Total
앱 개발 공부방
안드로이드 스튜디오-카카오톡 로그인 버튼 생성 및 클릭 이벤트 본문
저번 글에서 카카오 개발자 사이트에다 앱을 등록하고 설정을 마쳤습니다.
혹시 카카오 개발자 사이트에 앱을 등록하지 않았다면 정상 동작하지 않으니 들어가서 앱 등록부터 해주시기 바랍니다.
https://cpcp127.tistory.com/12
먼저 프로젝트를 만들 때 카카오 로그인 api는 SDK 버전 4.0(아이스크림 샌드위치) 이상이어야 정상 작동하므로 설정을 해줍니다.
카카오 로그인 기능을 수행하기위해서 API를 사용합니다
처음으로는 인터넷 권한을 설정하기위해 아래 코드를 manifests에 넣어줍니다
<uses-permission android:name="android.permission.INTERNET" />
다음으로 Gradle Scripts에서 build.gradle(Project)에서 아래 코드를 추가해줍니다
allprojects {
repositories {
google()
jcenter()
mavenCentral()
maven { url 'http://devrepo.kakao.com:8088/nexus/content/groups/public/' }
}
}
두 번째로 build.gradle(Module: app)에 dependencies에 아래 코드를 추가하고 sync now를 클릭합니다
implementation 'com.kakao.sdk:usermgmt:1.27.0'
1.27.0은 2020년 2월 15일 기준 가장 최신 버전입니다. 확인을 하시고 넣으셔야 합니다
다음으로는 res-values->strings.xml에서 카카오 개발자 사이트에서 확인하신 네이티브 앱 키를 아래 코드처럼 입력합니다.
<string name="kakao_app_key">네이티브 앱키</string>
이제 xml로 가셔서 아래 코드처럼 넣으시면 xml상에 카카오톡 로그인 버튼이 생성됩니다.
<com.kakao.usermgmt.LoginButton
android:layout_width="match_parent"
android:layout_height="match_parent">
</com.kakao.usermgmt.LoginButton>
다음으로 카카오 로그인 api를 정상적으로 사용하려면 Application을 상속받은 class를 만들어야 합니다
App.java
public class App extends Application {
private static volatile App instance = null;
private static class KakaoSDKAdapter extends KakaoAdapter {
// 카카오 로그인 세션을 불러올 때의 설정값을 설정하는 부분.
public ISessionConfig getSessionConfig() {
return new ISessionConfig() {
@Override
public AuthType[] getAuthTypes() {
return new AuthType[] {AuthType.KAKAO_LOGIN_ALL};
//로그인을 어떤 방식으로 할지 지정
//KAKAO_LOGIN_ALL: 모든 로그인방식을 사용하고 싶을때 지정.
}
@Override
public boolean isUsingWebviewTimer() {
return false;
// SDK 로그인시 사용되는 WebView에서 pause와 resume시에 Timer를 설정하여 CPU소모를 절약한다.
// true 를 리턴할경우 webview로그인을 사용하는 화면서 모든 webview에 onPause와 onResume 시에 Timer를 설정해 주어야 한다.
// 지정하지 않을 시 false로 설정된다.
}
@Override
public boolean isSecureMode() {
return false;
// 로그인시 access token과 refresh token을 저장할 때의 암호화 여부를 결정한다.
}
@Override
public ApprovalType getApprovalType() {
return ApprovalType.INDIVIDUAL;
// 일반 사용자가 아닌 Kakao와 제휴된 앱에서만 사용되는 값으로, 값을 채워주지 않을경우 ApprovalType.INDIVIDUAL 값을 사용하게 된다.
}
@Override
public boolean isSaveFormData() {
return true;
// Kakao SDK 에서 사용되는 WebView에서 email 입력폼의 데이터를 저장할지 여부를 결정한다.
// true일 경우, 다음번에 다시 로그인 시 email 폼을 누르면 이전에 입력했던 이메일이 나타난다.
}
};
}
@Override
public IApplicationConfig getApplicationConfig() {
return new IApplicationConfig() {
@Override
public Context getApplicationContext() {
return App.getGlobalApplicationContext();
}
};
}
}
public static App getGlobalApplicationContext() {
if(instance == null) {
throw new IllegalStateException("this application does not inherit com.kakao.GlobalApplication");
}
return instance;
}
@Override
public void onCreate() {
super.onCreate();
instance = this;
KakaoSDK.init(new KakaoSDKAdapter());
}
@Override
public void onTerminate() {
super.onTerminate();
instance = null;
}
}
위 링크로 들어가시면 위 소스코드 들에 쓰인 속성 값들에 대한 설명이 있습니다
다른 설정을 하실 분들은 참고하시면 됩니다.
다음으로 manifests에 가서 application태그 안에 아래 코드를 추가합니다
android:name="App"
다음으로 로그인 화면인 MainActivity.java 코드를 보시겠습니다
MainActivity.java
package com.example.variouslogin;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
import android.os.Bundle;
import android.util.Base64;
import android.util.Log;
import android.widget.Toast;
import com.kakao.auth.ApiErrorCode;
import com.kakao.auth.ISessionCallback;
import com.kakao.auth.Session;
import com.kakao.network.ErrorResult;
import com.kakao.usermgmt.UserManagement;
import com.kakao.usermgmt.callback.MeV2ResponseCallback;
import com.kakao.usermgmt.response.MeV2Response;
import com.kakao.util.OptionalBoolean;
import com.kakao.util.exception.KakaoException;
import java.security.MessageDigest;
public class MainActivity extends AppCompatActivity {
private SessionCallback sessionCallback;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sessionCallback = new SessionCallback();
Session.getCurrentSession().addCallback(sessionCallback);
Session.getCurrentSession().checkAndImplicitOpen();
getAppKeyHash();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(Session.getCurrentSession().handleActivityResult(requestCode, resultCode, data)) {
super.onActivityResult(requestCode, resultCode, data);
return;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
Session.getCurrentSession().removeCallback(sessionCallback);
}
private class SessionCallback implements ISessionCallback {
@Override
public void onSessionOpened() {
UserManagement.getInstance().me(new MeV2ResponseCallback() {
@Override
public void onFailure(ErrorResult errorResult) {
int result = errorResult.getErrorCode();
if(result == ApiErrorCode.CLIENT_ERROR_CODE) {
Toast.makeText(getApplicationContext(), "네트워크 연결이 불안정합니다. 다시 시도해 주세요.", Toast.LENGTH_SHORT).show();
finish();
} else {
Toast.makeText(getApplicationContext(),"로그인 도중 오류가 발생했습니다: "+errorResult.getErrorMessage(),Toast.LENGTH_SHORT).show();
}
}
@Override
public void onSessionClosed(ErrorResult errorResult) {
Toast.makeText(getApplicationContext(),"세션이 닫혔습니다. 다시 시도해 주세요: "+errorResult.getErrorMessage(),Toast.LENGTH_SHORT).show();
}
@Override
public void onSuccess(MeV2Response result) {
Intent intent = new Intent(getApplicationContext(), Main2Activity.class);
intent.putExtra("name", result.getNickname());
intent.putExtra("profile", result.getProfileImagePath());
if(result.getKakaoAccount().hasEmail() == OptionalBoolean.TRUE)
intent.putExtra("email", result.getKakaoAccount().getEmail());
else
intent.putExtra("email", "none");
if(result.getKakaoAccount().hasGender() == OptionalBoolean.TRUE)
intent.putExtra("gender", result.getKakaoAccount().getGender().getValue());
else
intent.putExtra("gender", "none");
startActivity(intent);
finish();
}
});
}
@Override
public void onSessionOpenFailed(KakaoException e) {
Toast.makeText(getApplicationContext(), "로그인 도중 오류가 발생했습니다. 인터넷 연결을 확인해주세요: "+e.toString(), Toast.LENGTH_SHORT).show();
}
}
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.e("Hash key", something);
}
} catch (Exception e) {
// TODO Auto-generated catch block
Log.e("name not found", e.toString());
}
}
}
위 코드에서 핵심은 SessionCallback부분입니다.
https://m.blog.naver.com/woo171tm/221461720960
저도 여기 블로그에서 보고 배운 거라서 SessionCallback부분의 자세한 설명이 있으니 궁금하신 분들은 확인해 주세요
로그인 성공 시 다음 화면인 Main2 Activity를 만들겠습니다
xml은
이런 식이고 코드는 아래와 같습니다
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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=".Main2Activity">
<ImageView
android:id="@+id/ivProfile"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginTop="10dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="25dp"
android:layout_marginTop="10dp"
android:textSize="20sp"
android:text="닉네임: "
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/ivProfile"/>
<TextView
android:id="@+id/tvNickname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:textSize="20sp"
android:text="..."
app:layout_constraintStart_toEndOf="@+id/textView"
app:layout_constraintTop_toTopOf="@+id/textView" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="25dp"
android:layout_marginTop="15dp"
android:textSize="16sp"
android:text="이메일: "
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView"/>
<TextView
android:id="@+id/tvEmail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:textSize="16sp"
android:text="..."
app:layout_constraintStart_toEndOf="@+id/textView2"
app:layout_constraintTop_toTopOf="@+id/textView2" />
<TextView
android:id="@+id/textView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="성별: "
android:textSize="16sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.067"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView2" />
<TextView
android:id="@+id/tvGender"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:text="..."
android:textSize="16sp"
app:layout_constraintStart_toEndOf="@+id/textView4"
app:layout_constraintTop_toTopOf="@+id/textView4" />
<Button
android:id="@+id/btnLogout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="100dp"
android:text="로그아웃"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
main에서 프로필 사진은 string형태로 url을 받아오는데 사진으로 보여주기 위하여 아래처럼 추가합니다
build.gradle(Module~)로 들어가셔서 dependencies에다 아래 코드를 추가해줍니다
implementation 'com.github.bumptech.glide:glide:4.8.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.8.0'
다음으로 Main2 Activity.java입니다
package com.example.variouslogin;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.bumptech.glide.Glide;
import com.kakao.usermgmt.UserManagement;
import com.kakao.usermgmt.callback.LogoutResponseCallback;
public class Main2Activity extends AppCompatActivity {
String strNickname, strProfile, strEmail, strGender;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
TextView tvNickname = findViewById(R.id.tvNickname);
ImageView ivProfile = findViewById(R.id.ivProfile);
TextView tvEmail = findViewById(R.id.tvEmail);
TextView tvGender = findViewById(R.id.tvGender);
Button btnLogout = findViewById(R.id.btnLogout);
Intent intent = getIntent();
strNickname = intent.getStringExtra("name");
strProfile = intent.getStringExtra("profile");
strEmail = intent.getStringExtra("email");
strGender = intent.getStringExtra("gender");
tvNickname.setText(strNickname);
tvEmail.setText(strEmail);
tvGender.setText(strGender);
Glide.with(this).load(strProfile).into(ivProfile); //프로필 사진 url을 사진으로 보여줌
btnLogout.setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(), "정상적으로 로그아웃되었습니다.", Toast.LENGTH_SHORT).show();
UserManagement.getInstance().requestLogout(new LogoutResponseCallback() {
@Override
public void onCompleteLogout() {
Intent intent = new Intent(Main2Activity.this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
}
});
}
});
}
}
이로써 간단한 카카오톡 로그인 및 로그아웃, 정보 받아오기를 했습니다
다음에는 다른 sns 로그인 방법도 올리도록 하겠습니다.
'Android-java' 카테고리의 다른 글
안드로이드 스튜디오-공공 데이터 API사용하기 (4) | 2020.03.07 |
---|---|
안드로이드 스튜디오-음성인식 사용하기 (6) | 2020.03.07 |
안드로이드 스튜디오-카카오톡 로그인 구현하기(카카오 개발자에 앱 등록 및 설정) (0) | 2020.02.15 |
안드로이드 스튜디오-SNS로그인 기능 구현시 필요한 해시 키 값 구하기 (1) | 2020.02.15 |
안드로이드 스튜디오-로그인 회원가입2 (5) | 2020.02.13 |