

# Casi d'uso avanzati per l'SDK di trasmissione IVS per Android \$1 Streaming a bassa latenza
<a name="broadcast-android-use-cases"></a>

Qui presentiamo alcuni casi d'uso avanzati. Iniziare con la configurazione di base di cui sopra e continuare qui. 

## Creare la configurazione di trasmissione
<a name="broadcast-android-create-configuration"></a>

Qui creiamo una configurazione personalizzata con due slot mixer che ci permettono di associare due fonti video al mixer. Uno (`custom`) è a schermo intero e disposto dietro l'altro (`camera`), che è più piccolo e si trova nell'angolo in basso a destra. Per lo slot `custom` non impostiamo una posizione, una dimensione o una modalità di aspetto. Poiché non impostiamo questi parametri, lo slot utilizzerà le impostazioni del video per le dimensioni e la posizione.

```
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 $;
});
```

## Creare la sessione di trasmissione (versione avanzata)
<a name="broadcast-android-create-session-advanced"></a>

Creare una `BroadcastSession` come è stato fatto nell'[esempio di base](broadcast-android-getting-started.md#broadcast-android-create-session), ma fornire qui la propria configurazione personalizzata. Inoltre, inserire `null` per l'array dei dispositivi, perché lo aggiungeremo 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
```

## Iterare e collegare un dispositivo fotocamera
<a name="broadcast-android-attach-camera"></a>

Qui iteriamo attraverso i vari dispositivi di input rilevati dall'SDK. Su Android 7 (Nougat) questo restituirà solo i dispositivi microfonici predefiniti, perché l'SDK di trasmissione di Amazon IVS non supporta la selezione di dispositivi non predefiniti su questa versione di Android.

Una volta trovato un dispositivo che vogliamo usare, chiamiamo `attachDevice` per collegarlo. Una funzione lambda viene richiamata sul thread principale una volta che il collegamento del dispositivo di input è stato completato. In caso di errore, si riceverà una segnalazione nel 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;
    }
}
```

