출처 : http://crowjdh.blogspot.kr/2013/11/v3.html

Ch1. 준비

0. Android SDK Manager -> Extras -> Google Play Billing Library 다운받고 설치한다.

1. Google Play Developer Console 여기로 가서 내 앱 추가

 - Prepare Store Listing 상태로 추가.

2. <SDK Path>/extras/google/play_billing/IInAppBillingService.aidl 파일을 프로젝트의 com.android.vending.billing 에 복사한다.

3. <SDK Path>/extras/google/play_billing/samples/

TrivialDrive/src/com/example/android/trivialdrivesample/util 의 클래스들을 내 프로젝트의 적절한 곳으로 복사한다.

*패키지명은 내 프로젝트 패키지 하위 패키지로 설정한다.

4. 메니페스트 파일의 <manifest>태그 아래에

<uses-permission android:name="com.android.vending.BILLING" />

퍼미션을 추가한다.

5. 인앱빌링을 사용하고자 하는 액티비티의 onCreate내에서 IabHelper 인스턴스를 생성한다. 이때 넘겨주는 license key는 아래와 같은 방법으로 구성, 보안을 높이는 것을 추천한다.

*license key는

Google Play Developer Console -> 위 1에서 등록한 내 어플리케이션 -> Services & APIs

여기에서 확인한다.

Security Recommendation: It is highly recommended that you do not hard-code the exact public license key string value as provided by Google Play. Instead, you can construct the whole public license key string at runtime from substrings, or retrieve it from an encrypted store, before passing it to the constructor. This approach makes it more difficult for malicious third-parties to modify the public license key string in your APK file.

6. IabHelper인스턴스에 startSetup메소드에 콜백 등록하자. (http://developer.android.com/training/in-app-billing/preparing-iab-app.html#Connect 참조)

6.1 해당 액티비티에서 인앱결제가 완료됐을 경우

@Override

public void onDestroy() {

   super.onDestroy();

   if (mHelper != null) mHelper.dispose();

   mHelper = null;

}

이처럼 연결을 해제한다.

* 연결이 실패할 경우 IabHelper 클래스의 dispose() 메서드 내에서 에러가 나는 경우가 있다.

연결이 실패할 경우 startSetup 메서드에서 mServiceConn 객체 인스턴스를 만들 때 onServiceDisconnected 콜백이 불리면 mService 을 null로 만들어준다.

if (mContext != null) mContext.unbindService(mServiceConn);

위의 줄을

if (mContext != null && mService != null) mContext.unbindService(mServiceConn);

위처럼 바꾸자.

7.1 릴리즈용 키스토어를 사용해 사인된 apk파일을 생성한다.(디버그용 키스토어어는 안됨)

(http://www.androidpub.com/35445 참조)

* conversion to dalvik format failed with error 1 에러 발생시

project properties -> java build path -> Libraries

에서 의심가는 라이브러리를 제거하고 다시 추가해보자.

android-support-v4.jar을 업데이트한 후에 이 에러가 발생할 수 있다.

* 자신의 프로젝트나 라이브러리로 임포트한 프로젝트의 values/strings.xml 파일에서 Missing Translation 이라는 린트 에러가 날 때는

1. 아직 번역이 덜 끝났을 경우 :

<resources

   xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">

위 처럼 우선 무시하고 번역이 끝났을 경우 번역을 추가하고 위의 속성을 제거한다.

2. 번역이 필요없는 문자열의 경우 :

<string name="hello" translatable="false">hello</string>

위 처럼 translatable=”false”라는 속성을 주자.

7.2 Google Play Developer Console -> 위 1에서 등록한 내 어플리케이션 -> APK탭

에 들어가서 APK 업로드하기기(퍼블리시 하지 않는다)

7.3 Google Play Developer Console -> 위 1에서 등록한 내 어플리케이션 -> In-app Products

에 들어가서 새 제품을 추가하고 continue를 누른다.

*Type : Managed product를 선택한다.(일반적인 소모성 아이템의 경우)

*Product Id : application에서 이 아이템을 특정하는 데에 필요한 아이디를 입력.

(네이밍 규칙은 https://support.google.com/googleplay/android-developer/answer/1072599?hl=ko 여기를 참조)

7.4 추가 정보 입력 후 위의 save버튼 옆 inactive 버튼을 눌러 active로 바꿔준다.

*Warning: It may take up to 2-3 hours after uploading the APK for Google Play to recognize your updated APK version. If you try to test your application before your uploaded APK is recognized by Google Play, your application will receive a ‘purchase cancelled’ response with an error message “This version of the application is not enabled for In-app Billing.”

Ch.2 구현

인앱 구매에서 일반적으로 필요한 시나리오는 다음과 같다.

(아래는 모두 셋업이 끝난 후, 즉 IabHelper.startSetup(OnIabSetupFinishedListener listener)의 콜백에서 result.isSuccess()가 true를 반환한 경우에 해야 한다.)

1. 내가 등록한 아이템의 정보(이름, 가격 등의 세부 정보)를 알아오기.

2. 구매 절차

일반적으로 OnIabSetupFinishedListener에서 위 1을 수행해 아이템의 이름과 가격을 가져오고 난 뒤 그 정보를 유저에게 보여준다. 유저가 구매 버튼을 누른 경우 위 2를 수행한다.

1. 아이템 확인

1. Ch.1 - 6의 startSetup메소드의 결과 연결이 수립된 후 불리는 OnIabSetupFinishedListener에서 아래와 같이 인앱제품의 세부사항을 요청할 수 있다.

인앱 제품의 sku(고유 아이디. 위 Ch.1 - 7.3 참고)를 리스트에 넣고 인벤토리의 정보를 요청한다.

List<String> additionalSkuList = new ArrayList<String>();

additionalSkuList.add(IAB.SKU_BG_RED);

additionalSkuList.add(IAB.SKU_BG_YELLOW);

mHelper.queryInventoryAsync(true, additionalSkuList,mQueryFinishedListener);

2. 세부사항 요청의 결과를 받아올 콜백 메소드를 선언하자. 위에서 요청한 인벤토리의 정보가 아래의 콜백으로 들어온다.

private IabHelper.QueryInventoryFinishedListener

           mQueryFinishedListener = new IabHelper.QueryInventoryFinishedListener() {

           public void onQueryInventoryFinished(IabResult result, Inventory inventory)  

           {

              if (result.isFailure()) {

                 // handle error

                 return;

               }

               String redPrice =

                  inventory.getSkuDetails(IAB.SKU_BG_RED).getPrice();

               String yellowPrice =

                  inventory.getSkuDetails(IAB.SKU_BG_YELLOW).getPrice();

               // update the UI

               TextView resultView = (TextView)findViewById(R.id.result);

               resultView.setText("red price : " + redPrice + ", yellow price : " + yellowPrice);

           }

        };

2. 아이템 구매

1. 아이템 구매 요청을 날리기 전 액티비티의 onActivityResult에서 아래와 같은 처리를 해야 한다.

빨간 색으로 하이라이트한 부분이 중요하다. 이 부분을 처리해주지 않으면 정상적으로 구매절차가 이뤄지지 않는다.

@Override

    protected void onActivityResult(int requestCode, int resultCode, Intent data) {

        LogUtil.message(TAG, "requestCode : " + requestCode + ", resultCode : " + resultCode + ", data : " + data);

        if (!mHelper.handleActivityResult(requestCode, resultCode, data)) {

            // not handled, so handle it ourselves (here's where you'd

            // perform any handling of activity results not related to in-app

            // billing...

            super.onActivityResult(requestCode, resultCode, data);

        }

        else {

            Log.d(TAG, "onActivityResult handled by IABUtil.");

        }

    }

2. 위에서 인벤토리의 정보를 가져온 후 유저가 구매버튼을 누르면 아래의 메서드를 실행, 구매절차를 수행한다.

mHelper.launchPurchaseFlow(MarketAct.this, IAB.SKU_BG_RED, IabHelper.ITEM_TYPE_INAPP, RC_REQUEST, mPurchaseFinishedListener, "test payload");

인자값들

1) 엑티비티 인스턴스

2) 구매할 인앱 아이템 ID(SKU)

3) 아이템의 종류.

