kakao / kakao_flutter_sdk

Flutter SDK for Kakao Open API
Apache License 2.0
193 stars 70 forks source link

카카오 링크 클릭시 파라미터를 어떻게 받아오나요? #114

Closed Benife closed 2 years ago

Benife commented 2 years ago

안녕하세요. flutter로 카카오링크 구현중입니다.

flutter 로 카카오 링크 구현후 "앱으로보기" 클릭하면 정보가 넘어오도록 androidExecParams 을 설정을 아래와 같이 설정했습니다.

"taleID=100&rId=5&rTitle=제목"

클릭했을때 저정보를 어떻게 얻어오나요?

Android Native에서는 OnResume에서 얻어오면 됬는데 Flutter에서는 어떻게 얻어오나요?

class MainActivity: FlutterActivity() 에 OnResume에서 아무리 해도 값이 안넘어와서요.

제가 참고할만한 예제나 문서가 있을까요?

mbkim95 commented 2 years ago

안녕하세요

사용하고 계신 버전을 알 수 없어서 최신 버전(0.9.0)을 기준으로 간단한 샘플 코드 첨부하니 참고 부탁드려요.

main.dart

import 'package:flutter/material.dart';
import 'package:kakao_flutter_sdk/link.dart';
import 'package:kakao_flutter_sdk/template.dart';

// 샘플 탬플릿
final defaultCommerce = CommerceTemplate(
  Content(
      "Ivory long dress (4 Color)",
      Uri.parse(
          "http://mud-kage.kakao.co.kr/dn/RY8ZN/btqgOGzITp3/uCM1x2xu7GNfr7NS9QvEs0/kakaolink40_original.png"),
      Link(
          webUrl: Uri.parse("https://developers.kakao.com"),
          mobileWebUrl: Uri.parse("https://developers.kakao.com"))),
  Commerce(208800,
      discountPrice: 146160,
      discountRate: 30,
      productName: "Ivory long dress",
      currencyUnit: "₩",
      currencyUnitPosition: 1),
  buttons: [
    Button(
        "구매하기",
        Link(
            webUrl: Uri.parse("https://developers.kakao.com"),
            mobileWebUrl: Uri.parse("https://developers.kakao.com"))),
    Button(
      "공유하기",
      Link(
        androidExecutionParams: {"key1": "value1", "key2": "value2"},
        iosExecutionParams: {"key1": "value1", "key2": "value2"},
      ),
    )
  ],
);

void main() {
  // 앱 키 등록
  KakaoContext.clientId = '${YOUR_NATIVE_APP_KEY}';
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Kakao Link Sample',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Kakao Link Sample'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _sendKakaoLink() async {
    try {
      // 탬플릿 설정
      final template = defaultCommerce;
      final isTalkInstalled = await isKakaoTalkInstalled();
      if (isTalkInstalled) {
        // 카카오톡으로 메시지 전송
        var uri = await LinkClient.instance.defaultWithTalk(template);
        await LinkClient.instance.launchKakaoTalk(uri);
      } else {
        // 웹브라우저로 메시지 전송
        var uri = await LinkClient.instance.defaultWithWeb(template);
        await launchBrowserTab(uri);
      }
    } catch (e) {
      print(e.toString());
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: ElevatedButton(
          child: const Text('Send Kakao Link'),
          onPressed: _sendKakaoLink,
        ),
      ),
    );
  }
}

AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.kakao_link_sample">

    <application
        android:icon="@mipmap/ic_launcher"
        android:label="kakao_link_sample">
        <activity
            android:name=".MainActivity"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:launchMode="singleTop"
            android:theme="@style/LaunchTheme"
            android:windowSoftInputMode="adjustResize">
            <!-- Specifies an Android theme to apply to this Activity as soon as
                 the Android process has started. This theme is visible to the user
                 while the Flutter UI initializes. After that, this theme continues
                 to determine the Window background behind the Flutter UI. -->
            <meta-data
                android:name="io.flutter.embedding.android.NormalTheme"
                android:resource="@style/NormalTheme" />
            <!-- Displays an Android View that continues showing the launch screen
                 Drawable until Flutter paints its first frame, then this splash
                 screen fades out. A splash screen is useful to avoid any visual
                 gap between the end of Android's launch screen and the painting of
                 Flutter's first frame. -->
            <meta-data
                android:name="io.flutter.embedding.android.SplashScreenDrawable"
                android:resource="@drawable/launch_background" />

            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>

            <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}://kakaolink" 형식의 앱 실행 스킴을 설정하는데 사용 -->
                <data
                    android:host="kakaolink"
                    android:scheme="kakao${YOUR_NATIVE_APP_KEY}" />
            </intent-filter>
        </activity>
        <!-- Don't delete the meta-data below.
             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
        <meta-data
            android:name="flutterEmbedding"
            android:value="2" />
    </application>
</manifest>

MainActivity.kt

package com.example.kakao_link_sample

import android.widget.Toast
import io.flutter.embedding.android.FlutterActivity