## Scambiare fotocamere
<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;
   }
}
```

## Creare una superficie di input
<a name="broadcast-android-create-input-surface"></a>

Per inserire dati audio o immagini generati dall'app, utilizzare `createImageInputSource` o `createAudioInputSource`. Entrambi questi metodi creano e collegano dispositivi virtuali che possono essere associati al mixer come qualsiasi altro dispositivo.

La `SurfaceSource` restituita da `createImageInputSource` dispone di un metodo `getInputSurface` che darà un `Surface` che utilizzabile con l'API Camera2, OpenGL o Vulkan, o qualsiasi altra cosa che può scrivere su una superficie.

Il `AudioDevice` restituito da `createAudioInputSource` può ricevere dati PCM lineari generati da AudioRecorder o altri mezzi.

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

## Scollegare un dispositivo
<a name="broadcast-android-detach-device"></a>

Se si desidera scollegare e non sostituire un dispositivo, scollegarlo con `Device` o `Device.Descriptor`.

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

## Acquisire l'audio dello schermo e del sistema
<a name="broadcast-android-screen-audio-capture"></a>

L'SDK di trasmissione di Amazon IVS per Android include alcuni strumenti che semplificano la cattura dell'audio dello schermo del dispositivo (Android 6 e versioni successive) e del sistema (Android 10 e versioni successive). Se si desidera gestirli manualmente si può creare una fonte di ingresso immagine personalizzata e una fonte di ingresso audio personalizzata.

Per creare una sessione di acquisizione dell'audio dello schermo e del sistema, si avrà bisogno innanzitutto di creare una formula per la richiesta di autorizzazione:

```
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);
    }
}
```

Per utilizzare questa funzionalità è necessario fornire una classe che estenda `com.amazonaws.ivs.broadcast.SystemCaptureService`. Non è necessario sovrascrivere nessuno dei suoi metodi, ma la classe deve essere specificata per evitare potenziali collisioni tra i servizi.

È necessario anche aggiungere un paio di elementi al proprio manifest Android:

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

La classe che estende `SystemCaptureService` deve essere denominata nell'elemento `<service>`. Su Android 9 e versioni successive, `foregroundServiceType` deve essere `mediaProjection`.

Una volta ottenuta una risposta alla formula di autorizzazione, si può procedere con la creazione della sessione di acquisizione dell'audio dello schermo e del sistema. Su Android 8 e versioni successive, è necessario fornire una notifica da visualizzare nel Pannello notifiche dell'utente. L'SDK di trasmissione di Amazon IVS per Android fornisce il metodo di convenienza `createServiceNotificationBuilder`. In alternativa, è possibile fornire la propria notifica. 

```
@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");
        }
    });
}
```

## Ottenere impostazioni di trasmissione suggerite
<a name="broadcast-android-recommended-settings"></a>

Per valutare la connessione dell'utente prima di avviare una trasmissione, utilizzare il metodo `recommendedVideoSettings` per eseguire un breve test. Durante l'esecuzione del test, si riceveranno vari suggerimenti ordinati dal più consigliato al meno raccomandato. In questa versione dell'SDK, non è possibile riconfigurare l'attuale `BroadcastSession`, quindi effettuare `release()` e crearne uno nuovo con le impostazioni suggerite. Si continuerà a ricevere `BroadcastSessionTest.Results` fino a che `Result.status` è `SUCCESS` o `ERROR`. È possibile controllare lo stato di avanzamento mediante `Result.progress`.

Amazon IVS supporta un bitrate massimo di 8,5 Mb/s (per i canali il cui `type` è `STANDARD` o `ADVANCED`), quindi il `maximumBitrate` restituito da questo metodo non supera mai 8,5 Mb/s. Per tenere in considerazione le piccole fluttuazioni nelle prestazioni di rete, il `initialBitrate` suggerito restituito da questo metodo è leggermente inferiore al bitrate reale misurato nel test. (Solitamente è sconsigliabile utilizzare il 100% della larghezza di banda disponibile.)

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

## Utilizzo della riconnessione automatica
<a name="broadcast-android-auto-reconnect"></a>

IVS supporta la riconnessione automatica a una trasmissione se la trasmissione si interrompe inaspettatamente senza chiamare l'API `stop`, ad esempio in caso di perdita temporanea della connettività di rete. Per abilitare la riconnessione automatica, chiama `setEnabled(true)` su `BroadcastConfiguration.autoReconnect`.

Quando qualcosa causa l'interruzione imprevista del flusso, l'SDK riprova fino a 5 volte, seguendo una strategia di backoff lineare. Notifica all'applicazione lo stato del nuovo tentativo tramite il metodo `BroadcastSession.Listener.onRetryStateChanged`.

Dietro le quinte, la riconnessione automatica utilizza la funzionalità [stream-takeover](streaming-config.md#streaming-config-stream-takeover) di IVS aggiungendo un numero di priorità, che inizia con 1, alla fine della chiave di flusso fornita. Per tutta la durata dell'istanza `BroadcastSession`, tale numero viene incrementato di 1 ogni volta che viene tentata una riconnessione. Ciò significa che se la connessione del dispositivo viene interrotta 4 volte durante una trasmissione e ogni perdita richiede 1-4 nuovi tentativi, la priorità dell'ultimo flusso in uscita potrebbe essere compresa tra 5 e 17. Per questo motivo, *consigliamo di non utilizzare l'acquisizione del flusso IVS da un altro dispositivo se per lo stesso canale nell'SDK è abilitata la riconnessione automatica*. Non ci sono garanzie sulla priorità utilizzata dall'SDK in quel momento e l'SDK proverà a riconnettersi con una priorità più alta se un altro dispositivo prende il controllo.

## Uso dei microfoni Bluetooth
<a name="broadcast-android-bluetooth-microphones"></a>

Per trasmettere utilizzando dispositivi microfonici Bluetooth, è necessario avviare una connessione Bluetooth SCO:

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