간단한 요청 보내기

Cronet 라이브러리를 사용하여 Android 앱에서 네트워크 작업을 실행하는 방법을 알아봅니다. Cronet은 앱에서 사용할 수 있는 라이브러리로 제공되는 Chromium 네트워크 스택입니다. 라이브러리 기능에 관한 자세한 내용은 Cronet을 사용하여 네트워크 작업 실행을 참고하세요.

프로젝트에서 라이브러리 설정

프로젝트의 Cronet 라이브러리에 종속성을 추가하려면 다음 단계를 따르세요.

  1. 다음 예와 같이 Android 스튜디오가 프로젝트의 settings.gradle 파일에 Google의 Maven 저장소 참조를 포함했는지 확인합니다.

    Groovy

    dependencyResolutionManagement {
       ...
       repositories {
           ...
           google()
       }
    }
    

    Kotlin

    dependencyResolutionManagement {
       ...
       repositories {
           ...
           google()
       }
    }
    
  2. 다음 예와 같이 앱 모듈 build.gradle 파일의 dependencies 섹션에 Cronet용 Google Play 서비스 클라이언트 라이브러리 참조를 포함합니다.

    Groovy

    dependencies {
       implementation 'com.google.android.gms:play-services-cronet:18.0.1'
    }
    

    Kotlin

    dependencies {
       implementation("com.google.android.gms:play-services-cronet:18.0.1")
    }
    

이 종속 항목이 추가된 후 생성된 CronetEngine 객체는 Google Play 서비스에서 로드된 Cronet을 사용합니다. 기기에 업데이트된 버전의 Google Play 서비스가 필요한 등의 오류로 인해 CronetEngine 생성 중에 예기치 않은 예외가 발생하지 않도록 CronetEngine 객체를 만들기 전에 CronetProviderInstaller.installProvider(Context)를 호출합니다.

Google Play 서비스에서 Cronet을 로드할 수 없는 경우 Cronet API의 성능이 저하된 구현을 사용할 수 있습니다. 이 대체 구현을 사용하려면 org.chromium.net:cronet-fallback에 종속되고 new JavaCronetProvider(context).createBuilder()를 호출합니다.

네트워크 요청 만들기

이 섹션에서는 Cronet 라이브러리를 사용하여 네트워크 요청을 만들고 전송하는 방법을 보여줍니다. 네트워크 요청을 전송한 후 앱에서는 네트워크 응답을 처리해야 합니다.

CronetEngine 인스턴스 만들기 및 구성

라이브러리는 CronetEngine 인스턴스를 만드는 데 사용할 수 있는 CronetEngine.Builder 클래스를 제공합니다. 다음 예는 CronetEngine 객체를 만드는 방법을 보여줍니다.

Kotlin

val myBuilder = CronetEngine.Builder(context)
val cronetEngine: CronetEngine = myBuilder.build()

Java

CronetEngine.Builder myBuilder = new CronetEngine.Builder(context);
CronetEngine cronetEngine = myBuilder.build();

Builder 클래스를 사용하여 CronetEngine 객체를 구성할 수 있습니다. 예를 들어 캐싱 및 데이터 압축과 같은 옵션을 제공할 수 있습니다. 자세한 내용은 CronetEngine.Builder를 참고하세요.

요청 콜백의 구현 제공

콜백 구현을 제공하려면 다음 예와 같이 UrlRequest.Callback의 서브클래스를 만들고 필요한 추상 메서드를 구현합니다.

Kotlin

private const val TAG = "MyUrlRequestCallback"

class MyUrlRequestCallback : UrlRequest.Callback() {
    override fun onRedirectReceived(request: UrlRequest?, info: UrlResponseInfo?, newLocationUrl: String?) {
        Log.i(TAG, "onRedirectReceived method called.")
        // You should call the request.followRedirect() method to continue
        // processing the request.
        request?.followRedirect()
    }

    override fun onResponseStarted(request: UrlRequest?, info: UrlResponseInfo?) {
        Log.i(TAG, "onResponseStarted method called.")
        // You should call the request.read() method before the request can be
        // further processed. The following instruction provides a ByteBuffer object
        // with a capacity of 102400 bytes for the read() method. The same buffer
        // with data is passed to the onReadCompleted() method.
        request?.read(ByteBuffer.allocateDirect(102400))
    }

    override fun onReadCompleted(request: UrlRequest?, info: UrlResponseInfo?, byteBuffer: ByteBuffer?) {
        Log.i(TAG, "onReadCompleted method called.")
        // You should keep reading the request until there's no more data.
        byteBuffer.clear()
        request?.read(byteBuffer)
    }

