728x90
반응형

 

현재 진행중인 프로젝트에서 웹페이지 url을 입력받아 Open Graph 정보를 표시하는 작업을 하려고 합니다.

 

카카오톡이나 소셜 sns를 사용할 때 url만 입력해도 이미지와 제목이 뜨는걸 보셨을꺼에요.

 

일반적으로 웹 페이지를 만들때 약속된 meta tag라고 할 수 있는데요, 이런걸 Open Graph 프로토콜이라고 합니다. 

 

https://ogp.me/

 

Open Graph protocol

The Open Graph protocol enables any web page to become a rich object in a social graph.

ogp.me

 

 

 

# og meta tag 확인

쿠팡을 기준으로 작업을 해보겠습니다.

 

쿠팡 사이트에 들어가서 맥북을 검색해 본 뒤 크롬 기준으로 [도구 더보기 -> 개발자 도구] 항목을 클릭합니다.

 

 

 

펼쳐진 개발자 도구에서 'Elements' 탭을 선택하면 HTML요소들어 보여집니다.

 

head tag부분에서 아래와같이 link, meta, script 태그들이 보이네요.

 

 

 

저는 여기서 og: 라고 시작되는 태그들만을 원합니다.

 

보통 다른 쇼핑몰 같은 경우에도 image, title, url, description 항목은 필수적으로 사용하고 있는데요.

 

이 정보들이 소셜 sns나 채팅에 공유될때 나오는 정보들입니다.

 

image - 상품의 이미지

title - 상품 제목

url - 해당 상품 url

description - 간략한 설명

 

 

 

 

# 개발 준비

 

Flutter 프레임워크에서는 특정 패키지가 필요합니다.

 

http 패키지로 사이트의 html문자열을 가져온 다음, html 패키지로 문자열을 html로 파싱파여 원하는 정보를 가져올겁니다.

https://pub.dev/packages/http

 

http | Dart Package

A composable, multi-platform, Future-based API for HTTP requests.

pub.dev

https://pub.dev/packages/html/install

 

html | Dart Package

APIs for parsing and manipulating HTML content outside the browser.

pub.dev

 

 

 

 

# 페이지 정보 읽기

아래처럼 패키지를 import 해줍니다.

import 'package:http/http.dart' as http;
import 'package:html/dom.dart' as dom;
import 'package:html/parser.dart' as parse;

 

 

http.get 함수로 웹페이지 주소를 넣어 호출합니다.

 

아래처럼만 작성해도 일반적인 사이트에서는 문제 없이 html 문자열을 응답받습니다.

final String uri = "웹 페이지 주소";
final response = await http.get(Uri.parse(uri));

 

 

 

하지만 쿠팡같은 경우에는 pending이 걸려버리고 response가 오지 않는것을 알 수 있습니다.

 

각종 블로그에서도 해당 문제에 대해서 다루지만 user-agent를 넣는 방법으로는 동작하지 않습니다.

 

 

 

 

해결을 위해 쿠팡 사이트에 들어와 다시 [도구 더보기 -> 개발자 도구] 로 진입해서 웹 페이지 요청 항목을 선택한 뒤 [Network -> Headers] 탭으로 들어가보겠습니다.

 

Request Headers 부분에서 아래와 같이 accept 정보를 넣어주어 압축된 정보를 주고받는걸 알 수 있는데요. 

 

 

 

 

저도 이와 같이 header정보를 추가 해주겠습니다.

 

그리고 만약 동작하지 않을 수 있다는 부분을 위해 timeout 시간을 2초로 주었습니다.

 

아래처럼 작성하시면 쿠팡 사이트의 정보까지 문제없이 html문자열을 응답받을 수 있습니다

final response = await http.get(Uri.parse(uri), headers: {
  'accept-encoding': 'gzip, deflate, br',
  'accept-language': 'ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7',
}).timeout(const Duration(seconds: 2));

 

 

 

# og tag 추출

이제 html문자열에서 og tag만 추출하면 되겠네요.

 

위에서 import한 alias를 확인해주시고 코드를 봐주시면 됩니다.

 

response.body에서 html 문자열만을 추출해 html로 변환하면 Document라는 객체로 변환됩니다.

 

이 Document 객체에서 어떻게 정보를 꺼내냐면 meta tag 속성을 살펴보면 됩니다.

