'광고달기'에 해당되는 글 1건

  1. 2014.07.07 cocos2d-x jni를 이용한 광고(AdMob) 달기 3
728x90

확실하지 않은 부분, 혹은 틀린 부분이 있을수도 잇다는 점을 우선 말씀드리고

포스팅 하겠습니다. (제 폰에는 정상적으로 다 잘됬음..)

 

우선 구글 AdMob을 이용하기 위해선 가입을 하셔야됩니다.

(http://www.google.co.kr/ads/admob/)

 

 

가입을 다 완료 하시게 되면

 

 

아래와같은 화면으로 이동할수 잇게 되고

저기 빨간박스로 줄치어진 부분에서 게시자 ID pub-xxxxxxxxxxxx.... 뭐로 시작하는게 있는데 나중에 이부분이 광고를 달때 쓰이니까 일단 기억해 두시길 바랍니다.

 

여기까지 이제 애드몹을 쓰기위한 준비는 끝...

 

1 . 이제 간단한 테스트를 위한 cocos2d-x 코드를 설명하겠습니다.

 

///// HelloWorldScene.h /////

 

#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__

#include "cocos2d.h"

class HelloWorld : public cocos2d::LayerColor
{
public:
 static cocos2d::Scene* createScene();

 virtual bool init();


 

 void doShow(Ref* pSender); //광고를 보여준다
 void doHide(Ref* pSender); //광고를 숨긴다
    
 CREATE_FUNC(HelloWorld);
};

#endif // __HELLOWORLD_SCENE_H__

 

///// HelloWorldScene.cpp /////

 

#include "HelloWorldScene.h"


 

USING_NS_CC;

 

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#include "platform/android/jni/JniHelper.h"

void callJavaMethod(std::string func)
{
    JniMethodInfo t;
    /**
     JniHelper를 통해 org/cocos2dx/cpp/에 있는
     AppActivity class의 파라미터로 들어온 스트링 이름의 함수 정보를 가져온다.
     */
    if (JniHelper::getStaticMethodInfo(t
                                       , "org/cocos2dx/cpp/AppActivity"
                                       , func.c_str()
                                       , "()V"))
    {
        // 함수 호출
        t.env->CallStaticVoidMethod(t.classID, t.methodID);
        // Release
        t.env->DeleteLocalRef(t.classID);
    }
}

#endif

 

Scene* HelloWorld::createScene()
{
    auto scene = Scene::create();
    auto layer = HelloWorld::create();
    scene->addChild(layer);
    return scene;
}

 

bool HelloWorld::init()
{
 if (!LayerColor::initWithColor(Color4B(255, 255, 255, 255)))
    {
        return false;
    }
    
 Size visibleSize = Director::getInstance()->getVisibleSize();
 Point origin = Director::getInstance()->getVisibleOrigin();

 

 MenuItemFont::setFontName("fonts/Marker Felt.ttf");
 MenuItemFont::setFontSize(40);


 

 auto pMenuItem1 = MenuItemFont::create("View", CC_CALLBACK_1(HelloWorld::doShow, this)); //View 글자를 누르면 doShow 함수를 호출
 pMenuItem1->setColor(Color3B(0, 0, 0));

 

 auto pMenuItem2 = MenuItemFont::create("Hide", CC_CALLBACK_1(HelloWorld::doHide, this)); //Hide 글자를 누르면 doHide 함수를 호출
 pMenuItem2->setColor(Color3B(0, 0, 0));

 

 auto pMenu = Menu::create(pMenuItem1, pMenuItem2, NULL);

 pMenu->alignItemsVerticallyWithPadding(10.0f);

 this->addChild(pMenu);

 

    return true;
}

 

//각각 호출에 맞는 함수명을 string으로 callJavaMethod로 넘겨줌

void HelloWorld::doShow(Ref* pSender)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
 callJavaMethod("ShowAdPopup");
#endif
}

