안녕하세요. 하이브리드앱에서 카톡 공유 메세지 클릭시 앱이 설치됐음에도 구글플레이가 실행되는 문제를 겪고있습니다!

앱ID 1086991

nextjs, react-native 환경이고 앱은 구글플레이를 통해 베타테스트를 배포해둔 상태입니다.
공유 메세지 클릭시 앱을 실행시키기 위한 설정 과 관련 로직은 구현이 되어있습니다.
ios에서는 카톡 공유 메세지 클릭시 앱이 실행되고 원하는 페이지로 이동까지 잘 되고 있습니다. 문제는 제목과 같이 안드로이드에서는 메세지 클릭시 앱이 설치됐음에도 구글플레이가 실행되며 앱설치 화면으로 넘어갑니다. 이미 설치되어있기 때문에 열기 버튼이 존재하고 열기 버튼을 누르면 앱이 실행됩니다…

react-native의 app.json에서 android 설정은 아래와 같습니다.

{
  "expo": {
    "android": {
      "exported": true,
      "permissions": [
        "android.permission.INTERNET",
      ],
      "intentFilters": [
        {
          "action": "VIEW",
          "autoVerify": true,
          "data": [
            {
              "scheme": "https",
              "host": "web.development.example.im",
              "pathPrefix": "/example"
            },
            {
              "scheme": "kakao${테스트 어플리케이션의 네이티브 앱 키}”,
              "host": "kakaolink"
            },
            {
              "scheme": "kakao${실제 어플리케이션의 네이티브 앱 키}",
              "host": "kakaolink"
            }
          ],
          "category": ["BROWSABLE", "DEFAULT"]
        }
      ],
      "package": "com.nation.app.example",
      "queries": {
        "packages": ["com.kakao.talk"]
      }
    },
  }
}

react-native에서 android intent uri를 다음과 같이 처리하고 있습니다. 아래 로직을 통해 카카오톡을 실행시키고 있습니다.

import { Linking, Platform } from 'react-native';

import { ShouldStartLoadRequest } from 'react-native-webview/lib/WebViewTypes';

const shouldStartLoadWithRequest = (request: ShouldStartLoadRequest): boolean => {
  const { url } = request;

  if (url.startsWith('http') || url.startsWith('https')) {
    return true;
  }

  // NOTE: 안드가 웹뷰에서 외부앱을 실행시킬려면 intent URI를 사용해야 함. 카카오 JS SDK는 카톡 실행을 위한 intent URI를 생성해 호출함. 이 intent를 파싱해서 해당 activity를 실행시켜야 한다
  if (Platform.OS === 'android' && url.startsWith('intent')) {
    const kakaoLinkUrl = url.replace('intent://', 'kakaolink://');
    console.log('kakaoLinkUrl', kakaoLinkUrl);

    Linking.canOpenURL(kakaoLinkUrl)
      .then((canOpen) => {
        if (canOpen) {
          return Linking.openURL(kakaoLinkUrl);
        }
        throw new Error('카카오톡을 열 수 없습니다.');
      })
      .then(() => {
        // console.log('카카오톡이 성공적으로 열렸습니다.');
      })
      .catch((error) => {
        alert(`error (${error.message})`);
      });
    return false;
  }

  return false;
};

export default shouldStartLoadWithRequest;

그리고 구글 플레이 콘솔에서 SHA-1 인증서 지문을 가져와 Base64로 인코딩하여 플랫폼-안드로이드-키 해시에도 등록해두었습니다!
원인이 무엇인지 알 수 없어 답답하네요…

안녕하세요.

빌드된 후의 AndroidManifest.xml 파일 내용 공유 부탁드립니다.

여기 있습니다!