<meta property="og:title" content="Apple 2020 맥북 에어 13">

 

 

 

 

[head -> meta 에서 property가 'og:title' 인것의 content라는 속성을 꺼내줘] 라고 한다면 html 패키지에서는 아래처럼 코드를 작성하면 됩니다.

 

정말 간단하게 원하는 tag 정보를 가져올 수 있습니다.

dom.Document document = parse.parse(response.body);

String? title = document.head
    ?.querySelector("meta[property='og:title']")
    ?.attributes['content'];
String? description = document.head
    ?.querySelector("meta[property='og:description']")
    ?.attributes['content'];
String? image = document.head
    ?.querySelector("meta[property='og:image']")
    ?.attributes['content'];
String? url = document.head
    ?.querySelector("meta[property='og:url']")
    ?.attributes['content'];

 

 

 

 

전체 코드 입니다.

 

return type은 원하는 model을 생성해서 응답해주면 딱이겠군요!

import 'package:http/http.dart' as http;
import 'package:html/dom.dart' as dom;
import 'package:html/parser.dart' as parse;

static void urlToMeta(String uri) async {
    final response = await http.get(Uri.parse(uri), headers: {
      'accept-encoding': 'gzip, deflate, br',
      'accept-language': 'ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7',
    }).timeout(const Duration(seconds: 2));
    dom.Document document = parse.parse(response.body);

    String? title = document.head
        ?.querySelector("meta[property='og:title']")
        ?.attributes['content'];
    String? description = document.head
        ?.querySelector("meta[property='og:description']")
        ?.attributes['content'];
    String? image = document.head
        ?.querySelector("meta[property='og:image']")
        ?.attributes['content'];
    String? url = document.head
        ?.querySelector("meta[property='og:url']")
        ?.attributes['content'];
 }

 

 

 

# 마무리

Flutter 뿐만 아니라 다른 언어에서도 방법만 안다면 문제없어 원하는 정보를 Crawling 할 수 있습니다.

 

728x90
반응형
728x90
반응형

 

플러터로 개발중에 sdk 를 3.3.0 으로 버전업을 한 뒤로 firebase_messging을 사용하는 Android에서 BackgroundHandler함수 호출을 못하는 문제점이 생겼어요.

 

 

문제발생

당황스러운건 Debug 모드에서는 정상적으로 호출이 되다가 Release 모드에서만 갑자기 동작을 안해서 오류가 있는지도 몰랐다는 것이었죠.

 

release 모드로 빌드를 한다음 해당 오류가 발생하는것을 알게되었습니다.

flutter run --release
E/flutter (12708): [ERROR:flutter/lib/ui/dart_runtime_hooks.cc(38)] Dart Error: Unhandled exception:
E/flutter (12708): NoSuchMethodError: No top-level getter '_firebaseMessagingBackgroundHandler' declared.
E/flutter (12708): Receiver: top-level
E/flutter (12708): Tried calling: _firebaseMessagingBackgroundHandler
E/flutter (12708): #0      NoSuchMethodError._throwNew (dart:core-patch/errors_patch.dart:225)
E/flutter (12708): #1      FfiTrampoline___getCallbackFromHandle$Method$FfiNative$Ptr (dart:ffi)
E/flutter (12708): #2      _getCallbackFromHandle (dart:ui/natives.dart:141)
E/flutter (12708): #3      PluginUtilities.getCallbackFromHandle.<anonymous closure> (dart:ui/plugins.dart:81)
E/flutter (12708): #4      _LinkedHashMapMixin.putIfAbsent (dart:collection-patch/compact_hash.dart:524)
E/flutter (12708): #5      PluginUtilities.getCallbackFromHandle (dart:ui/plugins.dart:80)
E/flutter (12708): #6      _firebaseMessagingCallbackDispatcher.<anonymous closure> (package:firebase_messaging_platform_interface/src/method_channel/method_channel_messaging.dart:40)
E/flutter (12708): #7      MethodChannel._handleAsMethodCall (package:flutter/src/services/platform_channel.dart:555)
E/flutter (12708): #8      MethodChannel.setMethodCallHandler.<anonymous closure> (package:flutter/src/services/platform_channel.dart:548)
E/flutter (12708): #9      _DefaultBinaryMessenger.setMessageHandler.<anonymous closure> (package:flutter/src/services/binding.dart:393)
E/flutter (12708): #10     _invoke2 (dart:ui/hooks.dart:183)
E/flutter (12708): #11     _ChannelCallbackRecord.invoke (dart:ui/channel_buffers.dart:40)
E/flutter (12708): #12     _Channel.push (dart:ui/channel_buffers.dart:130)
E/flutter (12708): #13     ChannelBuffers.push (dart:ui/channel_buffers.dart:326)
E/flutter (12708): #14     PlatformDispatcher._dispatchPlatformMessage (dart:ui/platform_dispatcher.dart:664)
E/flutter (12708): #15     _dispatchPlatformMessage (dart:ui/hooks.dart:86)

 

 

 

