Flutter AndroidManifest.xml 에 대하여

문의 시 사용하시는 SDK 버전 정보와 플랫폼(Android / iOS) 및 디벨로퍼스 앱ID를 알려주세요.


minSdkVersion 21 / Android -flutter로 개발중/ ID 1054732

안녕하세요. flutter로 kakao 로그인을 구현하던 중 오랫동안 해결하지 못했던 이슈를 해결하게 되었는데 이해가 되지 않아 글을 쓰게 되었습니다. 현상은 카카오로그인을 마치면 앱의 로직을 수행하지 않고, 앱이 종료되는 이슈였습니다. 에러는 아래와 같았습니다.

E/AndroidRuntime( 9789): Caused by: java.lang.ClassNotFoundException: Didn’t find class “com.kakao.sdk.auth.AuthCodeHandlerActivity” on path:

android/app/src/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" />
                
                <!-- "kakao${YOUR_NATIVE_APP_KEY}://oauth" 형식의 앱 실행 스킴 설정 -->
                <!-- 카카오 로그인 Redirect URI -->
                <data android:host="oauth" android:scheme="kakao블러" />
            </intent-filter>
        </activity>

변경 후 (잘 작동):

        <activity android:name="com.kakao.sdk.flutter.AuthCodeCustomTabsActivity">
            <intent-filter android:label="flutter_web_auth">
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
            
                <!-- Redirect URI, "kakao${YOUR_NATIVE_APP_KEY}://oauth" 형식 -->
                <data android:scheme="kakao블러" android:host="oauth"/>
            </intent-filter>
        </activity>

로그인 코드는 아래와 같았습니다.

// 카카오 로그인 관련 패키지 import
import 'package:kakao_flutter_sdk/kakao_flutter_sdk.dart';


final _storage = FlutterSecureStorage();

class LoginPage extends StatefulWidget {
  const LoginPage({Key? key}) : super(key: key);

  @override
  _LoginPageState createState() => _LoginPageState();
}

class _LoginPageState extends State<LoginPage> {
  late VideoPlayerController _controller;

  @override
  void initState() {
    super.initState();
    _controller = VideoPlayerController.asset('assets/login.mp4')
      ..initialize().then((_) {
        setState(() {});
      });
    _controller.setLooping(true);
    _controller.play();
  }

  // 카카오 로그인 시작하기 버튼 클릭 시 동작하는 함수
void _loginWithKakao() async {
  try {
    bool isInstalled = await isKakaoTalkInstalled();
    print("KakaoTalk Installed: $isInstalled");

    if (isInstalled) {
      // 카카오톡으로 로그인 시도
      try {
        var token = await UserApi.instance.loginWithKakaoTalk();
        print('카카오톡으로 로그인 성공: ${token.accessToken}');
        await sendTokenToServerAndNavigate(token.accessToken);
      } catch (error) {
        // 카카오톡으로 로그인 시도 실패
        print('카카오톡으로 로그인 실패: $error');
        if (error is PlatformException && error.code == 'CANCELED') {
          return; // 사용자가 로그인을 취소한 경우
        }
        // 카카오 계정으로 로그인 시도
        var token = await UserApi.instance.loginWithKakaoAccount();
        await sendTokenToServerAndNavigate(token.accessToken);
      }
    } else {
      // 카카오 계정으로 로그인 시도
      var token = await UserApi.instance.loginWithKakaoAccount();
      await sendTokenToServerAndNavigate(token.accessToken);
    }
  } catch (error) {
    print('로그인 실패: $error');
    // 로그인 실패 처리 로직
  }
}


// 서버에 토큰을 전송하고, 성공적으로 응답을 받으면 홈 페이지로 이동
Future<void> sendTokenToServerAndNavigate(String token) async {
  User user = await UserApi.instance.me();
  final response = await http.post(
    // Uri.parse('http://127.0.0.1:8000/kakao_login/'),
    Uri.parse('https://블러com/kakao_login/'),
    headers: {
      'Content-Type': 'application/json',
    },
    body: jsonEncode(<String, String>{
      'token': token,
      'kakao_user_id': '${user.id}',
    }),
  );

  if (response.statusCode == 200) {
    var jsonResponse = jsonDecode(response.body);
    var accessToken = jsonResponse['access'];
    var refreshToken = jsonResponse['refresh'];
    var userId = jsonResponse['user_id'];

    await _storage.write(key: 'accessToken', value: accessToken);
    await _storage.write(key: 'refreshToken', value: refreshToken);
    await _storage.write(key: 'userId', value: userId);
    Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (context) => HomePage()));
  } else {
    print('서버로부터 응답을 받는데 실패했습니다: ${response.body}');
    // 여기에 실패 처리 로직을 추가하세요.
  }
}

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: [
          // 배경 동영상
          _controller.value.isInitialized
              ? SizedBox.expand(
                  child: FittedBox(
                    fit: BoxFit.cover,
                    child: SizedBox(
                      width: _controller.value.size.width,
                      height: _controller.value.size.height,
                      child: VideoPlayer(_controller), // 비디오 플레이어
                    ),
                  ),
                )
              : SizedBox.expand(
                  child: FittedBox(
                    fit: BoxFit.cover,
                    child: SizedBox(
                      width: _controller.value.size.width,
                      height: _controller.value.size.height,
                      child: Image.asset('assets/login.png',
블러
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
}

둘의 차이를 모르겠고, 어떤 부분이 원인이었는지 모르겠습니다. 감사합니다.

안녕하세요

변경 전 후로 AndroidManifest.xml에 등록하신 activity의 android:name이 다르기 때문에 에러가 발생한 것으로 보입니다.

kakao_flutter_sdk에서는 내부적으로 com.kakao.sdk.flutter.AuthCodeCustomTabsActivity를 사용하고 있고, 변경 전에 등록하신 com.kakao.sdk.auth.AuthCodeHandlerActivity는 안드로이드용 Kakao SDK에서 사용하고 있는 Activity입니다.

1개의 좋아요

그 둘의 차이를 모르겠습니다 ㅠ
변경 전에 등록한거는 플러터에서 쓰는게 아닌가요?

변경 전에 등록한 Activity는 안드로이드용 카카오SDK (플러터에서의 안드로이드를 의미하는 것이 아닙니다)에서 사용하는 Activity 이고, kakao_flutter_sdk에서는 사용하지 않고 있어요.

참고)
안드로이드 SDK 가이드

플러터 SDK 가이드

1개의 좋아요

아하. 제가 com.kakao.sdk.auth.AuthCodeHandlerActivity를 블로그에서 가져왓는데 그게 플러터의 안드로이드에 쓰이는게 아니었군요. 플러터에서의 안드로이드는 com.kakao.sdk.flutter.AuthCodeCustomTabsActivity 이걸 쓰는게 맞는거군요. 혹시 제 이해가 맞을까요?

1개의 좋아요

네네 이해하신게 맞습니다~

1개의 좋아요

감사합니다. 모두 확인했습니다!!

1개의 좋아요