<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools">
  <uses-permission android:name="android.permission.CAMERA"/>
  <uses-permission android:name="android.permission.GALLERY"/>
  <uses-permission android:name="android.permission.INTERNET"/>
  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
  <uses-permission android:name="android.permission.RECORD_AUDIO"/>
  <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
  <uses-permission android:name="android.permission.VIBRATE"/>
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
  <queries>
    <intent>
      <action android:name="android.intent.action.VIEW"/>
      <category android:name="android.intent.category.BROWSABLE"/>
      <data android:scheme="https"/>
    </intent>
  </queries>
  <application android:name=".MainApplication" android:label="@string/app_name" android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round" android:allowBackup="true" android:theme="@style/AppTheme" android:requestLegacyExternalStorage="true">
    <meta-data android:name="expo.modules.updates.ENABLED" android:value="false"/>
    <meta-data android:name="expo.modules.updates.EXPO_UPDATES_CHECK_ON_LAUNCH" android:value="ALWAYS"/>
    <meta-data android:name="expo.modules.updates.EXPO_UPDATES_LAUNCH_WAIT_MS" android:value="0"/>
    <activity android:name=".MainActivity" android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout|uiMode" android:launchMode="singleTask" android:windowSoftInputMode="adjustResize" android:theme="@style/Theme.App.SplashScreen" android:exported="true" android:screenOrientation="portrait">
      <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"/>
        <data android:scheme="example"/>
        <data android:scheme="com.nation.app.example"/>
      </intent-filter>
      <intent-filter android:autoVerify="true" data-generated="true">
        <action android:name="android.intent.action.VIEW"/>
        <data android:scheme="https" android:host="web.development.example.im" android:pathPrefix="/share"/>
        <data android:scheme="kakao${native app key}" android:host="kakaolink"/>
        <category android:name="android.intent.category.BROWSABLE"/>
        <category android:name="android.intent.category.DEFAULT"/>
      </intent-filter>
      <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <data android:mimeType="text/*"/>
        <data android:mimeType="image/*"/>
        <data android:mimeType="video/*"/>
        <category android:name="android.intent.category.DEFAULT"/>
      </intent-filter>
      <intent-filter>
        <action android:name="android.intent.action.SEND_MULTIPLE"/>
        <data android:mimeType="text/*"/>
        <data android:mimeType="image/*"/>
        <data android:mimeType="video/*"/>
        <category android:name="android.intent.category.DEFAULT"/>
      </intent-filter>
    </activity>
    <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" android:exported="false"/>
  </application>
</manifest>

androidExecutionParams를 사용하셨을까요?
사용하지 않으셨다면 파라미터 전달 부탁드립니다.

androidExecutionParams는 따로 사용하지 않고 메세지 템플릿에서 파라미터를 템플릿 args로 전달되도록 해놨습니다!

아래 코드를 보시면 웹에서 공유 기능을 실행할 때 템플릿 args에 parameter가 전달되고 있습니다.

import { useCallback, useEffect } from 'react';
import type { KakaoShareResult } from './types';

declare global {
  interface Window {
    Kakao: any;
  }
}

export function useKakaoShare(): KakaoShareResult {
  useEffect(() => {
    if (!window.Kakao.isInitialized()) {
      window.Kakao.init(process.env.NEXT_PUBLIC_KAKAO_CLIENT_ID);
    }
  }, []);

  const handleKakaoShare = useCallback(
    async (imageUrl: string, documentID: string) => {
      const { Kakao } = window;
      const TEMPLATE_ID =
        process.env.NODE_ENV === 'production' ? 110073 : 110074;

      Kakao.Share.sendScrap({
        requestUrl: 'https://web.development.example.im',
        templateId: TEMPLATE_ID,
        templateArgs: {
          THUMB: imageUrl,
          PATH: `share/${documentID}`,
          PARAMETER: `documentID=${documentID}`,
        },
      });
    },
    [window],
  );

  return { handleKakaoShare };
}

++ 추가로 prebuild 이후 AndroidManifest.xml 파일을 보고 <package android:name="com.kakao.talk" /> 가 빠진 것을 알게됐습니다. 아래와 같이 직접 입력해주고 aab 파일을 빌드해서 해당 파일로 구글 플레이에서 배포해도 똑같은 문제가 발생하고 있습니다!