이슈확인

NoSuchMethodError: No top-level getter '_firebaseMessagingBackgroundHandler' declared. 오류로 고통받는 개발자가 많이 생길것이라고 봅니다.

 

문제점 해결은 github 링크를 참고했습니다.

 

https://github.com/firebase/flutterfire/issues/9446#issuecomment-1240554285

 

🐛 [firebase_messaging] `onBackgroundMessage` is never called when using Flutter 3.3.0 in release mode on Android · Issue #94

Bug report When an app using firebase_messaging is built using Flutter 3.3.0, onBackgroundMessage is not being called at all on Android. When using Flutter 3.0.5, the app receives notifications in ...

github.com

 

 

 

해결

backgroundHandler에 @pragma 애노테이션을 작성하고 다시 Release 모드로 시작하면 문제가 사라진것을 알 수 있습니다.

@pragma('vm:entry-point')
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  ...
}

 

https://api.dart.dev/stable/2.1.0/dart-core/pragma-class.html

 

pragma class - dart:core library - Dart API

pragma class A hint to tools. Tools that work with Dart programs may accept hints to guide their behavior as pragma annotations on declarations. Each tool decides which hints it accepts, what they mean, and whether and how they apply to sub-parts of the an

api.dart.dev

 

 

 

 

firease_messaging Release모드에서 백그라운드 알림 수신을 하지 않는다는것은 정말 치명적이네요.

 

firebase_messaging을 사용하시는 분들에게 문제점 해결에 도움이 되었으면 합니다.

 

728x90
반응형
728x90
반응형

 

이전글에서 ReactNative Plugin 사용방법과 CodePush Option을 알아보았습니다.

 

이번글에서는 코드를 변경한 후에 릴리즈 하는 방법을 알아보겠습니다.

 

https://gigas-blog.tistory.com/273

 

[ReactNative] Code Push #4 ReactNative Plugin사용

#1 번글에서 CodePush 라이브러리를 추가 했습니다. https://gigas-blog.tistory.com/270 [ReactNative] Code Push #1 appcenter cli ReactNative의 장점은 CodePush 로 앱을 심사없이 없데이트 할 수 있다는 것..

gigas-blog.tistory.com

 

 

 

기본적인 Release는 아래의 형식으로 이루어져 있습니다.

appcenter codepush release-react -a <ownerName>/<appName>

 

 

 

#1번 글에서 CodePush-Android, CodePush-iOS 프로젝트를 만들었는데요. 그렇다면 아래와 같이 작성하면 됩니다.

appcenter codepush release-react -a bonjin/CodePush-iOS
appcenter codepush release-react -a bonjin/CodePush-Android

 

 

 

AppCenter 홈페이지에 보여지는 내용입니다.

 

appcenter codepush 명령시 아래의 옵션을 지정할 수 있습니다.

 

[-v]

해당 옵션을 추가하여 version을 지정할 수 있습니다.

 

[--description] 

해당 옵션을 추가하여 Description 내용을 추가할 수 있습니다.

 

[-x]

해당 옵션을 추가하여 Disabled 처리할 수 있습니다.

 

[-r]

해당 옵션을 추가하여 rollout 을 설정할 수 있습니다.

 

[-m]

해당 옵션을 추가하여 Required Update 옵션을 활성화 할 수 있습니다.

 

 

 

 

 

다양한 옵션들은 appcenter cli 문서를 통해 확인할 수 있습니다.

https://docs.microsoft.com/ko-kr/appcenter/distribution/codepush/cli#releasing-updates-react-native

 

App Center CLI를 사용하여 CodePush 업데이트 릴리스 - Visual Studio App Center