void HelloWorld::doHide(Ref* pSender)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
 callJavaMethod("HideAdPopup");
#endif
}

 

cocos2d-x 정리

View 라는 글자를 누르게 되면 callJavaMethod로 문자열 ShowAdPopup 을 보냄.

Hide 라는 글자를 누르게 되면 callJavaMethod로 문자열 HideAdPopup 을 보냄.

 

callJavaMethod는 매개변수로 받은 이 문자열을 c_str()로 변환하여 해당 이름으로 함수를 호출합니다.

즉 매개변수로 받는 문자열이 안드로이드에서 호출될 함수 이름입니다.

 

2. eclipse 에서 import 및 코드 설명

 

 

우선 이클립스에 필요한 목록들을 import 합시다.

자기 프로젝트의 proj.android 폴더와, google-play-services_lib 폴더를 import를 해야하는데요

 

2 - 1. 자기 프로젝트의 proj.android 폴더 부터 일단 설명하겠습니다.

 

처음엔 그냥 import를 시키면 막연한 빨간줄로 에러가 나실수 있습니다.

대부분이 참조할수 있는 cocos2d-x 라이브러리를 설정을 해주지 않아서 우선 에러가 납니다.

라이브러리 참조 방법은 제가 아는 방법은 2가지가 있습니다.

 

(참고. 첫번째 방법보단, 나중에 코드수정이나, 광고를 달거나 하는것에 있어서.. 말씀드릴 두번째 방법이 효율적이라 합니다.. 저도 왜그런지는 잘 모르겠습니다..)

 

첫째. 내프로젝트에 있는 libcocos2dx 를 import 하는겁니다.

 

 

(제 프로젝트 경로 기준... 으로 자세히 보여드리면 아래와 같은곳에 있는 라이브러리들을 가져 옵니다. )

C:\Users\BITEC-15P\Desktop\jniEx01\cocos2d\cocos\2d\platform\android\java\src\org\cocos2dx\lib

 

그럼 사진에서 보시는바와 같이 libcocos2dx 라는 폴더가 생깁니다.

import 를 하셨으면 내프로젝트에 오른쪽 클릭->Properties 클릭->Android에 들어가시면 사진과같은 화면이 뜨는데 여기서 add버튼을 눌러 참조할 라이브러리를 설정해 줍니다.

 

add누르시면 libcocos2dx 가 보이는데 클릭하고 ok후 적용해주시면 끝입니다.

 

둘째. 기존에 받았던 ex) cocos2d-x-3.0 폴더에 있는 cocos2dx 라이브러리 폴더를 내 proj.android 경로에 넣어준다

 

저는 현재 cocos2d-x-3.0을 쓰고 있습니다. 여기 안에 있는 lib폴더를 제 프로젝트의 proj.android 에 넣어주는 방법인데요.

 

우선 lib폴더의 자세한 경로는 제 기준

( C:\Users\BITEC-15P\Desktop\cocos2d-x-3.0\cocos\2d\platform\android\java\src\org\cocos2dx\lib ) 에 있습니다.

 

 

lib 폴더를 이제 나의 프로젝트 proj.android 에다가 그냥 복사만 해주시면 되는데요

 

복사하는 경로는 제 기준

( C:\Users\BITEC-15P\Desktop\jniEx01\proj.android\src\org\cocos2dx ) 여기입니다.

cpp폴더가 하나 보일텐데요 거기에 같이 lib폴더를 복사해주시면 됩니다.

 

 

 

완료하시면 이클립스에서 프로젝트를 Refresh 한번만 해주시면 아래와같이 lib가 추가된것을 확인할수 있습니다.

 

 

3. 이제 google-play-services_lib를 참조 시켜주어야 합니다.

 

예전에는 애드몹을 이용하기 위해서 jar 파일을 직접 배포하여 주었는데 이제는 그렇게 해주지 않는 대신

이 google-play-service를 사용해야 한다고 합니다.

 

