안드로이드 웹뷰 카카오톡 로그인 - andeuloideu webbyu kakaotog logeu-in

하이브리드 앱 테스트 환경에서 카톡로그인 intent 처리

Mobile App/Android 2021. 5. 24. 19:36

SMALL

카톡로그인 인텐트를 아래와 같이 처리해줬다.

@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
  if (url.startsWith("intent:")) {
    try {
        Intent intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
        Intent existPackage = getPackageManager().getLaunchIntentForPackage(intent.getPackage());
        if (existPackage!=null) {
        	startActivity(intent);
        } else {
        	Intent marketIntent = new Intent(Intent.ACTION_VIEW);
        	marketIntent.setData(Uri.parse("market://details?id=" + intent.getPackage()));
        }
      return true;
    } catch (Exception e) {
    	e.printStackTrace();
    }
  } 
  else {
  	view.loadUrl(url);
  }
  return true;
}

실사용에서는 참 편하지만 테스트할 때 만큼은 정말 불편하다.

특히 여러대의 테스트기기로 로그인을 해야하는데..
현재 개발중인 서비스는 카톡로그인 외의 로그인방법이 존재하지 않는다.

 

방법이 없을까 고민하다가 Extra를 자세히 보니 브라우저에서 로드되는 URL이 있어서 아래와 같이 처리해줬다.

  @Override
  public boolean shouldOverrideUrlLoading(WebView view, String url) {
    Log.d("MainIntent URL", url);
    if (url.startsWith("intent:")) {
    	try {
    		Intent intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
    		Intent existPackage = getPackageManager().getLaunchIntentForPackage(intent.getPackage());
    		if (existPackage!=null) {
    			startActivity(intent);
    		} else {
    			Intent marketIntent = new Intent(Intent.ACTION_VIEW);
    			marketIntent.setData(Uri.parse("market://details?id=" + intent.getPackage()));
    		}
    		return true;
    	} catch (Exception e) {
        	try{
            	Intent intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);

                if(intent.getAction().contains("kakao")){
                	view.loadUrl(intent.getStringExtra("browser_fallback_url"));
                }
                else {
                    Intent marketIntent = new Intent(Intent.ACTION_VIEW);
                    marketIntent.setData(Uri.parse("market://details?id=" + intent.getPackage()));
                }
            }
            catch (Exception ex){
                ex.printStackTrace();
            }
      	}
    } 
    else {
      view.loadUrl(url);
    }
    return true;
  }

 

이제 카톡이 깔려있지 않아도 카카오 계정으로 사용이 가능하다.

 

안드로이드 웹뷰 카카오톡 로그인 - andeuloideu webbyu kakaotog logeu-in

BIG

공유하기

게시글 관리

구독하기Jade's Hello, World!

저작자표시 비영리

'Mobile App > Android' 카테고리의 다른 글

[Gradle] 안드로이드 빌드 버전 자동으로 관리하기  (1)2021.12.14Cross-App Scripting Reject 해결방법  (4)2021.09.12안드로이드 웹뷰 뒤로가기 버튼 이벤트 만들기  (1)2021.05.12안드로이드 웹뷰 사용 및 설정, SSL 무시  (0)2021.05.12안드로이드 하단 메뉴바 활용하기  (0)2021.05.02

관련글 관련글 더보기

  • [Gradle] 안드로이드 빌드 버전 자동으로 관리하기
  • Cross-App Scripting Reject 해결방법
  • 안드로이드 웹뷰 뒤로가기 버튼 이벤트 만들기
  • 안드로이드 웹뷰 사용 및 설정, SSL 무시

댓글 0

댓글 접기 댓글 펼치기

이전 댓글 더보기

비밀글

등록

Kakao SDK를 사용하기 위해서는 초기화를 해줘야 합니다. 초기화는 GlobalApplication 공유 클래스를 만들어 앱 수준에서 관리하도록 하겠습니다. kakaoSDKAdapter클래스는 KakaoAdapter를 상속받습니다.

 

GlobalApplication.java

public class GlobalApplication extends Application {
    private static GlobalApplication instance;

    @Override
    public void onCreate() {
        super.onCreate();
        instance = this;

        // Kakao Sdk 초기화
        KakaoSDK.init(new KakaoSDKAdapter());
    }

    @Override
    public void onTerminate() {
        super.onTerminate();
        instance = null;
    }