CodePush 업데이트를 릴리스하기 위해 App Center CLI를 사용하고 설정하는 방법

docs.microsoft.com

 

 

 

이로써 React Native프로젝트에 CodePush 기능을 적용해봤습니다.

 

CodePush의 기본적인 설정으로 만들어진 프로젝트는 GitHub에 공유 되어있습니다.

 

https://github.com/bonjin-app/ReactNative/tree/main/SideProject/CodePush

 

GitHub - bonjin-app/ReactNative

Contribute to bonjin-app/ReactNative development by creating an account on GitHub.

github.com

 

728x90
반응형
728x90
반응형

 

#1 번글에서 CodePush 라이브러리를 추가 했습니다.

https://gigas-blog.tistory.com/270

 

[ReactNative] Code Push #1 appcenter cli

ReactNative의 장점은 CodePush 로 앱을 심사없이 없데이트 할 수 있다는 것 인데요. 지금부터 CodePush 설정을 진행해보려고 합니다. 1. AppCenter 계정만들기 AppCenter 회원가입을 진행합니다. GitHub계정이나

gigas-blog.tistory.com

 

 

 

네이티브에서의 설정을 마쳤으니 이번글에서는 ReactNative Plugin을 사용해보도록 하겠습니다.

https://docs.microsoft.com/ko-kr/appcenter/distribution/codepush/rn-plugin

 

React Native 클라이언트 SDK 플러그 인 사용 - Visual Studio App Center

CodePush에서 React Native SDK를 사용하는 방법

docs.microsoft.com

 

 

 

# 간단한 사용 방법

간단하게 CodePush 설정을 한다면 아래와 같이 진행합니다.

 

기본 옵션으로는 앱 시작시 업데이트를 확인합니다. 업데이트가 완료되면 다음번에 앱 실행시 자동으로 다운로드되고 설치 됩니다. 만약 Required Update 옵션이 켜져 있다면 즉시 설치됩니다.

 

1. codePush로 래핑

App 컴포넌트를 codePush로 랩핑합니다.

 

이렇게 한줄만 추가해주면 기본적인 옵션으로 codePush가 동작됩니다.

import React from 'react'
import { View, Text } from 'react-native'
import codePush from 'react-native-code-push'

const App = () => {
    return (
        <View style={{
            flex: 1,
            justifyContent: 'center',
            alignItems: 'center',
        }}>
            <Text>App</Text>
        </View>
    )
}

export default codePush(App)

 

 

 

2. ES7 데코레이터 구문

두번째로는 @codePush 구문을 추가로 위와같은 동작을 합니다.

import React from 'react'
import { View, Text } from 'react-native'
import codePush from 'react-native-code-push'

@codePush
const App = () => {
    return (
        <View style={{
            flex: 1,
            justifyContent: 'center',
            alignItems: 'center',
        }}>
            <Text>App</Text>
        </View>
    )
}

export default App

 

 

 

# CodePush Option

CodePush에는 다양한 옵션이 있습니다. 

https://docs.microsoft.com/ko-kr/appcenter/distribution/codepush/rn-api-ref

 

CodePush API 참조를 사용하여 SDK React Native - Visual Studio App Center

CodePush API를 사용하여 React Native SDK에 사용하는 방법

docs.microsoft.com

 

 

- CheckFrequency

이 옵션은 AppCenter 서버와 동기화할 시기를 지정합니다.

 

1. codePush.CheckFrequency.ON_APP_START (0)

앱 프로세스가 시작될 때마다 업데이트를 확인합니다.

(기본옵션으로 일반적으로 많이 사용합니다.)

 

2. codePush.CheckFrequency.ON_APP_RESUME (1)

앱이 백그라운드에서 포그라운드로 진입시 업데이트를 확인합니다.

(보통 이 옵션은 사용자가 사용중에 갑자기 업데이트를 하기 때문에 잘 사용하지 않습니다.)

 

3. codePush.CheckFrequency.MANUAL (2)

업데이트에 대한 자동 확인을 사용하지 않도록 설정합니다. 별도로 codePush.sync()를 호출하여 업데이트를 확인합니다.

(별도 업데이트 체크를 하고 Custom Dialog, Progress를 제어 할때 사용합니다.)

 

 

- InstallMode

업데이트가 설치되고 앱에 적용할 시기를 지정합니다.

 

