### Handle Split Install State Updates in Java Source: https://developer.android.com/guide/app-bundle/on-demand-delivery Implement `onStateUpdate` to manage the installation status of dynamic feature modules. This example shows how to handle download progress and post-installation actions, including retrying on `SERVICE_DIES` errors. ```java @Override public void onStateUpdate(SplitInstallSessionState state) { if (state.status() == SplitInstallSessionStatus.FAILED && state.errorCode() == SplitInstallErrorCode.SERVICE_DIES) { // Retry the request. return; } if (state.sessionId() == mySessionId) { switch (state.status()) { case SplitInstallSessionStatus.DOWNLOADING: int totalBytes = state.totalBytesToDownload(); int progress = state.bytesDownloaded(); // Update progress bar. break; case SplitInstallSessionStatus.INSTALLED: // After a module is installed, you can start accessing its content or // fire an intent to start an activity in the installed module. // For other use cases, see access code and resources from installed modules. // If the request is an on demand module for an Android Instant App // running on Android 8.0 (API level 26) or higher, you need to // update the app context using the SplitInstallHelper API. } } } ``` -------------------------------- ### Handle Split Install State Updates in Kotlin Source: https://developer.android.com/guide/app-bundle/on-demand-delivery Implement `onStateUpdate` to manage the installation status of dynamic feature modules. This example shows how to handle download progress and post-installation actions, including retrying on `SERVICE_DIED` errors. ```kotlin override fun onStateUpdate(state : SplitInstallSessionState) { if (state.status() == SplitInstallSessionStatus.FAILED && state.errorCode() == SplitInstallErrorCode.SERVICE_DIED) { // Retry the request. return } if (state.sessionId() == mySessionId) { when (state.status()) { SplitInstallSessionStatus.DOWNLOADING -> { val totalBytes = state.totalBytesToDownload() val progress = state.bytesDownloaded() // Update progress bar. } SplitInstallSessionStatus.INSTALLED -> { // After a module is installed, you can start accessing its content or // fire an intent to start an activity in the installed module. // For other use cases, see access code and resources from installed modules. // If the request is an on demand module for an Android Instant App // running on Android 8.0 (API level 26) or higher, you need to // update the app context using the SplitInstallHelper API. } } } } ``` -------------------------------- ### Handle Installation Errors Source: https://developer.android.com/guide/app-bundle/on-demand-delivery Demonstrates how to handle specific installation error codes and check for active sessions when a request fails. ```kotlin splitInstallManager .startInstall(request) .addOnFailureListener { exception -> when ((exception as SplitInstallException).errorCode) { SplitInstallErrorCode.NETWORK_ERROR -> { // Display a message that requests the user to establish a // network connection. } SplitInstallErrorCode.ACTIVE_SESSIONS_LIMIT_EXCEEDED -> checkForActiveDownloads() ... } } fun checkForActiveDownloads() { splitInstallManager // Returns a SplitInstallSessionState object for each active session as a List. .sessionStates .addOnCompleteListener { task -> if (task.isSuccessful) { // Check for active sessions. for (state in task.result) { if (state.status() == SplitInstallSessionStatus.DOWNLOADING) { // Cancel the request, or request a deferred installation. } } } } } ``` -------------------------------- ### Initialize CrossDevicePromptManager Source: https://developer.android.com/guide/playcore/install-prompt/kotlin-java Create an instance of the manager to request information and launch the install prompt flow. ```kotlin import com.google.android.play.core.crossdeviceprompt.CrossDevicePromptInfo import com.google.android.play.core.crossdeviceprompt.CrossDevicePromptManager import com.google.android.play.core.crossdeviceprompt.CrossDevicePromptManagerFactory import com.google.android.play.core.crossdeviceprompt.model.CrossDevicePromptInstallationRequest ... val crossDevicePromptManager: CrossDevicePromptManager = CrossDevicePromptManagerFactory.create(context) ``` ```java import com.google.android.play.core.crossdeviceprompt.CrossDevicePromptInfo; import com.google.android.play.core.crossdeviceprompt.CrossDevicePromptManager; import com.google.android.play.core.crossdeviceprompt.CrossDevicePromptManagerFactory; import com.google.android.play.core.crossdeviceprompt.model.CrossDevicePromptInstallationRequest; ... CrossDevicePromptManager crossDevicePromptManager = CrossDevicePromptManagerFactory.create(context); ``` -------------------------------- ### Compose Navigation Host Setup Source: https://developer.android.com/guide/navigation/design/encapsulate Set up the NavHost in a Composable function to manage navigation between different destinations. This example shows how to define the start destination and include custom destination builders. ```kotlin // MyApp.kt @Composable fun MyApp() { ... NavHost(navController, startDestination = Contacts) { contactsDestination(onNavigateToContactDetails = { contactId -> navController.navigateToContactDetails(id = contactId) }) contactDetailsDestination() } } ``` -------------------------------- ### Configure START_EXERCISE BII for Inline Catalog and Widget Source: https://developer.android.com/guide/app-actions/widgets?hl=zh-cn This shortcuts.xml configuration demonstrates setting up the START_EXERCISE BII capability for both inline catalog and widget execution. ```xml ``` -------------------------------- ### Get Installed Languages (Java) Source: https://developer.android.com/guide/playcore/feature-delivery/on-demand Retrieve a set of strings representing the currently installed languages for your app. This is useful before deciding which languages to uninstall. ```java Set installedLanguages = splitInstallManager.getInstalledLanguages(); ``` -------------------------------- ### Get Installed Languages (Kotlin) Source: https://developer.android.com/guide/playcore/feature-delivery/on-demand Retrieve a set of strings representing the currently installed languages for your app. This is useful before deciding which languages to uninstall. ```kotlin val installedLanguages: Set = splitInstallManager.installedLanguages ``` -------------------------------- ### Configure START_EXERCISE BII with Inline Inventory Source: https://developer.android.com/guide/app-actions/widgets Demonstrates a capability configuration in shortcuts.xml for inline inventory and widget fulfillment. ```xml ``` -------------------------------- ### Activity Initialization and UI Setup (Java) Source: https://developer.android.com/guide/components/aidl?hl=ja Initializes the activity, sets the content view, and sets up click listeners for buttons to manage service binding and interaction. ```java public static class Binding extends Activity { /** The primary interface we are calling on the service. */ IRemoteService mService = null; /** Another interface we use on the service. */ ISecondary secondaryService = null; Button killButton; TextView callbackText; private InternalHandler handler; private boolean isBound; /** * Standard initialization of this activity. Set up the UI, then wait * for the user to interact with it before doing anything. */ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.remote_service_binding); // Watch for button taps. Button button = (Button)findViewById(R.id.bind); button.setOnClickListener(mBindListener); button = (Button)findViewById(R.id.unbind); button.setOnClickListener(unbindListener); killButton = (Button)findViewById(R.id.kill); killButton.setOnClickListener(killListener); killButton.setEnabled(false); ``` -------------------------------- ### On-Demand Module Installation Error Codes Source: https://developer.android.com/guide/playcore/feature-delivery/on-demand A reference guide for error codes returned via SplitInstallStateUpdatedListener when an on-demand module installation fails. ```APIDOC ## Error Handling: On-Demand Module Installation ### Description This section details the error codes returned in `SplitInstallSessionState` when an installation request fails. Developers should implement logic to handle these errors, typically by providing user feedback or retrying the request. ### Error Codes - **SERVICE_DIED**: The service responsible for handling the request has died. Action: Retry the request. - **INSUFFICIENT_STORAGE**: The device does not have enough free storage. Action: Notify the user. - **SPLITCOMPAT_VERIFICATION_ERROR / SPLITCOMPAT_EMULATION_ERROR / SPLITCOMPAT_COPY_ERROR**: SplitCompat could not load the module. Action: These should resolve after an app restart. - **PLAY_STORE_NOT_FOUND**: The Play Store app is not installed. Action: Inform the user that the Play Store is required. - **APP_NOT_OWNED**: The app was not installed via Google Play. Action: Use `startInstall()` to obtain user confirmation. - **INTERNAL_ERROR**: An internal error occurred within the Play Store. Action: Retry the request. ### Implementation Recommendations - For installation errors, display a dialog with 'Try again' and 'Cancel' options. - Provide a 'Help' link directing users to the Google Play Help center. - Note: `onError(-2)` during testing usually indicates the app has not been uploaded to Google Play; use internal/closed testing tracks to verify functionality. ``` -------------------------------- ### Get Installed Languages Source: https://developer.android.com/guide/app-bundle/on-demand-delivery Retrieve a set of strings representing the language resources currently installed on the device. This is useful before deciding to uninstall specific languages. ```kotlin val installedLanguages: Set = splitInstallManager.installedLanguages ``` ```java Set installedLanguages = splitInstallManager.getInstalledLanguages(); ``` -------------------------------- ### Fragment UI Logic Setup (Kotlin) Source: https://developer.android.com/guide/navigation/migrate Demonstrates setting up UI logic within a Fragment, separating view inflation in onCreateView() from post-view initialization in onViewCreated(). Navigation logic is handled conditionally based on lifecycle state. ```kotlin class ProductListFragment : Fragment() { private lateinit var binding: ProductListFragmentBinding private val viewModel: ProductListViewModel by viewModels() // View initialization logic override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { binding = DataBindingUtil.inflate( inflater, R.layout.product_list, container, false ) return binding.root } // Post view initialization logic override fun onViewCreated(view: View, savedInstanceState: Bundle?) { // Connect adapters productAdapter = ProductAdapter(productClickCallback) binding.productsList.setAdapter(productAdapter) // Initialize view properties, set click listeners, etc. binding.productsSearchBtn.setOnClickListener {...} // Subscribe to state viewModel.products.observe(this, Observer { myProducts -> ... }) // ...and so on } // Provided to ProductAdapter private val productClickCallback = ProductClickCallback { product -> if (lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) { ``` -------------------------------- ### Activity Initialization and UI Setup Source: https://developer.android.com/guide/components/aidl?hl=it Sets up the activity's UI, including finding buttons and text views, and attaching click listeners. Initializes the Handler for UI updates. ```kotlin override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.remote_service_binding) // Watch for button taps. var button: Button = findViewById(R.id.bind) button.setOnClickListener(mBindListener) button = findViewById(R.id.unbind) button.setOnClickListener(unbindListener) killButton = findViewById(R.id.kill) killButton.setOnClickListener(killListener) killButton.isEnabled = false callbackText = findViewById(R.id.callback) callbackText.text = "Not attached." handler = InternalHandler(callbackText) } ``` -------------------------------- ### Initiate Non-blocking Navigation Source: https://developer.android.com/guide/navigation/integrations/feature-modules Pass a DynamicExtras object containing a DynamicInstallMonitor to NavController.navigate to start the installation flow. ```kotlin val navController = ... val installMonitor = DynamicInstallMonitor() navController.navigate( destinationId, null, null, DynamicExtras(installMonitor) ) ``` ```java NavController navController = ... DynamicInstallMonitor installMonitor = new DynamicInstallMonitor(); navController.navigate( destinationId, null, null, new DynamicExtras(installMonitor); ) ``` -------------------------------- ### Configure START_EXERCISE BII for Website Catalog and Widget Source: https://developer.android.com/guide/app-actions/widgets?hl=zh-cn This shortcuts.xml configuration enables the START_EXERCISE BII capability for website catalog and widget execution, including data path matching. ```xml ``` -------------------------------- ### GET /CalendarContract.Instances Source: https://developer.android.com/guide/topics/providers/calendar-provider Reference for querying the read-only Instances table which holds start and end times for event occurrences. ```APIDOC ## GET CalendarContract.Instances ### Description The Instances table holds the start and end time for occurrences of an event. This table is read-only. ### Method GET ### Endpoint CalendarContract.Instances.CONTENT_URI ### Parameters #### Queryable Fields - **BEGIN** (Long) - The beginning time of the instance, in UTC milliseconds. - **END** (Long) - The ending time of the instance, in UTC milliseconds. - **END_DAY** (Integer) - The Julian end day of the instance, relative to the Calendar's time zone. - **END_MINUTE** (Integer) - The end minute of the instance measured from midnight in the Calendar's time zone. - **EVENT_ID** (Long) - The _ID of the event for this instance. - **START_DAY** (Integer) - The Julian start day of the instance, relative to the Calendar's time zone. - **START_MINUTE** (Integer) - The start minute of the instance measured from midnight, relative to the Calendar's time zone. ``` -------------------------------- ### Initialize Companion Device Manager in Java Source: https://developer.android.com/guide/topics/connectivity/companion-device-pairing?hl=de Set up the CompanionDeviceManager, define device filters, and initiate the association request. ```java class MainActivityJava extends AppCompatActivity { private static final int SELECT_DEVICE_REQUEST_CODE = 0; Executor executor = new Executor() { @Override public void execute(Runnable runnable) { runnable.run(); } }; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); CompanionDeviceManager deviceManager = (CompanionDeviceManager) getSystemService( Context.COMPANION_DEVICE_SERVICE ); // To skip filtering based on name and supported feature flags, // do not include calls to setNamePattern() and addServiceUuid(), // respectively. This example uses Bluetooth. BluetoothDeviceFilter deviceFilter = new BluetoothDeviceFilter.Builder() .setNamePattern(Pattern.compile("My device")) .addServiceUuid( new ParcelUuid(new UUID(0x123abcL, -1L)), null ) .build(); // The argument provided in setSingleDevice() determines whether a single // device name or a list of device names is presented to the user as // pairing options. AssociationRequest pairingRequest = new AssociationRequest.Builder() .addDeviceFilter(deviceFilter) .setSingleDevice(true) .build(); // When the app tries to pair with the Bluetooth device, show the // appropriate pairing request dialog to the user. deviceManager.associate(pairingRequest, new CompanionDeviceManager.Callback() { executor, // Called when a device is found. Launch the IntentSender so the user can // select the device they want to pair with. @Override public void onDeviceFound(IntentSender chooserLauncher) { try { startIntentSenderForResult( chooserLauncher, SELECT_DEVICE_REQUEST_CODE, null, 0, 0, 0 ); } catch (IntentSender.SendIntentException e) { Log.e("MainActivity", "Failed to send intent"); } } @Override public void onAssociationCreated(AssociationInfo associationInfo) { // AssociationInfo object is created and get association id and the // macAddress. int associationId = associationInfo.getId(); MacAddress macAddress = associationInfo.getDeviceMacAddress(); } @Override public void onFailure(CharSequence errorMessage) { // Handle the failure. }); } ``` -------------------------------- ### Initialize Activity and UI Source: https://developer.android.com/guide/components/aidl?hl=fa Sets up the activity layout, button listeners, and the internal message handler. ```kotlin override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.remote_service_binding) // Watch for button taps. var button: Button = findViewById(R.id.bind) button.setOnClickListener(mBindListener) button = findViewById(R.id.unbind) button.setOnClickListener(unbindListener) killButton = findViewById(R.id.kill) killButton.setOnClickListener(killListener) killButton.isEnabled = false callbackText = findViewById(R.id.callback) callbackText.text = "Not attached." handler = InternalHandler(callbackText) } ``` -------------------------------- ### Start an immediate update flow Source: https://developer.android.com/guide/playcore/in-app-updates/unity Initiates an asynchronous update request using the AppUpdateManager. The app will restart automatically upon successful installation. ```csharp IEnumerator StartImmediateUpdate() { // Creates an AppUpdateRequest that can be used to monitor the // requested in-app update flow. var startUpdateRequest = appUpdateManager.StartUpdate( // The result returned by PlayAsyncOperation.GetResult(). appUpdateInfoResult, // The AppUpdateOptions created defining the requested in-app update // and its parameters. appUpdateOptions); yield return startUpdateRequest; // If the update completes successfully, then the app restarts and this line // is never reached. If this line is reached, then handle the failure (for // example, by logging result.Error or by displaying a message to the user). } ``` -------------------------------- ### Deploy and Start App via Command Line Source: https://developer.android.com/guide/topics/connectivity/cross-device-sdk/testing-debugging Use Gradle to install the debug build and ADB to launch the main activity on test devices. ```bash ./gradlew crossdevice-app:installDebug # Start the app's activity. This example uses the sample app. adb shell am start -n \ com.example.dtdi/com.example.crossdevice.MainActivity ``` -------------------------------- ### ProductListActivity Initialization (Java) Source: https://developer.android.com/guide/navigation/navigation-migrate Sets up the ProductListActivity by inflating the layout and initializing the fragment. The fragment is added only if savedInstanceState is null to prevent recreation. ```java @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.product_list_host); if (savedInstanceState == null) { ProductListFragment fragment = new ProductListFragment(); getSupportFragmentManager() .beginTransaction() .add(R.id.main_content, fragment) .commit(); } } ``` -------------------------------- ### Implement onCreate() for Activity Setup Source: https://developer.android.com/guide/components/activities/activity-lifecycle Use this method for fundamental activity setup, including declaring the UI, defining member variables, and configuring UI elements. It's called once when the activity is first created. ```kotlin lateinit var textView: TextView // Some transient state for the activity instance. var gameState: String? = null override fun onCreate(savedInstanceState: Bundle?) { // Call the superclass onCreate to complete the creation of // the activity, like the view hierarchy. super.onCreate(savedInstanceState) // Recover the instance state. gameState = savedInstanceState?.getString(GAME_STATE_KEY) // Set the user interface layout for this activity. // The layout is defined in the project res/layout/main_activity.xml file. setContentView(R.layout.main_activity) // Initialize member TextView so it is available later. textView = findViewById(R.id.text_view) } ``` ```kotlin // This callback is called only when there is a saved instance previously saved using // onSaveInstanceState(). Some state is restored in onCreate(). Other state can optionally // be restored here, possibly usable after onStart() has completed. // The savedInstanceState Bundle is same as the one used in onCreate(). override fun onRestoreInstanceState(savedInstanceState: Bundle?) { textView.text = savedInstanceState?.getString(TEXT_VIEW_KEY) } ``` ```kotlin // Invoked when the activity might be temporarily destroyed; save the instance state here. override fun onSaveInstanceState(outState: Bundle?) { outState?.run { putString(GAME_STATE_KEY, gameState) putString(TEXT_VIEW_KEY, textView.text.toString()) } // Call superclass to save any view hierarchy. super.onSaveInstanceState(outState) } ``` -------------------------------- ### Calling the addint kernel in Java Source: https://developer.android.com/guide/topics/renderscript/index.html Examples of calling the 'addint' reduction kernel in Java. Shows how to get immediate results from a 1D array and process a 2D allocation with subsequent operations. ```java ScriptC_example script = new ScriptC_example(renderScript); // 1D array // and obtain answer immediately int input1[] = _…_; int sum1 = script.reduce_addint(input1).get(); // Method 3 ``` ```java Type.Builder typeBuilder = new Type.Builder(RS, Element.I32(RS)); typeBuilder.setX(_…_); typeBuilder.setY(_…_); Allocation input2 = createTyped(RS, typeBuilder.create()); _populateSomehow_(input2); // fill in input Allocation with data ScriptC_example.result_int result2 = script.reduce_addint(input2); // Method 1 _doSomeAdditionalWork_(); // might run at same time as reduction int sum2 = result2.get(); ``` -------------------------------- ### Declare Required Sensor Feature in Manifest Source: https://developer.android.com/guide/practices/compatibility Declare a device feature as a requirement in your app's manifest file to prevent installation on devices lacking the feature. This example shows how to require a compass sensor. ```xml ... ``` -------------------------------- ### ProductListActivity Initialization (Kotlin) Source: https://developer.android.com/guide/navigation/navigation-migrate Sets up the ProductListActivity by inflating the layout and initializing the fragment. The fragment is added only if savedInstanceState is null to prevent recreation. ```kotlin override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.product_list_host) if (savedInstanceState == null) { val fragment = ProductListFragment() supportFragmentManager .beginTransaction() .add(R.id.main_content, fragment) .commit() } } ``` -------------------------------- ### Animate object property with ObjectAnimator (getter required) Source: https://developer.android.com/guide/topics/graphics/prop-animation When animating a property with ObjectAnimator and providing only an end value, a getter method for the property is necessary to determine the starting value. The getter should be named get(). ```java ObjectAnimator.ofFloat(targetObject, "propName", 1f) ``` -------------------------------- ### Set up List Adapter and Options Menu Source: https://developer.android.com/guide/components/loaders?hl=ar Configures the list adapter with data mapping and sets up the action bar for search functionality. Requires `getActivity()` context. ```java mAdapter = new SimpleCursorAdapter(getActivity(), android.R.layout.simple_list_item_2, null, new String[] { Contacts.DISPLAY_NAME, Contacts.CONTACT_STATUS }, new int[] { android.R.id.text1, android.R.id.text2 }, 0); setListAdapter(mAdapter); ``` ```java MenuItem item = menu.add("Search"); item.setIcon(android.R.drawable.ic_menu_search); item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); SearchView sv = new SearchView(getActivity()); sv.setOnQueryTextListener(this); item.setActionView(sv); ``` -------------------------------- ### Activity Initialization with UI Setup Source: https://developer.android.com/guide/components/aidl?hl=id Sets up the activity's UI by inflating the layout and attaching click listeners to buttons. Initializes the Handler for UI updates. ```kotlin super.onCreate(savedInstanceState) setContentView(R.layout.remote_service_binding) // Watch for button taps. var button: Button = findViewById(R.id.bind) button.setOnClickListener(mBindListener) button = findViewById(R.id.unbind) button.setOnClickListener(unbindListener) killButton = findViewById(R.id.kill) killButton.setOnClickListener(killListener) killButton.isEnabled = false callbackText = findViewById(R.id.callback) callbackText.text = "Not attached." handler = InternalHandler(callbackText) ``` -------------------------------- ### Set Navigation Graph with Intent Extras in Host Activity (Java) Source: https://developer.android.com/guide/navigation/migrate In the host activity's onCreate method, find the NavHostFragment, get its NavController, and set the navigation graph, passing the intent extras as arguments to the start destination fragment. Avoid setting app:NavGraph in the NavHostFragment XML to prevent double inflation. ```java public class ProductDetailsActivity extends AppCompatActivity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.product_details_host); NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.main_content); NavController navController = navHostFragment.getNavController(); navController .setGraph(R.navigation.product_detail_graph, getIntent().getExtras()); } } ``` -------------------------------- ### Gestione della messa a fuoco audio con ExoPlayer Source: https://developer.android.com/guide/topics/media-apps/audio-focus?hl=it Se utilizzi ExoPlayer, valuta la possibilità di lasciare che gestisca automaticamente la messa a fuoco audio chiamando `setAudioAttributes` con `true` per il parametro `handleAudioFocus`. Se questo comportamento è attivato, la tua app non deve includere codice per richiedere o rispondere alle modifiche della messa a fuoco audio. ```java player.setAudioAttributes(new AudioAttributes.Builder().setContentType(TYPE_SPEECH).build(), true); ``` -------------------------------- ### Set Navigation Graph with Intent Extras in Host Activity (Kotlin) Source: https://developer.android.com/guide/navigation/migrate In the host activity's onCreate method, find the NavHostFragment, get its NavController, and set the navigation graph, passing the intent extras as arguments to the start destination fragment. Avoid setting app:NavGraph in the NavHostFragment XML to prevent double inflation. ```kotlin class ProductDetailsActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.product_details_host) val navHostFragment = supportFragmentManager.findFragmentById(R.id.main_content) as NavHostFragment val navController = navHostFragment.navController navController .setGraph(R.navigation.product_detail_graph, intent.extras) } } ``` -------------------------------- ### Start Activity using Kotlin Source: https://developer.android.com/guide/navigation/design/activity-destinations This Kotlin code snippet demonstrates how to start an activity directly, which is equivalent to defining an activity destination in XML. ```kotlin startActivity(Intent(context, DestinationActivity::class.java)) ``` -------------------------------- ### Defer language resource installation (Java) Source: https://developer.android.com/guide/app-bundle/test/testing-fakesplitinstallmanager Defer the installation of language resources until the app is in the background. This is useful when immediate installation is not required. ```java splitInstallManager.deferredLanguageInstall( Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION))); ``` -------------------------------- ### Defer language resource installation (Kotlin) Source: https://developer.android.com/guide/app-bundle/test/testing-fakesplitinstallmanager Defer the installation of language resources until the app is in the background. This is useful when immediate installation is not required. ```kotlin splitInstallManager.deferredLanguageInstall( Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION))) ``` -------------------------------- ### Recreate activity after language install (Java) Source: https://developer.android.com/guide/app-bundle/test/testing-fakesplitinstallmanager Recreate the activity when the language resource installation status is `INSTALLED` to load the newly available language resources. ```java switch (state.status()) { case SplitInstallSessionStatus.INSTALLED: activity.recreate(); ... } ``` -------------------------------- ### Initialize Activity and UI Source: https://developer.android.com/guide/components/aidl?hl=es-419 Sets up the activity layout and initializes listeners for binding, unbinding, and killing services. ```kotlin override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.remote_service_binding) // Watch for button taps. var button: Button = findViewById(R.id.bind) button.setOnClickListener(mBindListener) button = findViewById(R.id.unbind) button.setOnClickListener(unbindListener) killButton = findViewById(R.id.kill) killButton.setOnClickListener(killListener) killButton.isEnabled = false callbackText = findViewById(R.id.callback) callbackText.text = "Not attached." handler = InternalHandler(callbackText) } ``` -------------------------------- ### Initialize Discovery and Sessions APIs (Java) Source: https://developer.android.com/guide/topics/connectivity/cross-device-sdk/get-started Create instances of the Discovery and Sessions classes using the provided context. The Cross device SDK is asynchronous. ```java Discovery discovery = Discovery.create(context); Sessions sessions = Sessions.create(context); ``` -------------------------------- ### Recreate activity after language install (Kotlin) Source: https://developer.android.com/guide/app-bundle/test/testing-fakesplitinstallmanager Recreate the activity when the language resource installation status is `INSTALLED` to load the newly available language resources. ```kotlin when (state.status()) { SplitInstallSessionStatus.INSTALLED -> { activity.recreate() } ... } ``` -------------------------------- ### Install on-demand modules Source: https://developer.android.com/guide/app-bundle/on-demand-delivery Use this to install on-demand modules. Your app must be in the foreground to submit the request. You can install multiple modules in a single request. ```kotlin // Creates an instance of SplitInstallManager. val splitInstallManager = SplitInstallManagerFactory.create(context) // Creates a request to install a module. val request = SplitInstallRequest .newBuilder() // You can download multiple on demand modules per // request by invoking the following method for each // module you want to install. .addModule("pictureMessages") .addModule("promotionalFilters") .build() splitInstallManager // Submits the request to install the module through the // asynchronous startInstall() task. Your app needs to be // in the foreground to submit the request. .startInstall(request) // You should also be able to gracefully handle // request state changes and errors. To learn more, go to // the section about how to Monitor the request state. .addOnSuccessListener { sessionId -> ... } .addOnFailureListener { exception -> ... } ``` ```java // Creates an instance of SplitInstallManager. SplitInstallManager splitInstallManager = SplitInstallManagerFactory.create(context); // Creates a request to install a module. SplitInstallRequest request = SplitInstallRequest .newBuilder() // You can download multiple on demand modules per // request by invoking the following method for each // module you want to install. .addModule("pictureMessages") .addModule("promotionalFilters") .build(); splitInstallManager // Submits the request to install the module through the // asynchronous startInstall() task. Your app needs to be // in the foreground to submit the request. .startInstall(request) // You should also be able to gracefully handle // request state changes and errors. To learn more, go to // the section about how to Monitor the request state. .addOnSuccessListener(sessionId -> { ... }) .addOnFailureListener(exception -> { ... }); ``` -------------------------------- ### Initialize Media Session in Java Source: https://developer.android.com/guide/topics/media-apps/audio-app/building-a-mediabrowserservice Create and initialize a MediaSessionCompat, set its flags, initial playback state, callback, and session token in the onCreate() method. ```java public class MediaPlaybackService extends MediaBrowserServiceCompat { private static final String MY_MEDIA_ROOT_ID = "media_root_id"; private static final String MY_EMPTY_MEDIA_ROOT_ID = "empty_root_id"; private MediaSessionCompat mediaSession; private PlaybackStateCompat.Builder stateBuilder; @Override public void onCreate() { super.onCreate(); // Create a MediaSessionCompat mediaSession = new MediaSessionCompat(context, LOG_TAG); // Enable callbacks from MediaButtons and TransportControls mediaSession.setFlags( MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS | MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS); // Set an initial PlaybackState with ACTION_PLAY, so media buttons can start the player stateBuilder = new PlaybackStateCompat.Builder() .setActions( PlaybackStateCompat.ACTION_PLAY | PlaybackStateCompat.ACTION_PLAY_PAUSE); mediaSession.setPlaybackState(stateBuilder.build()); // MySessionCallback() has methods that handle callbacks from a media controller mediaSession.setCallback(new MySessionCallback()); // Set the session's token so that client activities can communicate with it. setSessionToken(mediaSession.getSessionToken()); } } ``` -------------------------------- ### Defer installation of on-demand modules Source: https://developer.android.com/guide/app-bundle/on-demand-delivery Use this to defer the installation of on-demand modules until the app is in the background. Your app does not need to be in the foreground to initiate this request. Progress cannot be tracked for deferred installs. ```kotlin // Requests an on demand module to be downloaded when the app enters // the background. You can specify more than one module at a time. splitInstallManager.deferredInstall(listOf("promotionalFilters")) ``` ```java // Requests an on demand module to be downloaded when the app enters // the background. You can specify more than one module at a time. splitInstallManager.deferredInstall(Arrays.asList("promotionalFilters")); ``` -------------------------------- ### Create CrossDevicePromptManager Instance (Java) Source: https://developer.android.com/guide/playcore/install-prompt/kotlin-java?hl=pt-br Instantiate the CrossDevicePromptManager using the CrossDevicePromptManagerFactory. This manager is the primary interface for requesting installation information and initiating the installation prompt flow. ```Java import com.google.android.play.core.crossdeviceprompt.CrossDevicePromptInfo; import com.google.android.play.core.crossdeviceprompt.CrossDevicePromptManager; import com.google.android.play.core.crossdeviceprompt.CrossDevicePromptManagerFactory; import com.google.android.play.core.crossdeviceprompt.model.CrossDevicePromptInstallationRequest; ... CrossDevicePromptManager crossDevicePromptManager = CrossDevicePromptManagerFactory.create(context); ``` -------------------------------- ### Setup Navigation Controller in Activity Source: https://developer.android.com/guide/navigation/integrations/ui Initialize the navigation controller and link it to the NavigationView within the onCreate method. ```kotlin override fun onCreate(savedInstanceState: Bundle?) { setContentView(R.layout.activity_main) ... **val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment val navController = navHostFragment.navController findViewById(R.id.nav_view) .setupWithNavController(navController)** } ``` ```java @Override protected void onCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_main); ... **NavHostFragment navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment); NavController navController = navHostFragment.getNavController(); NavigationView navView = findViewById(R.id.nav_view); NavigationUI.setupWithNavController(navView, navController);** } ``` -------------------------------- ### Install App and Feature APKs Source: https://developer.android.com/guide/playcore/feature-delivery/on-demand Install the base app and transfer additional feature module APKs to the device using bundletool. This prepares the device for local testing of feature module installs. ```bash bundletool install-apks --apks my_app.apks ``` -------------------------------- ### Start Activity using Java Source: https://developer.android.com/guide/navigation/design/activity-destinations This Java code snippet demonstrates how to start an activity directly, which is equivalent to defining an activity destination in XML. ```java startActivity(new Intent(context, DestinationActivity.class)); ``` -------------------------------- ### Install Location Configuration Source: https://developer.android.com/guide/topics/manifest/manifest-element Configuration options for the default installation location of an Android application. ```APIDOC ## `android:installLocation` ### Description Determines the default installation location for the app. ### Accepted Values - `"internalOnly"`: Installs only on internal device storage. Default behavior. App won't install if internal storage is full. - `"auto"`: Installs on external storage if internal storage is full, otherwise installs on internal storage by default. User can move the app later. - `"preferExternal"`: Prefers installation on external storage. May install on internal storage if external media is unavailable or full. User can move the app later. ### Notes - By default, apps install on internal storage and cannot be moved to external storage unless `"auto"` or `"preferExternal"` is specified. - When an app installs on external storage, the APK is saved there, but app data remains on internal memory. The APK container is encrypted. - Apps installed on external storage can be moved to internal storage at the user's request. - The system does not allow moving an app to external storage if `"internalOnly"` is set. ### Introduced in - API level 8 ``` -------------------------------- ### Build ExoPlayer with Cronet network stack Source: https://developer.android.com/guide/topics/media/exoplayer/network-stacks Demonstrates initializing an ExoPlayer instance configured to use the Cronet network stack while maintaining support for local file playback. ```Kotlin // Given a CronetEngine and Executor, build a CronetDataSource.Factory. val cronetDataSourceFactory = CronetDataSource.Factory(cronetEngine, executor) // Wrap the CronetDataSource.Factory in a DefaultDataSource.Factory, which adds // in support for requesting data from other sources (such as files, resources, // etc). val dataSourceFactory = DefaultDataSource.Factory(context, /* baseDataSourceFactory= */ cronetDataSourceFactory) // Inject the DefaultDataSource.Factory when creating the player. val player = ExoPlayer.Builder(context) .setMediaSourceFactory( DefaultMediaSourceFactory(context).setDataSourceFactory(dataSourceFactory) ) .build() ``` ```Java // Given a CronetEngine and Executor, build a CronetDataSource.Factory. CronetDataSource.Factory cronetDataSourceFactory = new CronetDataSource.Factory(cronetEngine, executor); // Wrap the CronetDataSource.Factory in a DefaultDataSource.Factory, which adds // in support for requesting data from other sources (such as files, resources, // etc). DefaultDataSource.Factory dataSourceFactory = new DefaultDataSource.Factory( context, /* baseDataSourceFactory= */ cronetDataSourceFactory); // Inject the DefaultDataSource.Factory when creating the player. ExoPlayer player = new ExoPlayer.Builder(context) .setMediaSourceFactory( new DefaultMediaSourceFactory(context).setDataSourceFactory(dataSourceFactory)) .build(); ``` -------------------------------- ### Recreate activity after installation Source: https://developer.android.com/guide/playcore/feature-delivery/on-demand Triggers an activity recreation once the language resources are successfully installed. ```kotlin when (state.status()) { SplitInstallSessionStatus.INSTALLED -> { // Recreates the activity to load resources for the new language // preference. activity.recreate() } ... ``` ```java switch (state.status()) { case SplitInstallSessionStatus.INSTALLED: // Recreates the activity to load resources for the new language // preference. activity.recreate(); ... ``` -------------------------------- ### Defer language resource installation Source: https://developer.android.com/guide/playcore/feature-delivery/on-demand Schedules the installation of language resources for when the app is in the background. ```kotlin splitInstallManager.deferredLanguageInstall( Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION))) ``` ```java splitInstallManager.deferredLanguageInstall( Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION))); ```