    public static Application getInstance(){
        if (instance == null){
            throw new IllegalStateException("this app illegal state");
        }
        return instance;
    }

    public class KakaoSDKAdapter extends KakaoAdapter {

        @Override
        public ISessionConfig getSessionConfig() {
            return new ISessionConfig() {
                @Override
                public AuthType[] getAuthTypes() {
                    // Kakao SDK로그인을 하는 방식에 대한 Enum class (카카오톡 앱 + 카카오 스토리 + 웹뷰 다이어로그 포함)
                    return new AuthType[] {AuthType.KAKAO_LOGIN_ALL};
                }

                @Override
                public boolean isUsingWebviewTimer() {
                    return false;
                }

                @Override
                public boolean isSecureMode() {
                    return false;
                }

                @Nullable
                @Override
                public ApprovalType getApprovalType() {
                    return ApprovalType.INDIVIDUAL;

                }

                @Override
                public boolean isSaveFormData() {
                    return true;
                }
            };
        }

        @Override
        public IApplicationConfig getApplicationConfig() {
            return GlobalApplication::getInstance;
        }
    }
}

 

AuthType

Kakao SDK로그인을 하는 방식에 대한 Enum class

 

KAKAO_TALK0kakaotalk으로 login을 하고 싶을때 지정.KAKAO_STORY1kakaostory으로 login을 하고 싶을때 지정.KAKAO_ACCOUNT2웹뷰 Dialog를 통해 카카오 계정연결을 제공하고 싶을경우 지정.KAKAO_TALK_EXCLUDE_NATIVE_LOGIN3카카오톡으로만 로그인을 유도하고 싶으면서 계정이 없을때 계정생성을 위한 버튼도 같이 제공을 하고 싶다면 지정.
KAKAO_TALK과 중복 지정불가.KAKAO_LOGIN_ALL4모든 로그인 방식을 사용하고 싶을 때 지정.

 

manifests.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.lakue.kakaologinsample">
    <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">
        <meta-data
            android:name="com.kakao.sdk.AppKey"
            android:value="@string/kakao_app_key" />
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

인터넷을 사용하기 위해 <uses-permission android:name="android.permission.INTERNET" /> 를 넣어줘야 하고,

카카오에서 받아온 앱 키를 설정할 메타데이터를 넣어줘야 합니다.

 

activity_main.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=".MainActivity">


    <Button
        android:id="@+id/loginV1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="328dp"
        android:text="카카오 로그인 v1"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.734" />

    <Button
        android:id="@+id/logout"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="로그아웃"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.498"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.636" />
</androidx.constraintlayout.widget.ConstraintLayout>

 

 

MainActivity.java

로그인 버튼을 클릭하면 로그인 요청,

로그아웃 클릭 시 로그아웃 요청 및 사용자의 세션을 제거하도록 했습니다.

public class MainActivity extends AppCompatActivity {
    private Button loginV1, logout;
    private SessionCallback sessionCallback = new SessionCallback();
    Session session;
    private static final String TAG = "MainActivity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        loginV1 = findViewById(R.id.loginV1);
        logout = findViewById(R.id.logout);


        session = Session.getCurrentSession();
        session.addCallback(sessionCallback);

        loginV1.setOnClickListener(v -> {
            if (Session.getCurrentSession().checkAndImplicitOpen()) {
                Log.d(TAG, "onClick: 로그인 세션살아있음");
                // 카카오 로그인 시도 (창이 안뜬다.)
                sessionCallback.requestMe();
            } else {
                Log.d(TAG, "onClick: 로그인 세션끝남");
                // 카카오 로그인 시도 (창이 뜬다.)
                session.open(AuthType.KAKAO_LOGIN_ALL, MainActivity.this);
            }
        });

        logout.setOnClickListener(v -> {
            Log.d(TAG, "onCreate:click ");
            UserManagement.getInstance()
                    .requestLogout(new LogoutResponseCallback() {
                        @Override
                        public void onSessionClosed(ErrorResult errorResult) {
                            super.onSessionClosed(errorResult);
                            Log.d(TAG, "onSessionClosed: "+errorResult.getErrorMessage());

                        }
                        @Override
                        public void onCompleteLogout() {
                            if (sessionCallback != null) {
                                Session.getCurrentSession().removeCallback(sessionCallback);
                            }
                            Log.d(TAG, "onCompleteLogout:logout ");
                        }
                    });
        });