1. codePush.InstallMode.IMMEDIATE (0)

업데이트가 완료되면 즉시 앱을 다시 시작합니다.

 

2. codePush.InstallMode.ON_NEXT_RESTART (1) 

업데이트가 완료되고 다음에 앱을 시작할 때 업데이트가 적용됩니다.

 

3. codePush.InstallMode.ON_NEXT_RESUME (2)

업데이트가 완료되고 백그라운드에서 포그라운드로 진입시 업데이트가 적용됩니다.

 

4. codePush.InstallMode.ON_NEXT_SUSPEND (3)

백그라운드에 있는 동안에만 업데이트를 설치합니다.

minimumBackgroundDuration 옵션으로 몇 초 후에만 설치할 것을 지정합니다. (기본값 0)

 

 

 

- updateDialog

updateDialog와 Custom Dialog는 별도의 글로 작성할 예정입니다.

 

 

 

ReactNative 코드에서 CodePush Option은 아래와 같이 넣을 수 있습니다.

import React from 'react'
import { View, Text } from 'react-native'
import codePush from 'react-native-code-push'

const App = () => {
    return (
        <View style={{
            flex: 1,
            justifyContent: 'center',
            alignItems: 'center',
        }}>
            <Text>CodePush</Text>
        </View>
    )
}

const codePushOptions = {
	// 옵션 적용 범위
    codePush.CheckFrequency.ON_APP_START,
    codePush.InstallMode.IMMEDIATE,
    ...
}

export default codePush(codePushOptions)(App)

 

 

 

간단하게 CodePush Plugin 사용방법을 알아보았습니다.

 

728x90
반응형
728x90
반응형

 

React Native에서 gif 로딩 이미지를 사용하려고 합니다.

 

iOS에서는 별다른 설정없이 Image 컴포넌트를 사용하여 gif 파일을 로드할 수 있는데요.

 

Android에서는 기본적으로 gif 파일을 지원하지 않기 때문에 별도의 모듈을 추가 해야 합니다.

 

 

 

# 소개

Fresco는 Android를 위해 이미지를 표시하는 강력한 시스템입니다.

 

메모리와 로컬 저장소를 사용하여 캐쉬처리를 하는것 외에도 많은 기능을 포함하고 있습니다.

https://fresco.recrack.com/

 

Fresco An image management library.

Fresco is a powerful system for displaying images in Android applications. It takes care of image loading and display so you don’t have to. Fresco supports Android 2.3 (Gingerbread) and later.

facebook.github.io

 

 

# 모듈 적용

공식 홈페이지에서 아래와 같은 선택적 모듈을 지원하고 있습니다.

https://reactnative.dev/docs/image#gif-and-webp-support-on-android

 

Image · React Native

A React component for displaying different types of images, including network images, static resources, temporary local images, and images from local disk, such as the camera roll.

reactnative.dev

 

Android OS 4.0 (API Level 14) 이하 버전을 지원하는것과, WebP 지원여부에 따라 모듈을 추가하면 됩니다.

dependencies {
  // If your app supports Android versions before Ice Cream Sandwich (API level 14)
  implementation 'com.facebook.fresco:animated-base-support:1.3.0'

  // For animated GIF support
  implementation 'com.facebook.fresco:animated-gif:2.5.0'

  // For WebP support, including animated WebP
  implementation 'com.facebook.fresco:animated-webp:2.5.0'
  implementation 'com.facebook.fresco:webpsupport:2.5.0'

  // For WebP support, without animations
  implementation 'com.facebook.fresco:webpsupport:2.5.0'
}

 

 

제가 사용하는 프로젝트는 단순 gif를 로드하기 때문에 [implementation 'com.facebook.fresco:animated-gif:2.5.0']를 추가했습니다.

 

구글에서 search하여 다양한 글들이 나와있지만 fresco를 따로 추가한다거나 잘못된 방식이 많았습니다.

 

위와같이 한줄만 추가하여도 아래와같은 모듈들이 추가되어있으니 참고하면 됩니다.

 

 

 

이렇게 모듈을 추가하면 Android 업데이트를 해야하니 프로젝트 생성시 추가해주는것을 추천합니다.

 

728x90
반응형
728x90
반응형

 

ReactNative 환경에서 타사 라이브러리를 붙이려면 NativeModule로 작성해야 합니다.

 

