Version: 2017.1
アプリケーションでの"アプリ内課金" の準備
App Thinning

iOS の WWW リクエストをカスタマイズ

WWW クラスでリクエストを処理するときに Unity が使うデフォルトのコードを置き換えるには、プラグインを使いきます。 例えは、URL だけに基づいてキャッシュするデフォルトのキャッシュの挙動を変えることができます。

以下のコードは (詳細は後述を参照)、デフォルトのキャッシュの方法を無効にし、ゲームのスクリプトコードから特定したヘッダーに加え、「秘密」のヘッダーフィールドをリクエストに追加します。

    // Asset フォルダー内の Plugins/iOS/CustomConnection.mm のコード

        #include "Unity/WWWConnection.h"

        @interface UnityWWWCustomRequestProvider : UnityWWWRequestDefaultProvider
        {
        }
        + (NSMutableURLRequest*)allocRequestForHTTPMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary*)headers;
        @end

        @implementation UnityWWWCustomRequestProvider
        + (NSMutableURLRequest*)allocRequestForHTTPMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary*)headers
        {
            NSMutableURLRequest* request = [super allocRequestForHTTPMethod:method url:url headers:headers];

            // 安全上の理由でキャッシュ、クッキーをまったく使いたくない、としましょう
            request.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
            [request setHTTPShouldHandleCookies:NO];

            // ヘッダーに特別な秘密の (secret) 情報が必要だということにしましょう
            [request setValue:@"123456789"forHTTPHeaderField:@"Secret"];

            return request;
        }
        @end

        @interface UnityWWWCustomConnectionDelegate : UnityWWWConnectionDelegate
        {
        }
        @end

        @implementation UnityWWWCustomConnectionDelegate
        - (NSCachedURLResponse*)connection:(NSURLConnection*)connection willCacheResponse:(NSCachedURLResponse*)cachedResponse
        {
            // キャッシュは必要ありません
            return nil;
        }
        - (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse*)response
        {
            // テストのために、ここに何かをプリントしてみましょう
            [super connection:connection didReceiveResponse:response];
            if([response isMemberOfClass:[NSHTTPURLResponse class]])
                ::printf_console("We've got response with status: %d\n", [(NSHTTPURLResponse*)response statusCode]);
        }
        @end

        IMPL_WWW_DELEGATE_SUBCLASS(UnityWWWCustomConnectionDelegate);
        IMPL_WWW_REQUEST_PROVIDER(UnityWWWCustomRequestProvider);

先ほどのコードを詳しく説明していきます。まず、UnityWWWRequestDefaultProvider のサブクラスを作成し、接続のための変更した NSURLRequest オブジェクトを提供します。他の方法は単に、クラスに UnityWWWRequestProvider プロトコルを初めから実装するというものです。ただし、この場合は Unity の既存コードを使用します。

    @interface UnityWWWCustomRequestProvider : UnityWWWRequestDefaultProvider
        {
        }
        + (NSMutableURLRequest*)allocRequestForHTTPMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary*)headers;
        @end

スーパークラス上の同じメソッドを呼び出すことによって allocRequestForHTTPMethod のアクションが開始されます。

    @implementation UnityWWWCustomRequestProvider
        + (NSMutableURLRequest*)allocRequestForHTTPMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary*)headers
        {
            NSMutableURLRequest* request = [super allocRequestForHTTPMethod:method url:url headers:headers];

それから、iOS がキャッシュするデフォルトデータとクッキーを無効にします。

    request.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
        [request setHTTPShouldHandleCookies:NO];

次に “Secret” という名のいくらかデータを追加できるヘッダーフィールドを加えます。実際のゲーム中は、接続のソースが正しいかどうかを確かめるために、この値がサーバーからチェックされる事があります。

    [request setValue:@"123456789"forHTTPHeaderField:@"Secret"];

カスタムリクエストのハンドリングクラスを作成すると、さらにUnityWWWConnectionDelegate のサブクラスを作成して接続の処理をカスタマイズする必要があります。

    @interface UnityWWWCustomConnectionDelegate : UnityWWWConnectionDelegate
        {
        }
        @end

connection:willCacheResponse: メソッドから nil を返すことにより、データのキャッシュを無効にすることができます。

    - (NSCachedURLResponse*)connection:(NSURLConnection*)connection willCacheResponse:(NSCachedURLResponse*)cachedResponse
        {
            // キャッシュは必要ありません
            return nil;
        }

connection:didReceiveResponse: から接続自体を処理することができます。connection:didReceiveResponse: は実際のデータを取得するためにスーパークラスの同じメソッドを呼び出します。ここでは、接続が発生したときに、単にメッセージをコンソールに出力するだけですが、任意に実装できます。

    - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
        {
            // テストのために、ここに何かをプリントしてみましょう
            [super connection:connection didReceiveResponse:response];
            if([response isMemberOfClass:[NSHTTPURLResponse class]])
                ::printf_console("We've got response with status: %d\n", [(NSHTTPURLResponse*)response statusCode]);
        }

最後に、新しい接続のデリゲートとリクエストプロバイダーを Unity に登録します。そうすると、スクリプトから WWW リクエストを呼び出す時は常に、デリゲートとリクエストプロバイダーが呼び出されます。

    IMPL_WWW_DELEGATE_SUBCLASS(UnityWWWCustomConnectionDelegate);
        IMPL_WWW_REQUEST_PROVIDER(UnityWWWCustomRequestProvider);

WWW クラスを Unity で使用するときにカスタムコードに影響されることはなく、余分な C#/JS スクリプトを追加する必要はありません。

アプリケーションでの"アプリ内課金" の準備
App Thinning