ReactNative GreenpOfferwall SDK 가이드 - rnd-adforus/GreenpSDK_Android GitHub Wiki
ReactNative GreenpOfferwall SDK 가이드는 Native로 개발되어 있는 GreenpOfferwall SDK를 ReactNative 환경에서 적용 가능하도록 구성된 샘플 코드 가이드 입니다. 다음의 구현 사항을 준수한 샘플 앱 다운로드 경로로 샘플 코드 적용을 확인 할 수 있습니다. ReactNative - GreenpOfferwall SDK Sample
-
platform 별 초기 세팅
1-1 AOS
(1) build.gradle 설정
(2) AndroidManifest.xml 설정
(3) Proguard 설정
(4) Native Interface 호출 필수 설정
1-2 iOS
(1) Installation 설정
(2) Info.plist 설정
(3) Native Interface 호출 필수 설정
- SDK 초기화
- SDK 사용법
- 콜백 URL 파라미터 설정
최소 지원 Android 버전은 ReactNative 프로젝트 > android > build.gradle 을 열고 의존성 Maven url을 설정합니다.
allprojects {
repositories {
google()
jcenter()
mavenCentral()
maven{
url 'https://nexus.adforus.com/repository/greenp/'
}
maven { // Optional - 오퍼월 내 구글 광고를 사용하시려면 작성 해주세요!
url 'https://artifact.bytedance.com/repository/pangle/'
}
}
}
ReactNative 프로젝트 > android > app > build.gradle 을 열고 의존성 목록을 추가합니다.
android {
viewBinding{
enabled = true
}
}
dependencies {
...
// 가이드 문서 내 최신버전 참고
implementation 'com.adforus.sdk:greenp_v3:3.5.2'
implementation 'com.adforus.sdk:adsu:1.2.0' // Optional - 오퍼월 내 구글 광고를 사용하시려면 작성 해주세요!
}
ReactNative 프로젝트 > android > app > src > main > AndroidManifest.xml 파일에 권한 설정을 추가합니다. 개인 식별과 리워드 적립을 위해서는 아래의 권한이 필요합니다. 권한 설정이 되지 않는 경우 SDK를 사용할 수 없습니다.
<uses-permission android:name=“android.permission.ACCESS_NETWORK_STATE”/>
<uses-permission android:name=“com.google.android.gms.permission.AD_ID”/>
<!-- CS 첨부파일 등록을 위해 외부 파일 접근권한이 필요합니다. api level에 따라 선택해서 선언해주세요. -->
<!-- targetSdk 32 이하 -->
<uses-permission android:name=“android.permission.READ_EXTERNAL_STORAGE”/>
<!-- targetSdk 33 이상 -->
<uses-permission android:name=“android.permission.READ_MEDIA_IMAGES”/>
[HTTP 트래픽 허용 관련]
그린피 SDK 에서는 HTTPS 를 사용하고 있지 않습니다. 따라서 SDK의 AndroidManifest.xml 을 통해 아래의 내용을 포함하고 있습니다.
(그린피에서는 많은 광고사를 실시간으로 연동하고 있어 여러 도메인이 추가/삭제 될 수 있습니다. 가급적 모든 HTTP 트래픽의 허용을 권장드립니다.)
<application
...
android:usesCleartextTraffic="true">
...
<application/>
앱의 보안을 위해 HTTP 프로토콜을 허용하지 않고자 하시는 경우 AndroidManifest.xml에 usesCleartextTraffic 을 false 로 변경 후 ReactNative 프로젝트 Root > android > app > src > main > res > xml 위치에 network_security_config.xml을 생성하고 아래의 도메인을 예외사항으로 추가해주세요. (허용이 필요한 도메인의 목록은 예고없이 추가/삭제 될 수 있습니다.) [network_security_config.xml]
<domain includeSubdomains="true">greenp.kr</domain>
<domain includeSubdomains="true">decaffeine.net</domain>
<domain includeSubdomains="true">adboost.co.kr</domain>
ReactNative 프로젝트 > android > app > proguard-rules.pro 에 다음을 추가하여 난독화 시 구현에 필요한 인터페이스의 난독화가 되지 않도록 설정해주세요.
-keep class com.adforus.sdk.greenp.v3.** { *; }
-dontwarn com.adforus.sdk.greenp.v3.**
-keep class com.adforus.sdk.adsu.** {*;}
-dontwarn com.adforus.sdk.adsu.**
- ReactContextBaseJavaModule 구현 클래스 생성 ( ReactNative 프로젝트 Root > android > app > src > main > 패키지경로 )
- ReactPackage 구현 클래스 생성 ( ReactNative 프로젝트 Root > android > app > src > main > 패키지경로 )
- MainApplication에 ReactPackage 구현 클래스 모듈 수동 등록 ( ReactNative 프로젝트 Root > android > app > src > main > 패키지경로 > MainApplication )
[ReactContextBaseJavaModule 구현 클래스 생성 및 구현] GreenpOfferwall SDK Android의 Native 인터페이스를 호출하기 위해 ReactContextBaseJavaModule을 구현한 클래스를 작성합니다.
import android.content.Context;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.adforus.sdk.greenp.v3.GreenpReward;
import com.adforus.sdk.greenp.v3.OfferwallBuilder;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
public class GreenpModule extends ReactContextBaseJavaModule {
private ReactApplicationContext reactContext;
private final Context context;
private OfferwallBuilder builder = null;
private Callback callback = null;
public GreenpModule(@Nullable ReactApplicationContext reactContext) {
super(reactContext);
this.reactContext = reactContext;
this.context = reactContext.getApplicationContext();
}
@NonNull
@Override
public String getName() {
return "GreenpModule";
}
@ReactMethod
public void initialized(String appCode, String userId, Callback callback){
if(this.callback == null) {
this.callback = callback;
}
if(context != null) {
if(reactContext.getCurrentActivity() == null) {
GreenpReward.init(context, appCode, userId, new GreenpReward.OnGreenpRewardListener() {
// 복수의 오퍼월을 게시 하기 위해서는 다음의 코드를 사용해주세요.
// GreepReward greenpReward = new GreewnpReward();
// greenpReward.initialize(Context context, String appCode, String appUid, GreenpReward.OnGreenpRewardListener listener);
@Override
public void onResult(boolean result, String msg) {
sendResult(result, msg, appCode);
}
});
}else {
GreenpReward.init(reactContext.getCurrentActivity(), appCode, userId, new GreenpReward.OnGreenpRewardListener() {
// 복수의 오퍼월을 게시 하기 위해서는 다음의 코드를 사용해주세요.
// GreepReward greenpReward = new GreewnpReward();
// greenpReward.initialize(Activity activity, String appCode, String appUid, GreenpReward.OnGreenpRewardListener listener);
@Override
public void onResult(boolean result, String msg) {
sendResult(result, msg, appCode);
}
});
}
}
}
private void sendResult(boolean result, String msg, String appCode) {
if(this.callback != null ) {
if(result) {
builder = GreenpReward.getOfferwallBuilder();
// 복수의 오퍼월을 게시 하기 위해서는 다음의 코드를 사용해주세요.
// builder = greenpReward.createOfferwallBuilder();
if(builder != null) {
builder.setAppUniqKey(appCode);
}
}
this.callback.invoke(result, msg);
}
}
@ReactMethod
public void show(){
if(builder != null && reactContext.getCurrentActivity() != null){
builder.showOfferwall(reactContext.getCurrentActivity());
}
}
}
[ReactPackage 구현 클래스 생성 및 구현] ReactNative에서 생성한 모듈을 인식할 수 있도록 다음과 같이 ReactPackage를 구현합니다.
import androidx.annotation.NonNull;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class GreenpPackage implements ReactPackage {
@NonNull
@Override
public List<NativeModule> createNativeModules(@NonNull ReactApplicationContext reactApplicationContext) {
List<NativeModule> modules = new ArrayList<>();
modules.add(new GreenpModule(reactApplicationContext));
return modules;
}
@NonNull
@Override
public List<ViewManager> createViewManagers(@NonNull ReactApplicationContext reactApplicationContext) {
return Collections.emptyList();
}
}
[ReactPackage 구현 클래스 모듈 수동 등록] 사용자 정의 Module을 ReactNative용으로 구현한 ReactPackage 구현 클래스를 다음과 같이 DefaultReactNativeHost 클래스의 ReactPackage 목록으로 추가 합니다.
import android.app.Application
import com.facebook.react.PackageList
import com.facebook.react.ReactApplication
import com.facebook.react.ReactHost
import com.facebook.react.ReactNativeHost
import com.facebook.react.ReactPackage
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load
import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
import com.facebook.react.defaults.DefaultReactNativeHost
import com.facebook.soloader.SoLoader
class MainApplication : Application(), ReactApplication {
override val reactNativeHost: ReactNativeHost =
object : DefaultReactNativeHost(this) {
override fun getPackages(): List<ReactPackage> =
PackageList(this).packages.apply {
add(GreenpPackage()) //Module 수동 등록
}
... 생략 ...
}
... 생략 ...
}
ReactNative 프로젝트 Root > ios > Podfile 을 열고 의존성 설정을 추가하여 주십시오.
- GreepPOfferwall SDK의 최소 iOS 지원 버전은 14.0 입니다.
- 타겟 모듈 내의 설정에서 use_react_native! 선언 부 상단에 use_framework! 선언과 함께 GreenpOfferwall SDK pod 의존성을 작성 합니다.
- 라이브러리의 표준화된 호환성 보장을 위해 post_install 내에 BUILD_LIBRARY_FOR_DISTRIBUTION 설정을 추가합니다.
수정된 Podfile을 저장하고, ios 경로에서 터미널 명령으로 pod update 와 pod install 명령으로 프로젝트 내에 의존성을 적용합니다.
platform :ios, '14.0'
''' 중략 '''
target 'YourProject' do
config = use_native_modules!
use_frameworks!
pod 'GreenPOfferWall', '3.4.0'
use_react_native!(
:path => config[:reactNativePath],
# An absolute path to your application root.
:app_path => "#{Pod::Config.instance.installation_root}/.."
)
''' 중략 '''
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'
end
end
# https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202
react_native_post_install(
installer,
config[:reactNativePath],
:mac_catalyst_enabled => false,
# :ccache_enabled => true
)
end
end
광고 추적 권한 허용 여부에 사용 되는 문구 설정 및 오퍼월 광고 지원을 위한 api 통신 설정이 다음과 같이 필요합니다. 다음의 설정이 올바르지 않을 시 오퍼월 리워드 지급이 원활하지 않을 수 있습니다. ReactNative 프로젝트 Root > ios > YourProject.xcworkspace을 xcode로 열고 Info.plist에 다음과 같이 추가 설정합니다.
광고 추적 권한에 따른 문구 설정
http 통신 예외처리
- RCTBridgeModule swift 클래스 구현 ( ReactNative 프로젝트 Root > ios > 프로젝트 디렉토리 )
- RCTBridgeModule swift 클래스를 Objective-C로 연결하는 implementation File (.m) 구현 ( ios > 프로젝트 디렉토리 )
[RCTBridgeModule swift 클래스 구현] ReactNative 프로젝트 Root > ios > .xcworkspace을 xcode로 엽니다. swift 파일을 생성하기 위해 프로젝트 디렉토리 내에서 우클릭 하여 New File을 클릭하고 클래스 이름을 작성합니다.
생성된 swift파일에 GreenpOfferwall SDK의 Native 코드를 호출하기 위한 RCTBridgeModule을 구현 한 클래스의 내용을 작성합니다.
import Foundation
import React
import GreenpOfferwall
@objc(GreenpModule) // ModuleName ex)GreenpModule
class GreenpModule: NSObject, RCTBridgeModule {
private lazy var greenp = GreenPSettings(delegate: **self**)
private var callback: RCTResponseSenderBlock?
static func moduleName() -> String! {
return "GreenpModule"
}
@objc
func initialized(_ appCode: String, userId: String, callback: @escaping RCTResponseSenderBlock){
greenp.set(appCode: appCode, userID: userId)
self.callback = callback
}
@objc
func show(){
DispatchQueue.main.async {
if let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
let window = scene.windows.first,
let viewController = window.rootViewController {
self.greenp.show(on: viewController)
}
}
}
}
extension GreenpModule : GreenPDelegate {
func greenPSettingsDidEnd(with message: String) {
if let reply = callback {
if message == "Device Regist Success!" {
reply(["true", message])
}else {
reply(["false", message])
}
}
}
}
[RCTBridgeModule swift 클래스를 Objective-C로 연결하는 implementation File (.m) 구현] RCTBridgeModule을 구현 했던 swift 클래스에 작성한 인터페이스에 맞추어 Objective-C 프로토타입 인터페이스를 작성합니다.
#import <React/RCTBridgeModule.h>
@interface RCT_EXTERN_MODULE(GreenpModule, NSObject)
RCT_EXTERN_METHOD(show)
RCT_EXTERN_METHOD(initialized:(NSString *)appCode userId:(NSString *)userId callback:(RCTResponseSenderBlock)callback)
@end
Native 코드를 호출하기 위한 기본 설정이 완료되었다면, 다음과 같이 ReactNative 코드로 GreenpOfferwall SDK를 호출 할 수 있습니다.
import { ... , NativeModules,} from 'react-native';
export default function App() {
if(Platform.OS === 'android') {
NativeModules.GreenpModule.initialized('Your Code', 'User ID', (result: string, message: string) => {
if(result) {
//초기화 성공
} else {
//초기화 실패
}
});
} else if(Platform.OS === 'ios'){
NativeModules.GreenpModule.initialized('Your Code', 'User ID', (result, message) => {
if(result) {
//초기화 성공
}else {
//초기화 실패
}
});
}
}
※ 유저 구분값 생성 규칙
- 각각의 유저별 고유한 값을 이용해야 합니다.
- 개인정보 및 IDFA는 사용할 수 없습니다. ( 암호화 후 사용 가능 )
- 한글, 특수문자, 공백은 반드시 URL 인코딩 후 사용하셔야 합니다.
NativeModules.GreenpModule.show();
광고 참여가 정상적으로 완료된 경우, 매체사에서 등록 하신 콜백 URL로 암호화키를 전송해 드립니다.
CallBack url : 매체사 URLMethod : GET or POST (기본은 GET 방식이나 요청시 POST 방식으로도 가능합니다.
Ad Parameter | Type | 설명 |
---|---|---|
ads_idx | int |
광고키 |
ads_name | string |
갬페인 타이틀 |
rwd_cost | int |
매체사에 지급되는 단가 |
app_uid | string |
매체사에 보낸 유저 구분 값 (UserID) |
gp_key | int |
전환 건에 대한 유니크 값 |
etc | int |
referrer 값. 매체용 추가 정보(매체 uniq 클릭값 등) etc 대신 원하는 파라미터로 변경가능 |