타사에서 jni .so 라이브러리를 제공해서 load하는데 계속 아래와 같은 오류가 발생했습니다.

A/libc: Fatal signal 6 (SIGABRT), code -1 (SI_QUEUE) in tid 28002 (mqt_native_modu), pid 27506 (nativexxx)

 

 

 

이유를 알아본다면 Native Module이 javascript thread에서 실행되는곳이 문제가 되고 있는건데요.

 

ReactNative 0.55 Version부터 mgt_접두사가 붙인 MessageQueueThread를 사용하는데 0.55 이하버전에서 .so파일을 불러오는것은 문제가 되지 않지만 이상의 버전이라면 hermes를 사용하여야 합니다.

 

공식 홈페이지를 참고하여 hermes를 활성화 하면 정상적으로 so파일 load가 됩니다.

https://reactnative.dev/docs/hermes

 

Using Hermes · React Native

Hermes is an open-source JavaScript engine optimized for React Native. For many apps, enabling Hermes will result in improved start-up time, decreased memory usage, and smaller app size. At this time Hermes is an opt-in React Native feature, and this guide

reactnative.dev

 

 

 

React Native하면서 이런 이슈들이 많네요.

 

Flutter보다 이런 설정문제가 많다보니 유저들이 많이 떠나고 있는것 같습니다..

 

 

 

- 참고 -

https://stackoverflow.com/questions/49216063/what-is-mqt-native-modules-and-what-to-do-about-its-crashes

 

What is mqt_native_modules and what to do about its crashes

I'm working with React Native (noob) and I'm getting some crashes like the following on Android: libc: Fatal signal 11 (SIGSEGV), code 1 (mqt_native_modu) What is this module mqt_native_modu? Is ...

stackoverflow.com

https://stackoverflow.com/questions/65418985/react-native-crashedthread-sigsegv-libjsc-so

 

React Native Crashed:Thread : SIGSEGV libjsc.so

We are getting following crash on various random places in android devices. Although we have changed ndk abifilters to "armeabi-v7a", "arm64-v8a" Crashed: Thread : SIGSEGV

stackoverflow.com

 

728x90
반응형
728x90
반응형

 

이전 글에서는 Code Push 다중 배포 중 Android 설정에 대해서 알아보았습니다.

https://gigas-blog.tistory.com/276?category=1037450 

 

[ReactNative] Code Push 다중 배포 #1 Android

이전 글에 CodePush 설정을하여 실시간 배포를 진행해봤습니다. https://gigas-blog.tistory.com/270?category=1037450 [ReactNative] Code Push #1 appcenter cli ReactNative의 장점은 CodePush 로 앱을 심사없..

gigas-blog.tistory.com

 

 

 

이번 글에서는 iOS 설정에 대해서 알아보겠습니다.

 

* React Native 0.60 이상을 기준으로 작성하였습니다. *

 

 

 

# iOS 설정

xcode 프로젝트를 열고 프로젝트 탐색기에서 Project를 선택합니다.

 

'Info' 탭에서 'Configurations' 항목의 '+'버튼을 클릭합니다.

 

'Duplicate "Release" Configuration' 을 선택하여 Staging(원하는)이름으로 변경해줍니다.

 

 

 

 

Staging 을 추가하였으니 Build Settings 탭으로 이동합니다.

 

'+' 버튼을 클릭하고 Add User-Defined Setting 을 선택합니다.

 

 

 

MULTI_DEPLOYMENT_CONFIG 항목을 생성하고 Release에는 '$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)', Staging에는 '$(BUILD_DIR)/Release$(EFFECTIVE_PLATFORM_NAME)' 값을 넣어줍니다.

 

 

 

다시 '+' 버튼을 클릭하고 Add User-Defined Setting 을 선택합니다.

 

이번에는 CODEPUSH_KEY 항목을 추가하고 Release에는 Production DeploymentKey를, Staging에는 Staging DeploymentKey 값을 넣어줍니다.

 

 

 

마지막으로 info.plist파일을 열고 기존에 작성했던 CodePushDeploymentKey 항목의 값을 '$(CODEPUSH_KEY)' 로 변경하여 줍니다.

 

기존에 CodePush 설정이 되어있지 않았다면 해당 항목은 없으니 새로 추가하면 됩니다.

 

 

 

 