<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools">
  <uses-permission android:name="android.permission.CAMERA"/>
  <uses-permission android:name="android.permission.GALLERY"/>
  <uses-permission android:name="android.permission.INTERNET"/>
  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
  <uses-permission android:name="android.permission.RECORD_AUDIO"/>
  <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
  <uses-permission android:name="android.permission.VIBRATE"/>
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
  <queries>
    <package android:name="com.kakao.talk"/>
    <intent>
      <action android:name="android.intent.action.VIEW"/>
      <category android:name="android.intent.category.BROWSABLE"/>
      <data android:scheme="https"/>
    </intent>
  </queries>
  <application android:name=".MainApplication" android:label="@string/app_name" android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round" android:allowBackup="true" android:theme="@style/AppTheme" android:requestLegacyExternalStorage="true">
    <meta-data android:name="expo.modules.updates.ENABLED" android:value="false"/>
    <meta-data android:name="expo.modules.updates.EXPO_UPDATES_CHECK_ON_LAUNCH" android:value="ALWAYS"/>
    <meta-data android:name="expo.modules.updates.EXPO_UPDATES_LAUNCH_WAIT_MS" android:value="0"/>
    <activity android:name=".MainActivity" android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout|uiMode" android:launchMode="singleTask" android:windowSoftInputMode="adjustResize" android:theme="@style/Theme.App.SplashScreen" android:exported="true" android:screenOrientation="portrait">
      <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"/>
        <data android:scheme="example"/>
        <data android:scheme="com.nation.app.example"/>
      </intent-filter>
      <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <data android:mimeType="text/*"/>
        <data android:mimeType="image/*"/>
        <data android:mimeType="video/*"/>
        <category android:name="android.intent.category.DEFAULT"/>
      </intent-filter>
      <intent-filter>
        <action android:name="android.intent.action.SEND_MULTIPLE"/>
        <data android:mimeType="text/*"/>
        <data android:mimeType="image/*"/>
        <data android:mimeType="video/*"/>
        <category android:name="android.intent.category.DEFAULT"/>
      </intent-filter>
      <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <data android:mimeType="text/*"/>
        <data android:mimeType="image/*"/>
        <data android:mimeType="video/*"/>
        <category android:name="android.intent.category.DEFAULT"/>
      </intent-filter>
      <intent-filter>
        <action android:name="android.intent.action.SEND_MULTIPLE"/>
        <data android:mimeType="text/*"/>
        <data android:mimeType="image/*"/>
        <data android:mimeType="video/*"/>
        <category android:name="android.intent.category.DEFAULT"/>
      </intent-filter>
      <intent-filter android:autoVerify="true" data-generated="true">
        <action android:name="android.intent.action.VIEW"/>
        <data android:scheme="https" android:host="web.development.example.im" android:pathPrefix="/share"/>
        <data android:host="kakaolink" android:scheme="kakao${테스트 어플리케이션의 native app key}"/>
        <data android:host="kakaolink" android:scheme="kakao${실제 배포 어플리케이션의 native app key}"/>
        <category android:name="android.intent.category.BROWSABLE"/>
        <category android:name="android.intent.category.DEFAULT"/>
      </intent-filter>
      <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <data android:mimeType="text/*"/>
        <data android:mimeType="image/*"/>
        <data android:mimeType="video/*"/>
        <category android:name="android.intent.category.DEFAULT"/>
      </intent-filter>
      <intent-filter>
        <action android:name="android.intent.action.SEND_MULTIPLE"/>
        <data android:mimeType="text/*"/>
        <data android:mimeType="image/*"/>
        <data android:mimeType="video/*"/>
        <category android:name="android.intent.category.DEFAULT"/>
      </intent-filter>
    </activity>
    <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" android:exported="false"/>
  </application>
</manifest>

안녕하세요.

하이브리드앱에서 띄우는 공유하기 재현해볼 수 있는 페이지 URL 알려주시면 어떤 상황인지 확인해보겠습니다.