우선 android sdk manager을 실행시켜서 사진에 보이시는 Google Play services가 install 되어 있지 않다면

install 해주시기 바랍니다. 그리고 혹시나 모르니까 업데이트 표시가 있으시면 업데이트도 해주시기 바랍니다.

 

 

다 설치가 완료되었으면 google-play-services_lib 를 이클립스에 우선 import 시켜서 가져와야 합니다.

이 라이브러리가 있는 경로는

 

sdk폴더->extras->google->google->google_play_services->libproject 에 있습니다.

 

import를 시키시면 아래 사진과 같이 추가가 되는데

 

이제 주의할 점이 있습니다.

google-play-service는 안드로이드 버전 4.0이상을 기준으로 제공된다고 합니다.

그래서 google-play-service 폴더, 내 안드로이드 프로젝트 버전을 4.0 이상으로 바꿔 주셔야 합니다.

 

 

google-play-service_lib 폴더와, 내프로젝트 폴더 둘다

오른쪽 클릭->Properties 클릭->Android 에 들어가서 사진에 보이시는 해당 버전에 체크 하신후 apply

하시고 ok누르고 종료 하시면 적용됩니다.

 

(혹시나 사진처럼 andorid 버전이 안보인다 하시는 분은 ... 아예 안드로이드를 이클립스에서 잘 안해보신분이라고도 할수 있는데... android sdk manager를 실행시키셔서 각각 버전들을 install 시키셔서 해당 버전 플랫폼을 설치 해주 셔야 됩니다.)

 

 

이제 여기까지 하셨으면 모든 환경설정은 다 끝입니다. 글로, 사진으로 보면 엄청 길고 오래 보일수 있는데

직접 해보면 금방합니다...(익숙하다면...)

 

4. 안드로이드 액티비티 코드 설명..

package org.cocos2dx.cpp;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.cocos2dx.lib.Cocos2dxActivity;

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.graphics.Color;
import android.graphics.Point;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Display;
import android.view.View;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.Toast;

import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdSize;
import com.google.android.gms.ads.AdView;
 

 

@SuppressLint("HandlerLeak")
public class AppActivity extends Cocos2dxActivity {
 
 static public Handler handler;
 
 private static AppActivity _appActiviy;
 private AdView adView;
 private static final String AD_UNIT_ID = "ca-app-pub-xxxxxxxxxxxxxxxx/0000000000";
  //아까 애드몹에서 확인하셨던 게시자 id pub 번호를 저 x로 되어있는 부분에 입력해주시면 됩니다.

 

뒤에 나머지 000은 정식으로 앱에 광고를 달고 apk를 출시할때 뒷번호를 더 알려준다고 합니다 (이부분은 저도 정확하게 알고 말씀드리는건 아닙니다.)


 // Helper get display screen to avoid deprecated function use
 private Point getDisplaySize(Display d)
 {
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
  {
   return getDisplaySizeGE11(d);
  }
  return getDisplaySizeLT11(d);
 }
 
 @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
 private Point getDisplaySizeGE11(Display d)
 {
  Point p = new Point(0, 0);
  d.getSize(p);
  return p;
 }
 private Point getDisplaySizeLT11(Display d)
 {
  try
  {
   Method getWidth = Display.class.getMethod("getWidth", new Class[] {});
   Method getHeight = Display.class.getMethod("getHeight", new Class[] {});
   return new Point(((Integer) getWidth.invoke(d, (Object[]) null)).intValue(), ((Integer) getHeight.invoke(d, (Object[]) null)).intValue());
  }
  catch (NoSuchMethodException e2) // None of these exceptions should ever occur.
  {
   return new Point(-1, -1);
  }
  catch (IllegalArgumentException e2)
  {
   return new Point(-2, -2);
  }
  catch (IllegalAccessException e2)
  {
   return new Point(-3, -3);
  }
  catch (InvocationTargetException e2)
  {
   return new Point(-4, -4);
  }
 }
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  // TODO Auto-generated method stub
  super.onCreate(savedInstanceState);
  
  getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

  int width = getDisplaySize(getWindowManager().getDefaultDisplay()).x;

  LinearLayout.LayoutParams adParams = new LinearLayout.LayoutParams(
    width,
  LinearLayout.LayoutParams.WRAP_CONTENT);

  adView = new AdView(this);
  adView.setAdSize(AdSize.BANNER);
  adView.setAdUnitId(AD_UNIT_ID);


  AdRequest adRequest = new AdRequest.Builder()
  .addTestDevice(AdRequest.DEVICE_ID_EMULATOR)
  .addTestDevice("455611DB7112DF5A280975818FA14B5C")

//455611DB7112DF5A280975818FA14B5C 이 이상한.. 번호들은 제 스마트폰 디바이스를 뜻하는 번호입니다. 이 .addTestDevice 에 테스트용으로 실험할 디바이스 번호를 입력해 줍니다.

내 디바이스 번호를 어떻게 알아내느냐? 이것은 밑에서 설명해 드리겠습니다.

  .build();

  adView.loadAd(adRequest);
  adView.setBackgroundColor(Color.BLACK);
  adView.setBackgroundColor(0);
  addContentView(adView,adParams);
  
  _appActiviy = this;
  
  handler = new Handler()
  {
   public void handleMessage(Message msg)
   {
    if(msg.what == 0) // 핸들러 값이 0일경우 광고를 보이게한다.
    {
      showAd();
    }
    else if(msg.what == 1) // 핸들러 값이 1일경우 광고를 보이지 않게 한다.
    {
     hideAd();
    } 

   }
  };
 }
 
 public static void hideAd() // 광고 숨김 처리 함수 

{
  Log.d("Cocos2d-x","bbbbb");
  _appActiviy.runOnUiThread(new Runnable()
  {

   @Override
   public void run()
   {
    if (_appActiviy.adView.isEnabled())
     _appActiviy.adView.setEnabled(false);
    if (_appActiviy.adView.getVisibility() != 4 )
     _appActiviy.adView.setVisibility(View.INVISIBLE);
   }
  });

 }


 public static void showAd() //광고 보이게 하는 처리 함수
 {
  Log.d("Cocos2d-x","aaaaa");
  _appActiviy.runOnUiThread(new Runnable()
  {

   @Override
   public void run()
   { 
    if (!_appActiviy.adView.isEnabled())
     _appActiviy.adView.setEnabled(true);
    if (_appActiviy.adView.getVisibility() == 4 )
     _appActiviy.adView.setVisibility(View.VISIBLE); 
   }
  });

 }

 @Override
 protected void onResume() {
  super.onResume();
  if (adView != null) {
   adView.resume();
  }
 }

 @Override
 protected void onPause() {
  if (adView != null) {
   adView.pause();
  }
  super.onPause();
 }

 @Override
 protected void onDestroy() {
  adView.destroy();
  super.onDestroy();
 }

 

 //cocos2d-x(C++)에서 호출하는 함수로써 광고를 보이게 할때는 핸들러값을 0, 안보이게 할때는 1로 주고 있고 각각의 함수명은 앞서 cocos2d-x에서 callJavaMethod에 매개변수로 보내던 문자열과 동일하다. 

    public static void ShowAdPopup()   

    {
        handler.sendEmptyMessage( 0 );
    }

    public static void HideAdPopup()
    {
        handler.sendEmptyMessage( 1 );
    } 

}

 우선 너무 길어서 햇갈려 하시는 분들이 있을수도 있을것 같애서 참고 AppActivity.java 폴더를 올려 드리겠습니다.

 

jniAppActivity.java

 