1. 일반 인앱 아이템 : IabHelper.ITEM_TYPE_INAPP

2. 정기구독 : IabHelper.ITEM_TYPE_SUBS

4) 임의 정수. 구매과정이 끝나면 onActivityResult의 requestCode로 반환된다. 자세한 내용은 후에 적는다.

5) 구매 종료 후 불려질 콜백. 여기서 상황에 따라 데이터와 UI를 업데이트 해준다.

6) ***

https://play.google.com/apps/publish/

1. All applications에 들어가서 테스트할 어플리케이션이 등록되어 있는지 확인.

2. Setting -> Account details

에서 Gmail accounts with testing access 에 자신이 사용하는 디바이스의 기본 계정을 추가한다.

* 기본 계정을 변경하려면 디바이스를 공장초기화하고 등록해야 한다(고 한다).

3. ch.1 - 7.1 ~ 7.2의 과정을 거친 apk파일을 올려야 테스트 구매를 할 수 있다. 릴리즈용으로 사인된 apk를 업로드하자.

(서버측의 인증은 대중 없다. 새로 apk를 올린 후 정상적으로 인앱 확인, 구매를 하려면 15분 정도 소요된다고는 하지만 테스트결과 주말의 경우 하루가 지나야 인증되는 경우도 있었다.)

4. 마찬가지로 이클립스에서 실행한 앱으로는 테스트 구매를 할 수 없다. 위 3번 단계에서 사인한 apk를 디바이스에 직접 설치하자.

*명령어(Mac OS 기준) :

언인스톨 : <sdk path>/platform-tools/adb [-s 디바이스 번호] uninstall 패키지명

인스톨 : <sdk path>/platform-tools/adb [-s 디바이스 번호] install 파일이름.apk

*디바이스 번호는

<sdk path>/platform-tools/adb devices

로 확인할 수 있다. 여러 개의 디바이스가 연결된 상황이 아니라면 이 옵션은 무시해도 좋다.

3. 아이템 소모

소모성 아이템의 경우 아이템을 사용하거나 앱이 구동될 때 체크하는 것이 좋다.

앱이 구동될 때 체크하는 이유는 소모성 아이템은 구입 즉시 유저에게 제공해야 하기 때문이다. 만약 소모성 아이템이 구글 플레이 서버에 남아있다면 유저에게 제공되지 않았다는 것을 뜻한다.

또한 소모성 아이템은 구글 플레이 서버에 소모 요청을 하지 않으면 다시 구매할 수 없기도 하므로 꼭 소모해주자.

mHelper.consumeAsync(purchase, mConsumeFinishedListener);

1) 소모할 아이템의 Purchase객체

2) 콜백. 변경된 데이터 반영과 UI 업데이트.

부록 2. 참고 문서

API Document

http://developer.android.com/google/play/billing/index.html

Lesson

http://developer.android.com/training/in-app-billing/index.html

Managing application

https://play.google.com/apps/publish/

Handling In-app-purchase orders

https://wallet.google.com/merchant/



+ Recent posts