

# Casos de uso avançados para o SDK de Transmissão para Android do IVS \| Streaming de baixa latência
<a name="broadcast-android-use-cases"></a>

Aqui, apresentamos alguns casos de uso avançados. Comece com a configuração básica acima e continue aqui. 

## Criar uma configuração de transmissão do Android
<a name="broadcast-android-create-configuration"></a>

Aqui, criamos uma configuração personalizada com dois slots de mixer que nos permitem vincular duas fontes de vídeo ao mixer. Um deles (`custom`) é tela cheia e fica posicionado atrás do outro (`camera`), que é menor e está localizado no canto inferior direito. Para o slot `custom`, não definimos uma posição, um tamanho ou um modo de aspecto. Como não definimos esses parâmetros, o slot usará as configurações de vídeo para tamanho e posição.

```
BroadcastConfiguration config = BroadcastConfiguration.with($ -> {
    $.audio.setBitrate(128_000);
    $.video.setMaxBitrate(3_500_000);
    $.video.setMinBitrate(500_000);
    $.video.setInitialBitrate(1_500_000);
    $.video.setSize(1280, 720);
    $.mixer.slots = new BroadcastConfiguration.Mixer.Slot[] {
            BroadcastConfiguration.Mixer.Slot.with(slot -> {
                // Do not automatically bind to a source
                slot.setPreferredAudioInput(
                           Device.Descriptor.DeviceType.UNKNOWN);
                // Bind to user image if unbound
                slot.setPreferredVideoInput(
                           Device.Descriptor.DeviceType.USER_IMAGE);
                slot.setName("custom");
                return slot;
            }),
            BroadcastConfiguration.Mixer.Slot.with(slot -> {
                slot.setzIndex(1);
                slot.setAspect(BroadcastConfiguration.AspectMode.FILL);
                slot.setSize(300, 300);
                slot.setPosition($.video.getSize().x - 350,
                        $.video.getSize().y - 350);
                slot.setName("camera");
                return slot;
            })
    };
    return $;
});
```

## Criar a sessão de transmissão (versão avançada)
<a name="broadcast-android-create-session-advanced"></a>