이제 Scheme 설정에서 원하는 모드로 빌드를 진행할 수 있습니다.

 

기본 debug 모드에서는 배포키가 없으며, 배포시 release, staging모드로 각 모드에 맞는 배포키로  빌드할 수 있습니다.

 

 

 

Release, Staging 말고도 원하는대로 커스텀이 가능하며, 용도에 맞는 모드로 배포해보세요.

 

728x90
반응형
728x90
반응형

 

이전 글에 CodePush 설정을하여 실시간 배포를 진행해봤습니다.

https://gigas-blog.tistory.com/270?category=1037450 

 

[ReactNative] Code Push #1 appcenter cli

ReactNative의 장점은 CodePush 로 앱을 심사없이 없데이트 할 수 있다는 것 인데요. 지금부터 CodePush 설정을 진행해보려고 합니다. 1. AppCenter 계정만들기 AppCenter 회원가입을 진행합니다. GitHub계정이나

gigas-blog.tistory.com

 

 

 

하지만 테스터에게 제공할 때에도 실시간 배포가 되야하는데요.

 

Production 이나 Staging 하나로 배포 키가 고정되어 있다면 매번 앱을 다시 빌드해야할겁니다.

 

AppCenter에서는 Staging으로 테스터에게 배포하고 문제가 없다면 Production으로 배포하는걸 권장하고 있죠.

 

이번 글에서 위의 상황에 맞게 배포할 수 있도록 다중 배포 키를 등록하도록 하겠습니다.

 

* React Native 0.60 이상을 기준으로 작성하였습니다. *

 

 

 

# Android 설정

app 수준의 build.gradle 파일을 열어줍니다.

 

 

 

android { buildTypes {} } 위치를 찾아 빌드 유형에 대한 항목을 정의합니다.

 

resValue에 각 항목에 맞는 배포 키를 넣어줍니다.

 

Staging은 명명규칙때문에 releaseStaging으로 작성해줍니다.

 

그냥 staging으로 작성한다면 Bundle 생성시 buildTypes에서 보여지지 않습니다.

android {
    ...
    buildTypes {
        debug {
            ...
            // Note: CodePush updates shouldn't be tested in Debug mode as they're overriden by the RN packager. However, because CodePush checks for updates in all modes, we must supply a key.
            resValue "string", "CodePushDeploymentKey", '""'
            ...
        }
        releaseStaging {
            ...
            resValue "string", "CodePushDeploymentKey", '"<INSERT_STAGING_KEY>"'
            // Note: It's a good idea to provide matchingFallbacks for the new buildType you create to prevent build issues
            // Add the following line if not already there
            matchingFallbacks = ['release']
            ...
        }
        release {
            ...
            resValue "string", "CodePushDeploymentKey", '"<INSERT_PRODUCTION_KEY>"'
            ...
        }
    }
    ...
}

 

 

 

# Android 에서 hermes를 사용하고 있다면 staging빌드시 충돌로 앱이 종료됩니다 #

# 아래처럼 releaseStagingImplementation 라인을 추가해줘야 정상적으로 앱이 실행됩니다. #

if (enableHermes) {
    ...
    releaseStagingImplementation files(hermesPath + "hermes-release.aar")
} else {
    implementation jscFlavor
}

 

 

 

 

기존에 작성했던 strings.xml에서 작성했던 'CodePushDeploymentKey' 항목은 제거해줍니다.

 

기존에 CodePush 설정이 되어있지 않았다면 해당 항목은 없으니 패스해도 됩니다.

 

 

 

잘 따라 오셨다면 build.gradle에서 'Sync Now'를 클릭해 줍니다.

 

 

 

정상적으로 Sync가 되었다면 상단 메뉴 'Build'항목에서 'Generate Signed Bundle / APK...'메뉴를 클릭합니다.

 

 

서명을 하고 다음으로 넘어가면 정상적으로 releaseStaging 타입이 생긴것을 확인할 수 있습니다.

 

기본 debug 모드에서는 배포키가 없으며, 배포시 release, staging모드로 각 모드에 맞는 배포키로  빌드할 수 있습니다.

 

 

 

Release, Staging 말고도 원하는대로 커스텀이 가능하며, 용도에 맞는 모드로 배포해보세요.

 

728x90
반응형
728x90
반응형

 

공식 홈페이지 입니다.