    override fun onSucceeded(request: UrlRequest?, info: UrlResponseInfo?) {
        Log.i(TAG, "onSucceeded method called.")
    }
}

Java

class MyUrlRequestCallback extends UrlRequest.Callback {
  private static final String TAG = "MyUrlRequestCallback";

  @Override
  public void onRedirectReceived(UrlRequest request, UrlResponseInfo info, String newLocationUrl) {
    Log.i(TAG, "onRedirectReceived method called.");
    // You should call the request.followRedirect() method to continue
    // processing the request.
    request.followRedirect();
  }

  @Override
  public void onResponseStarted(UrlRequest request, UrlResponseInfo info) {
    Log.i(TAG, "onResponseStarted method called.");
    // You should call the request.read() method before the request can be
    // further processed. The following instruction provides a ByteBuffer object
    // with a capacity of 102400 bytes for the read() method. The same buffer
    // with data is passed to the onReadCompleted() method.
    request.read(ByteBuffer.allocateDirect(102400));
  }

  @Override
  public void onReadCompleted(UrlRequest request, UrlResponseInfo info, ByteBuffer byteBuffer) {
    Log.i(TAG, "onReadCompleted method called.");
    // You should keep reading the request until there's no more data.
    byteBuffer.clear();
    request.read(byteBuffer);
  }

  @Override
  public void onSucceeded(UrlRequest request, UrlResponseInfo info) {
    Log.i(TAG, "onSucceeded method called.");
  }
}

Executor 객체를 만들어 네트워크 작업 관리

Executor 클래스를 사용하여 네트워크 작업을 실행할 수 있습니다. Executor의 인스턴스를 가져오려면 Executor 객체를 반환하는 Executors 클래스의 정적 메서드 중 하나를 사용합니다. 다음 예시에서는 newSingleThreadExecutor() 메서드를 사용하여 Executor 객체를 만드는 방법을 보여줍니다.

Kotlin

val executor: Executor = Executors.newSingleThreadExecutor()

Java

Executor executor = Executors.newSingleThreadExecutor();

UrlRequest 객체 만들기 및 구성

네트워크 요청을 만들려면 도착 URL, 콜백 클래스의 인스턴스, 실행자 객체를 전달하는 CronetEnginenewUrlRequestBuilder() 메서드를 호출합니다. newUrlRequestBuilder() 메서드는 다음 예와 같이 UrlRequest 객체를 만드는 데 사용할 수 있는 UrlRequest.Builder 객체를 반환합니다.

Kotlin

val requestBuilder = cronetEngine.newUrlRequestBuilder(
        "https://www.example.com",
        MyUrlRequestCallback(),
        executor
)

val request: UrlRequest = requestBuilder.build()

Java

UrlRequest.Builder requestBuilder = cronetEngine.newUrlRequestBuilder(
        "https://www.example.com", new MyUrlRequestCallback(), executor);

UrlRequest request = requestBuilder.build();

Builder 클래스를 사용하여 UrlRequest의 인스턴스를 구성할 수 있습니다. 예를 들어 우선순위 또는 HTTP 동사를 지정할 수 있습니다. 자세한 내용은 UrlRequest.Builder를 참고하세요.

네트워크 작업을 시작하려면 요청의 start() 메서드를 호출합니다.

Kotlin

request.start()

Java

request.start();

이 섹션의 안내에 따라 Cronet을 사용하여 네트워크 요청을 만들고 전송할 수 있습니다. 그러나 편의상 UrlRequest.Callback 구현 예에서는 로그에 메시지만 출력합니다. 다음 섹션에서는 응답에서 데이터를 추출하고 요청의 실패를 감지하는 등 더 유용한 시나리오를 지원하는 콜백 구현을 제공하는 방법을 보여줍니다.

네트워크 응답 처리

start() 메서드를 호출하면 Cronet 요청 수명 주기가 시작됩니다. 앱은 콜백을 지정하여 수명 주기 동안 요청을 관리해야 합니다. 수명 주기에 관한 자세한 내용은 Cronet 요청 수명 주기를 참조하세요. UrlRequest.Callback의 서브클래스를 만들고 다음 메서드를 구현하여 콜백을 지정할 수 있습니다.

onRedirectReceived()

서버가 원래 요청에 대한 응답으로 HTTP 리디렉션 코드를 발행할 때 호출됩니다. 새 대상으로의 리디렉션을 따르려면 followRedirect() 메서드를 사용합니다. 그 외의 경우에는 cancel() 메서드를 사용합니다. 다음 예에서는 메서드를 구현하는 방법을 보여줍니다.