이 소스의 모든것을 다 아실필요는 없고 전부다 복사해서 쓰면 되는겁니다. 세세한, 광고의 위치라던지, 기능이라던지 등을 jni의 흐름을 아시고 그런 부분만 맞게 코딩 해주시면 됩니다.

 

5. 내 프로젝트에 있는 AndroidManifest.xml 수정

 

(굵은 글씨로 되어있는 부분 추가해 주시면 됩니다.)

 

 <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.study.jni01"
      android:versionCode="1"
      android:versionName="1.0">

    <uses-sdk android:minSdkVersion="9"/>
    <uses-feature android:glEsVersion="0x00020000" />

    <application android:label="@string/app_name"
                 android:icon="@drawable/icon">


        <activity android:name="org.cocos2dx.cpp.AppActivity"
                  android:label="@string/app_name"
                  android:screenOrientation="landscape"
                  android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
                  android:configChanges="orientation">
            <!-- Tell NativeActivity the name of our .so -->
            <meta-data android:name="android.app.lib_name"
                       android:value="cocos2dcpp" />

            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
       
        <!-- Admob meta-data and activity start -->
        <meta-data android:name="com.google.android.gms.version"
                  android:value="@integer/google_play_services_version"/>
        <activity android:name="com.google.android.gms.ads.AdActivity"

             android:configChanges=

"keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"/>
         <!-- Admob meta-data and activity end -->

       
    </application>

    <supports-screens android:anyDensity="true"
                      android:smallScreens="true"
                      android:normalScreens="true"
                      android:largeScreens="true"
                      android:xlargeScreens="true"/>

    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
</manifest>

 

 

6. 그럼 아까 설명에서 내 디바이스 번호를 어떻게 알아내느냐?

 

그것은 이클립스에서 스마트폰으로 포팅할때

LogCat 화면에서 내 디바이스 번호를 확인할수 있습니다.

 

포팅준비

 

1. 포팅 할때 우선 visual studio에서 폴더를 일단 빌드 합니다.
2. build_native.py 를 실행한다

(이클립스에서 보이는거 실행해도 되고, cmd창으로 proj.android 안에 있는 builde_native.py를 실행하면 됨)

3. addTestDevice 함수에 아무 문자열이나 넣는다 ex) addTestDevice("test");

4. 스마트폰을 usb로 연결하고 프로젝트 Run As 를 시킨다.

 

사진에 보시는것처럼 로그켓에 내 디바이스 번호가 뜨게됩니다.

저 번호를 addTestDevice 안에 문자열로 적어주시면 됩니다.

 

 

거의 마무리인데요.

.addTestDevice 이 함수를 테스트버전에서 사용할때 이것을 사용하지 않으면.. 뭐 애드몹이 정지를 먹을수도 잇다고 합니다.. (테스트라는걸 반드시 상기시켜줘야하는건가..? 뭐 확실치는 않음...)

 

그리고 정식 배포용으로써 광고를 달게 될때는 .addTestDevice 함수는 사용하지 않는다고 합니다. 즉 삭제를 하라 이말이죠.

 

   AdRequest adRequest = new AdRequest.Builder()
  .addTestDevice(AdRequest.DEVICE_ID_EMULATOR) //삭제
  .addTestDevice("455611DB7112DF5A280975818FA14B5C") //삭제

 

그리고 앞에서

private static final String AD_UNIT_ID = "ca-app-pub-0000000000000000/0000000000";

이부분을 앞에 게시자 ID 값을 주지않고 저렇게 다 0으로 해버리면 광고가 뜨지 않습니다.

혹여나 이렇게 하고 안뜬다고 고민 하지마세요.

 

 

 

정상적으로 포팅이 되셨으면 아래 사진과 같이 광고가 나옵니다

View 를 누르면 광고가 나오고 Hide를 누르면 광고가 사라지고 ㅇㅇㅇ

 

 

 

728x90
Posted by 정망스
,


맨 위로
홈으로 ▲위로 ▼아래로 ♥댓글쓰기 새로고침