https://docs.microsoft.com/ko-kr/appcenter/distribution/codepush/rn-get-started

 

React Native 클라이언트 SDK 시작 - Visual Studio App Center

React Native SDK & CodePush 시작

docs.microsoft.com

 

 

 

CodePush 를 사용하기 위해 아래의 명령어를 입력하여 의존성을 추가합니다.

 

ReactNative 루트 경로에서 아래와 같은 명령어를 입력합니다.

npm install --save react-native-code-push

 

 

1. CocoaPods dependencies 설치

아래 명령어를 실행하여 CocoaPods dependencies를 설치 합니다.

cd ios && pod install && cd ..

 

 

2. AppDelegete.m 헤더 추가

AppDelegete.m 파일에서 아래 헤더 파일을 import 합니다.

 

#ifdef FB_SONARKIT_ENABLED 라인 위에 아래의 헤더파일을 추가합니다.

#import <CodePush/CodePush.h>

 

 

3. sourceURLForBridge 수정

Release 모드에서 원본 URL을 설정하는 코드를 찾습니다.

return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];

 

 

위에 코드를 아래 코드로 변경합니다.

 

CodePush bundleURL로 변경함으로써 최신 버전의 앱 JS 번들을 로드합니다.

return [CodePush bundleURL];

 

 

sourceURLForBridge 함수 코드는 아래와 같습니다.

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
  return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
#else
  return [CodePush bundleURL];
#endif
}

 

 

 

4. Info.plist 설정

CodePushDeploymentKey를 추가 합니다.

<key>CodePushDeploymentKey</key>
<string>DeploymentKey</string>

 

 

 

이와같은 설정으로 CodePush를 사용할 수 있는 기본적인 설정이 되었습니다.

728x90
반응형
728x90
반응형

 

공식 홈페이지 입니다.

https://docs.microsoft.com/ko-kr/appcenter/distribution/codepush/rn-get-started

 

React Native 클라이언트 SDK 시작 - Visual Studio App Center

React Native SDK & CodePush 시작

docs.microsoft.com

 

 

 

CodePush 를 사용하기 위해 아래의 명령어를 입력하여 의존성을 추가합니다.

 

ReactNative 루트 경로에서 아래와 같은 명령어를 입력합니다.

npm install --save react-native-code-push

 

 

1. settings.gradle 설정

android/settings.gradle 파일에 다음과 같이 추가 합니다.

include ':app', ':react-native-code-push'
project(':react-native-code-push').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-code-push/android/app')

 

 

아래의 위치에 추가를 진행합니다.

 

 

2. build.gradle 설정

android/app/build.gradle 파일에 다음과 같이 추가 합니다.

...
apply from: "../../node_modules/react-native/react.gradle"
apply from: "../../node_modules/react-native-code-push/android/codepush.gradle"
...

 

 

 

아래의 위치에 추가를 진행합니다.

 

 

 

3. MainApplication.java 설정

ReactNativeHost getJSBundleFile 메서드를 Override하여 아래처럼 작성해줍니다.

...
// 1. Import the plugin class.
import com.microsoft.codepush.react.CodePush;
public class MainApplication extends Application implements ReactApplication {
    private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
        ...
        // 2. Override the getJSBundleFile method to let
        // the CodePush runtime determine where to get the JS
        // bundle location from on each app start
        @Override
        protected String getJSBundleFile() {
            return CodePush.getJSBundleFile();
        }
    };
}

 

 

 

4. strings.xml 설정

CodePushDeploymentKey 값을 추가하여 배포 키를 추가 합니다.

 

Staging, Production 키를 넣으면 됩니다.

<resources>
     <string name="app_name">AppName</string>
     <string moduleConfig="true" name="CodePushDeploymentKey">DeploymentKey</string>
 </resources>

 

 

AppCenter의 Analytics와 Crashes를 사용하면 아래처럼 추가하면 됩니다.

<string name="appCenterCrashes_whenToSendCrashes" moduleConfig="true" translatable="false">DO_NOT_ASK_JAVASCRIPT</string>
<string name="appCenterAnalytics_whenToEnableAnalytics" moduleConfig="true" translatable="false">ALWAYS_SEND</string>

 

 

 

이와같은 설정으로 CodePush를 사용할 수 있는 기본적인 설정이 되었습니다.

 

728x90
반응형

+ Recent posts