Kotlin

override fun onRedirectReceived(request: UrlRequest?, info: UrlResponseInfo?, newLocationUrl: String?) {
  // Determine whether you want to follow the redirect.
  ...

  if (shouldFollow) {
      request?.followRedirect()
  } else {
      request?.cancel()
  }
}

Java

@Override
public void onRedirectReceived(UrlRequest request, UrlResponseInfo info, String newLocationUrl) {
  // Determine whether you want to follow the redirect.
  …

  if (shouldFollow) {
    request.followRedirect();
  } else {
    request.cancel();
  }
}
onResponseStarted()

헤더의 마지막 집합이 수신될 때 호출됩니다. onResponseStarted() 메서드는 모든 리디렉션을 따른 후에만 호출됩니다. 다음 코드는 메서드의 구현 예를 보여줍니다.

Kotlin

override fun onResponseStarted(request: UrlRequest?, info: UrlResponseInfo?) {
  val httpStatusCode = info?.httpStatusCode
  if (httpStatusCode == 200) {
    // The request was fulfilled. Start reading the response.
    request?.read(myBuffer)
  } else if (httpStatusCode == 503) {
    // The service is unavailable. You should still check if the request
    // contains some data.
    request?.read(myBuffer)
  }
  responseHeaders = info?.allHeaders
}

Java

@Override
public void onResponseStarted(UrlRequest request, UrlResponseInfo info) {
  int httpStatusCode = info.getHttpStatusCode();
  if (httpStatusCode == 200) {
    // The request was fulfilled. Start reading the response.
    request.read(myBuffer);
  } else if (httpStatusCode == 503) {
    // The service is unavailable. You should still check if the request
    // contains some data.
    request.read(myBuffer);
  }
  responseHeaders = info.getAllHeaders();
}
onReadCompleted()

응답 본문의 일부를 읽을 때마다 호출됩니다. 다음 코드 예에서는 메서드를 구현하고 응답 본문을 추출하는 방법을 보여줍니다.

Kotlin

override fun onReadCompleted(request: UrlRequest?, info: UrlResponseInfo?, byteBuffer: ByteBuffer?) {
  // The response body is available, process byteBuffer.
  ...

  // Continue reading the response body by reusing the same buffer
  // until the response has been completed.
  byteBuffer?.clear()
  request?.read(myBuffer)
}

Java

@Override
public void onReadCompleted(UrlRequest request, UrlResponseInfo info, ByteBuffer byteBuffer) {
  // The response body is available, process byteBuffer.
  …

  // Continue reading the response body by reusing the same buffer
  // until the response has been completed.
  byteBuffer.clear();
  request.read(myBuffer);
}
onSucceeded()

네트워크 요청이 성공적으로 완료되면 호출됩니다. 다음 예는 메서드를 구현하는 방법을 보여줍니다.

Kotlin

override fun onSucceeded(request: UrlRequest?, info: UrlResponseInfo?) {
    // The request has completed successfully.
}

Java

@Override
public void onSucceeded(UrlRequest request, UrlResponseInfo info) {
  // The request has completed successfully.
}
onFailed()

start() 메서드가 호출된 후 어떤 이유로든 요청이 실패하면 호출됩니다. 다음 예는 메서드를 구현하고 오류에 관한 정보를 가져오는 방법을 보여줍니다.

Kotlin

override fun onFailed(request: UrlRequest?, info: UrlResponseInfo?, error: CronetException?) {
    // The request has failed. If possible, handle the error.
    Log.e(TAG, "The request failed.", error)
}

Java

@Override
public void onFailed(UrlRequest request, UrlResponseInfo info, CronetException error) {
  // The request has failed. If possible, handle the error.
  Log.e(TAG, "The request failed.", error);
}
onCanceled()

cancel() 메서드를 사용하여 요청이 취소되면 호출됩니다. 호출된 후에는 UrlRequest.Callback 클래스의 다른 메서드가 호출되지 않습니다. 이 메서드를 사용하면 요청을 처리하도록 할당된 리소스를 확보할 수 있습니다. 다음 예에서는 메서드를 구현하는 방법을 보여줍니다.

Kotlin

override fun onCanceled(request: UrlRequest?, info: UrlResponseInfo?) {
    // Free resources allocated to process this request.
    ...
}

Java

@Override
public void onCanceled(UrlRequest request, UrlResponseInfo info) {
  // Free resources allocated to process this request.
  …
}