Crie uma `BroadcastSession`, como fez no [exemplo básico](broadcast-android-getting-started.md#broadcast-android-create-session), mas forneça sua configuração personalizada aqui. Forneça também `null` para a matriz de dispositivos, pois vamos adicioná-los manualmente.

```
// Create a broadcast-session instance and sign up to receive broadcast
// events and errors.
Context ctx = getApplicationContext();
broadcastSession = new BroadcastSession(ctx,
                       broadcastListener,
                       config, // The configuration we created above
                       null); // We’ll manually attach devices after
```

## Iterar e anexar um dispositivo de câmera
<a name="broadcast-android-attach-camera"></a>

Aqui nós fazemos a iteração por meio dos dispositivos de entrada que o SDK detectou. No Android 7 (Nougat), retornará apenas dispositivos de microfone padrão, pois o Amazon IVS Broadcast SDK não é compatível com a seleção de dispositivos não padrão nesta versão do Android.

Depois de encontrarmos um dispositivo que queremos usar, chamamos `attachDevice` para anexá-lo. Uma função lambda é chamada no thread principal quando o dispositivo de entrada termina de ser anexado. Em caso de falha, você receberá um erro no listener.

```
for(Device.Descriptor desc: BroadcastSession.listAvailableDevices(getApplicationContext())) {
    if(desc.type == Device.Descriptor.DeviceType.CAMERA &&
            desc.position == Device.Descriptor.Position.FRONT) {
        session.attachDevice(desc, device -> {
            LinearLayout previewHolder = findViewById(R.id.previewHolder);
            ImagePreviewView preview = ((ImageDevice)device).getPreviewView();
            preview.setLayoutParams(new LinearLayout.LayoutParams(
                    LinearLayout.LayoutParams.MATCH_PARENT,
                    LinearLayout.LayoutParams.MATCH_PARENT));
            previewHolder.addView(preview);
            // Bind the camera to the mixer slot we created above.
            session.getMixer().bind(device, "camera");
        });
        break;
    }
}
```

## Trocar câmeras
<a name="broadcast-android-swap-cameras"></a>

```
// This assumes you’ve kept a reference called "currentCamera" that points to
// a front facing camera
for(Device device: BroadcastSession.listAvailableDevices()) {
   if(device.type == Device.Descriptor.DeviceType.CAMERA &&
          Device.position != currentCamera.position) {
        // Remove the preview view for the old device.
        // setImagePreviewTextureView is an example function 
        // that handles your view hierarchy.
        setImagePreviewView(null);
        session.exchangeDevices(currentCamera, device, camera -> {
             // Set the preview view for the new device.
             setImagePreviewView(camera.getPreviewView());
             currentCamera = camera;
        });
        break;
   }
}
```

## Criar uma superfície de entrada
<a name="broadcast-android-create-input-surface"></a>

Para inserir dados de som ou imagem gerados pela aplicação, use `createImageInputSource` ou `createAudioInputSource`. Os dois métodos criam e anexam dispositivos virtuais que podem ser vinculados ao mixer como qualquer outro dispositivo.

O `SurfaceSource` retornado por `createImageInputSource` tem um método `getInputSurface`, que dará a você um `Surface` que poderá ser utilizado com a API do Camera2, o OpenGL, o Vulkan ou qualquer outra coisa que possa gravar em Surface.

O `AudioDevice` retornado por `createAudioInputSource` pode receber dados de PCM linear gerados pelo AudioRecorder ou por outros meios.

```
SurfaceSource source = session.createImageInputSource();
Surface surface = source.getInputSurface();
session.getMixer().bind(source, “custom”);
```

## Desconectar um dispositivo
<a name="broadcast-android-detach-device"></a>

Se você deseja desconectar e não substituir um dispositivo, desconecte-o com `Device` ou `Device.Descriptor`.

```
session.detachDevice(currentCamera);
```

## Captura de tela e de áudio de sistema
<a name="broadcast-android-screen-audio-capture"></a>

O Amazon IVS Broadcast SDK for Android inclui alguns ajudantes que simplificam a captura de tela do dispositivo (Android 6 e posteriores) e áudio do sistema (Android 10 e posteriores). Se quiser gerenciá-los manualmente, você pode criar uma fonte de entrada de imagem personalizada e uma fonte de entrada de áudio personalizada.

Para criar uma sessão de captura de tela e de áudio de sistema, primeiro é necessário criar uma intenção de solicitação de permissão:

```
public void startScreenCapture() {
    MediaProjectionManager manager =
                         (MediaProjectionManager) getApplicationContext()
                         .getSystemService(Context.MEDIA_PROJECTION_SERVICE);
    if(manager != null) {
        Intent intent = manager.createScreenCaptureIntent();
        startActivityIfNeeded(intent, SCREEN_CAPTURE_REQUEST_ID);
    }
}
```

Para usar esse recurso, é necessário fornecer uma classe que estenda `com.amazonaws.ivs.broadcast.SystemCaptureService`. Não é necessário substituir nenhum de seus métodos, mas a classe precisa estar lá para evitar possíveis colisões entre serviços.

Você também deve adicionar alguns elementos a seu manifesto do Android:

```
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application ...>
    <service android:name=".ExampleSystemCaptureService"
         android:foregroundServiceType="mediaProjection" 
         android:isolatedProcess="false" />
</application>
...
```

Sua classe que se estende `SystemCaptureService` deve ser nomeada no elemento `<service>`. No Android 9 e posteriores, o `foregroundServiceType` deve ser `mediaProjection`.

Depois que a intenção das permissões for retornada, será possível prosseguir com a criação da sessão de captura de tela e de áudio do sistema. No Android 8 e posteriores, é necessário fornecer uma notificação para ser exibida no painel de notificação do usuário. O Amazon IVS Broadcast SDK for Android fornece o método de conveniência `createServiceNotificationBuilder`. Se preferir, você pode fornecer sua própria notificação. 

```
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if(requestCode != SCREEN_CAPTURE_REQUEST_ID
       || Activity.RESULT_OK != resultCode) {
        return;
    }
    Notification notification = null;
    if(Build.VERSION.SDK_INT >= 26) {
        Intent intent = new Intent(getApplicationContext(),
                                   NotificationActivity.class);
        notification = session
                         .createServiceNotificationBuilder("example",
                                            "example channel", intent)
                         .build();
    }
    session.createSystemCaptureSources(data,
                  ExampleSystemCaptureService.class,
                  Notification,
                  devices -> {
        // This step is optional if the mixer slots have been given preferred
        // input device types SCREEN and SYSTEM_AUDIO
        for (Device device : devices) {
            session.getMixer().bind(device, "game");
        }
    });
}
```

## Obter configurações recomendadas de transmissão
<a name="broadcast-android-recommended-settings"></a>

Para avaliar a conexão do usuário antes de iniciar uma transmissão, use o método `recommendedVideoSettings` para executar um breve teste. À medida que o teste for executado, você receberá várias recomendações, ordenadas da mais recomendada para a menos recomendada. Nesta versão do SDK, não é possível reconfigurar a `BroadcastSession` atual, então você precisará `release()` e criar uma nova com as configurações recomendadas. Você continuará recebendo `BroadcastSessionTest.Results` até que `Result.status` seja `SUCCESS` ou `ERROR`. É possível verificar o progresso com `Result.progress`.

O Amazon IVS é compatível com uma taxa de bits de até 8,5 Mbps (para canais cujo `type` seja `STANDARD` ou `ADVANCED`), de modo que a `maximumBitrate` retornada por esse método nunca excede 8,5 Mbps. Para considerar pequenas flutuações da performance da rede, o `initialBitrate` recomendado retornado por esse método é ligeiramente menor do que a taxa de bits verdadeira medida no teste. (Geralmente, não é aconselhável usar 100% da largura de banda disponível.)

```
void runBroadcastTest() {
    this.test = session.recommendedVideoSettings(RTMPS_ENDPOINT, RTMPS_STREAMKEY,
        result -> {
            if (result.status == BroadcastSessionTest.Status.SUCCESS) {
                this.recommendation = result.recommendations[0];
            }
        });
}
```

## Uso da reconexão automática
<a name="broadcast-android-auto-reconnect"></a>

O IVS oferece suporte à reconexão automática a uma transmissão caso a transmissão pare inesperadamente sem chamar a API `stop`; por exemplo, uma perda temporária na conectividade de rede. Para ativar a reconexão automática, chame `setEnabled(true)` em `BroadcastConfiguration.autoReconnect`.

Quando algo faz com que o fluxo pare inesperadamente, o SDK tenta novamente até 5 vezes, seguindo uma estratégia de recuo linear. Ele notifica sua aplicação sobre o estado da nova tentativa por meio do método `BroadcastSession.Listener.onRetryStateChanged`.

Nos bastidores, a reconexão automática usa a funcionalidade de [aquisição de fluxo](streaming-config.md#streaming-config-stream-takeover) do IVS, anexando um número de prioridade, começando com 1, ao final da chave de fluxo fornecida. Pela duração da instância `BroadcastSession`, esse número é incrementado em 1 cada vez que uma reconexão é tentada. Isso significa que se a conexão do dispositivo for perdida 4 vezes durante uma transmissão e cada perda exigir de 1 a 4 tentativas, a prioridade da última transmissão poderá estar entre 5 e 17. Por isso, *recomendamos que você não use a aquisição de fluxo do IVS a partir de outro dispositivo enquanto a reconexão automática estiver ativada no SDK para o mesmo canal*. Não há garantias de qual prioridade o SDK estará usando no momento, e o SDK tentará se reconectar com uma prioridade mais alta se outro dispositivo assumir o controle.

## Uso de microfones Bluetooth
<a name="broadcast-android-bluetooth-microphones"></a>

Para transmitir usando microfones Bluetooth, você deve iniciar uma conexão por Bluetooth SCO:

```
Bluetooth.startBluetoothSco(context);
// Now bluetooth microphones can be used
…
// Must also stop bluetooth SCO
Bluetooth.stopBluetoothSco(context);
```