class MainActivity : FlutterActivity() {
    override fun onResume() {
        super.onResume()

        intent.data?.let { uri ->
            // 공유 시 전달한 파라미터
            val executionParams = mutableMapOf<String, String>()

            uri.queryParameterNames.forEach { key ->
                executionParams[key] = uri.getQueryParameter(key)!!
            }

            Toast.makeText(this, "$executionParams", Toast.LENGTH_SHORT).show()
        }
    }
}
HyeonKayh commented 2 years ago

안녕하세요

답변해주신대로 작업하니 resume 시에 intent를 가져오기는 하는데 앱이 완전히 종료되고 나서 다시 실행시킬때만 intent가 업데이트 되는것으로 보입니다. 보내주신 샘플코드로 앱을 따로 구성해서 테스트를 해봤는데도 똑같이 작동하네요...

증상을 정리해보자면

  1. 공유링크를 카카오톡 메세지로 보내는것은 정상적으로 됩니다.
  2. 앱 실행중에 공유링크를 눌러서 앱이 resume 되는 경우 intent정보를 가져오지 못합니다.
  3. 앱 종료 후 공유링크를 눌러 앱이 다시 실행될때 intent 정보가 들어와서 Toast가 출력됩니다.
  4. 이후 다시 앱을 resume 시키면 앞서 공유링크를 통해 전달되었던 intent 정보가 Toast로 출력됩니다.

kotlin 코드에 익숙하지 않아서 검색하면서 해봐도 해결이 잘 안되네요.. 제가 놓치고 있는 부분이 있는지 궁금해서 다시한번 질문드립니다!

kakao_flutter_sdk 버전은 0.9.0을 사용중이구요 flutter 환경은 다음과 같습니다.

C:\Users\admin>flutter doctor -v
[√] Flutter (Channel stable, 2.5.3, on Microsoft Windows [Version 10.0.19043.1288], locale ko-KR)
    • Flutter version 2.5.3 at D:\Program Files\flutter2.5\flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 18116933e7 (10 weeks ago), 2021-10-15 10:46:35 -0700
    • Engine revision 6ac856380f
    • Dart version 2.14.3

[!] Android toolchain - develop for Android devices (Android SDK version 29.0.3)
    • Android SDK at C:\Users\admin\AppData\Local\Android\sdk
    • Platform android-31, build-tools 29.0.3
    • Java binary at: C:\Users\admin\Downloads\android-studio\jre\bin\java
    • Java version OpenJDK Runtime Environment (build 11.0.11+9-b60-7590822)
    ! Some Android licenses not accepted.  To resolve this, run: flutter doctor --android-licenses

[√] Chrome - develop for the web
    • Chrome at C:\Program Files (x86)\Google\Chrome\Application\chrome.exe

[√] Android Studio (version 4.1)
    • Android Studio at C:\Program Files\Android\Android Studio
    • Flutter plugin can be installed from:
       https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
       https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b01)

[√] Android Studio (version 2021.1)
    • Android Studio at C:\Users\admin\Downloads\android-studio
    • Flutter plugin can be installed from:
       https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
       https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.11+9-b60-7590822)

[√] Connected device (3 available)
    • SM N960N (mobile) • 27f4447a10057ece • android-arm64  • Android 10 (API 29)
    • Chrome (web)      • chrome           • web-javascript • Google Chrome 96.0.4664.93
    • Edge (web)        • edge             • web-javascript • Microsoft Edge 96.0.1054.62

! Doctor found issues in 1 category.
mbkim95 commented 2 years ago

@HyeonKayh

안녕하세요

문의주신 내용에 대해서 해당 현상은 안드로이드 프레임워크의 동작 방식에 의해 발생하는 것으로 보이네요.

제가 위에 드린 샘플과 아래의 샘플은 단순히 카카오링크로 넘겨준 파라미터를 앱에서 받는 방법에 대한 가이드이기 때문에 실제로 개발하는 상황에 따라서 코드가 달라질 수 있다는점 양해 부탁드리고, 아래의 샘플 코드와 같이 구현하시면 증상이 해결될 것 같아요.

감사합니다.

package com.example.kakao_link_sample

import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.widget.Toast
import io.flutter.embedding.android.FlutterActivity

class MainActivity : FlutterActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        intent.data?.let {
            parseKakaoLink(it)
        }
    }

    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)

        intent.data?.let {
            parseKakaoLink(it)
        }
    }

    // 카카오링크 파라미터 파싱
    private fun parseKakaoLink(uri: Uri) {
        // 공유 시 전달한 파라미터
        val executionParams = mutableMapOf<String, String>()

        uri.queryParameterNames.forEach { key ->
            executionParams[key] = uri.getQueryParameter(key)!!
        }

        Toast.makeText(this, "$executionParams", Toast.LENGTH_SHORT).show()
    }
}
HyeonKayh commented 2 years ago

안녕하세요.

답변해주신 샘플 코드로 다시 테스트해보니 아주 잘됩니다!!!

감사합니다.

github-actions[bot] commented 2 years ago

Stale issue message