        // 카카오 개발자 홈페이지에 등록할 해시키 구하기
//        getHashKey();
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();

        // 세션 콜백 삭제
        Session.getCurrentSession().removeCallback(sessionCallback);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        // 카카오톡|스토리 간편로그인 실행 결과를 받아서 SDK로 전달
        if (Session.getCurrentSession().handleActivityResult(requestCode, resultCode, data)) {
            return;
        }

        super.onActivityResult(requestCode, resultCode, data);
    }
}

 

 

SessionCallback.java

 이제 로그인 결과 값을 전달받기 위한 Callback클래스를 구현하겠습니다.

public class SessionCallback implements ISessionCallback {

    // 로그인에 성공한 상태
    @Override
    public void onSessionOpened() {
        requestMe();
    }

    // 로그인에 실패한 상태
    @Override
    public void onSessionOpenFailed(KakaoException exception) {
        Log.e("SessionCallback :: ", "onSessionOpenFailed : " + exception.getMessage());
    }

    // 사용자 정보 요청
    public void requestMe() {
        UserManagement.getInstance()
                .me(new MeV2ResponseCallback() {
                    @Override
                    public void onSessionClosed(ErrorResult errorResult) {
                        Log.e("KAKAO_API", "세션이 닫혀 있음: " + errorResult);
                    }

                    @Override
                    public void onFailure(ErrorResult errorResult) {
                        Log.e("KAKAO_API", "사용자 정보 요청 실패: " + errorResult);
                    }

                    @Override
                    public void onSuccess(MeV2Response result) {
                        Log.i("KAKAO_API", "사용자 아이디: " + result.getId());
                        String id = String.valueOf(result.getId());
                        UserAccount kakaoAccount = result.getKakaoAccount();
                        if (kakaoAccount != null) {

                            // 이메일
                            String email = kakaoAccount.getEmail();
                            Profile profile = kakaoAccount.getProfile();
                            if (profile ==null){
                                Log.d("KAKAO_API", "onSuccess:profile null ");
                            }else{
                                Log.d("KAKAO_API", "onSuccess:getProfileImageUrl "+profile.getProfileImageUrl());
                                Log.d("KAKAO_API", "onSuccess:getNickname "+profile.getNickname());
                            }
                            if (email != null) {

                                Log.d("KAKAO_API", "onSuccess:email "+email);
                            } 

                            // 프로필
                            Profile _profile = kakaoAccount.getProfile();

                            if (_profile != null) {

                                Log.d("KAKAO_API", "nickname: " + _profile.getNickname());
                                Log.d("KAKAO_API", "profile image: " + _profile.getProfileImageUrl());
                                Log.d("KAKAO_API", "thumbnail image: " + _profile.getThumbnailImageUrl());

                            } else if (kakaoAccount.profileNeedsAgreement() == OptionalBoolean.TRUE) {
                                // 동의 요청 후 프로필 정보 획득 가능

                            } else {
                                // 프로필 획득 불가
                            }
                        }else{
                            Log.i("KAKAO_API", "onSuccess: kakaoAccount null");
                        }
                    }
                });

    }
}

 

이대로 앱을 실행하면 카카오 로그인이 정상적으로 됩니다.

로그인 버튼 클릭 시 카카로 로그인 웹페이지에 해당하는 웹뷰가 나타납니다.

카카오 계정으로 로그인 하면 앱에서 설정했던 정보 이용에 대한 동의를 받습니다.

안드로이드 웹뷰 카카오톡 로그인 - andeuloideu webbyu kakaotog logeu-in
안드로이드 웹뷰 카카오톡 로그인 - andeuloideu webbyu kakaotog logeu-in

 

다음까지 마치면 앱에서 사용자에 대한 정보를 받은 것을 확인할 수 있습니다.

마찬가지로 로그아웃까지 처리 가능합니다.

안드로이드 웹뷰 카카오톡 로그인 - andeuloideu webbyu kakaotog logeu-in
안드로이드 웹뷰 카카오톡 로그인 - andeuloideu webbyu kakaotog logeu-in

 

전체 소스코드는 깃허브에서 확인할 수 있습니다.

github.com/keepseung/Android-Blog-Source

 

keepseung/Android-Blog-Source

https://develop-writing.tistory.com/ 에서 제공하는 예제. Contribute to keepseung/Android-Blog-Source development by creating an account on GitHub.