Manage availability for on-demand Google Play services modules

As described in the Overview of Google Play services article, SDKs powered by Google Play services are backed by on-device services on Google-certified Android devices. To conserve storage and memory across the entire fleet of devices, some services are provided as modules that are installed on-demand when your app requires the relevant functionality. For example, ML Kit provides this option when using models in Google Play services.

In most cases, the Google Play services SDK downloads and installs the necessary modules automatically when your app uses an API that requires them. However, you might want to have more control over the process, such as when you want to improve the user experience by installing the module in advance.

The ModuleInstallClient API gives you the ability to:

  • Check if the modules are already installed on the device.
  • Request to install the modules.
  • Monitor the installation progress.
  • Handle errors during the installation process.

This guide shows you how to use ModuleInstallClient to manage modules in your app. Note that the following code snippets use the TensorFlow Lite SDK ( play-services-tflite-java ) as an example, but these steps are applicable for any library that's integrated with OptionalModuleApi .

Before you begin

To prepare your app, complete the steps in the following sections.

App prerequisites

Make sure that your app's build file uses the following values:

  • A minSdkVersion of 23 or higher

Configure your app

  1. In your top-level settings.gradle file, include Google's Maven repository and the Maven central repository within the dependencyResolutionManagement block:

      dependencyResolutionManagement 
      
     { 
      
     repositories 
      
     { 
      
     google 
     () 
      
     mavenCentral 
     () 
      
     } 
     } 
     
    
  2. In your module's Gradle build file (usually app/build.gradle ), add the Google Play services dependencies for play-services-base and play-services-tflite-java :

      dependencies 
      
     { 
      
     implementation 
      
     'com.google.android.gms:play-services-base:18.7.2' 
      
     implementation 
      
     'com.google.android.gms:play-services-tflite-java:16.4.0' 
     } 
     
    

Check if modules are available

Before you try to install a module, you can check if it's already installed on the device. This helps you avoid unnecessary installation requests.

  1. Get an instance of ModuleInstallClient :

    Kotlin

     val 
      
     moduleInstallClient 
      
     = 
      
     ModuleInstall 
     . 
     getClient 
     ( 
     context 
     ) 
    

    Java

     ModuleInstallClient 
      
     moduleInstallClient 
      
     = 
      
     ModuleInstall 
     . 
     getClient 
     ( 
     context 
     ); 
    
  2. Check the availability of a module using its OptionalModuleApi . This API is provided by the Google Play services SDK that you are using.

    Kotlin

     val 
      
     optionalModuleApi 
      
     = 
      
     TfLite 
     . 
     getClient 
     ( 
     context 
     ) 
     moduleInstallClient 
      
     . 
     areModulesAvailable 
     ( 
     optionalModuleApi 
     ) 
      
     . 
     addOnSuccessListener 
      
     { 
      
     if 
      
     ( 
     it 
     . 
     areModulesAvailable 
     ()) 
      
     { 
      
     // Modules are present on the device... 
      
     } 
      
     else 
      
     { 
      
     // Modules are not present on the device... 
      
     } 
      
     } 
      
     . 
     addOnFailureListener 
      
     { 
      
     // Handle failure... 
      
     } 
    

    Java

     OptionalModuleApi 
      
     optionalModuleApi 
      
     = 
      
     TfLite 
     . 
     getClient 
     ( 
     context 
     ); 
     moduleInstallClient 
      
     . 
     areModulesAvailable 
     ( 
     optionalModuleApi 
     ) 
      
     . 
     addOnSuccessListener 
     ( 
      
     response 
      
     -> 
      
     { 
      
     if 
      
     ( 
     response 
     . 
     areModulesAvailable 
     ()) 
      
     { 
      
     // Modules are present on the device... 
      
     } 
      
     else 
      
     { 
      
     // Modules are not present on the device... 
      
     } 
      
     }) 
      
     . 
     addOnFailureListener 
     ( 
      
     e 
      
     -> 
      
     { 
      
     // Handle failure… 
      
     }); 
    

Request a deferred install

If you don't need the module immediately, you can request a deferred install. This allows Google Play services to install the module in the background, potentially when the device is idle and connected to Wi-Fi.

  1. Get an instance of ModuleInstallClient :

    Kotlin

     val 
      
     moduleInstallClient 
      
     = 
      
     ModuleInstall 
     . 
     getClient 
     ( 
     context 
     ) 
    

    Java

     ModuleInstallClient 
      
     moduleInstallClient 
      
     = 
      
     ModuleInstall 
     . 
     getClient 
     ( 
     context 
     ); 
    
  2. Send the deferred request:

    Kotlin

     val 
      
     optionalModuleApi 
      
     = 
      
     TfLite 
     . 
     getClient 
     ( 
     context 
     ) 
     moduleInstallClient 
     . 
     deferredInstall 
     ( 
     optionalModuleApi 
     ) 
    

    Java

     OptionalModuleApi 
      
     optionalModuleApi 
      
     = 
      
     TfLite 
     . 
     getClient 
     ( 
     context 
     ); 
     moduleInstallClient 
     . 
     deferredInstall 
     ( 
     optionalModuleApi 
     ); 
    

Request an urgent module install

If your app needs the module immediately, you can request an urgent install. This will try to install the module as quickly as possible, even if it means using mobile data.

  1. Get an instance of ModuleInstallClient :

    Kotlin

     val 
      
     moduleInstallClient 
      
     = 
      
     ModuleInstall 
     . 
     getClient 
     ( 
     context 
     ) 
    

    Java

     ModuleInstallClient 
      
     moduleInstallClient 
      
     = 
      
     ModuleInstall 
     . 
     getClient 
     ( 
     context 
     ); 
    
  2. (Optional) Create an InstallStatusListener to monitor the install progress.

    If you want to display the download progress in your app's UI (for example, with a progress bar), you can create an InstallStatusListener to receive updates.

    Kotlin

     inner 
      
     class 
      
     ModuleInstallProgressListener 
      
     : 
      
     InstallStatusListener 
      
     { 
      
     override 
      
     fun 
      
     onInstallStatusUpdated 
     ( 
     update 
     : 
      
     ModuleInstallStatusUpdate 
     ) 
      
     { 
      
     // Progress info is only set when modules are in the progress of downloading. 
      
     update 
     . 
     progressInfo 
     ?. 
     let 
      
     { 
      
     val 
      
     progress 
      
     = 
      
     ( 
     it 
     . 
     bytesDownloaded 
      
     * 
      
     100 
      
     / 
      
     it 
     . 
     totalBytesToDownload 
     ). 
     toInt 
     () 
      
     // Set the progress for the progress bar. 
      
     progressBar 
     . 
     setProgress 
     ( 
     progress 
     ) 
      
     } 
      
     if 
      
     ( 
     isTerminateState 
     ( 
     update 
     . 
     installState 
     )) 
      
     { 
      
     moduleInstallClient 
     . 
     unregisterListener 
     ( 
     this 
     ) 
      
     } 
      
     } 
      
     fun 
      
     isTerminateState 
     ( 
     @InstallState 
      
     state 
     : 
      
     Int 
     ): 
      
     Boolean 
      
     { 
      
     return 
      
     state 
      
     == 
      
     STATE_CANCELED 
      
     || 
      
     state 
      
     == 
      
     STATE_COMPLETED 
      
     || 
      
     state 
      
     == 
      
     STATE_FAILED 
      
     } 
     } 
     val 
      
     listener 
      
     = 
      
     ModuleInstallProgressListener 
     () 
    

    Java

     static 
      
     final 
      
     class 
     ModuleInstallProgressListener 
      
     implements 
      
     InstallStatusListener 
      
     { 
      
     @Override 
      
     public 
      
     void 
      
     onInstallStatusUpdated 
     ( 
     ModuleInstallStatusUpdate 
      
     update 
     ) 
      
     { 
      
     ProgressInfo 
      
     progressInfo 
      
     = 
      
     update 
     . 
     getProgressInfo 
     (); 
      
     // Progress info is only set when modules are in the progress of downloading. 
      
     if 
      
     ( 
     progressInfo 
      
     != 
      
     null 
     ) 
      
     { 
      
     int 
      
     progress 
      
     = 
      
     ( 
     int 
     ) 
      
     ( 
     progressInfo 
     . 
     getBytesDownloaded 
     () 
      
     * 
      
     100 
      
     / 
      
     progressInfo 
     . 
     getTotalBytesToDownload 
     ()); 
      
     // Set the progress for the progress bar. 
      
     progressBar 
     . 
     setProgress 
     ( 
     progress 
     ); 
      
     } 
      
     // Handle failure status maybe… 
      
     // Unregister listener when there are no more install status updates. 
      
     if 
      
     ( 
     isTerminateState 
     ( 
     update 
     . 
     getInstallState 
     ())) 
      
     { 
      
     moduleInstallClient 
     . 
     unregisterListener 
     ( 
     this 
     ); 
      
     } 
      
     } 
      
     public 
      
     boolean 
      
     isTerminateState 
     ( 
     @InstallState 
      
     int 
      
     state 
     ) 
      
     { 
      
     return 
      
     state 
      
     == 
      
     STATE_CANCELED 
      
     || 
      
     state 
      
     == 
      
     STATE_COMPLETED 
      
     || 
      
     state 
      
     == 
      
     STATE_FAILED 
     ; 
      
     } 
      
     } 
     InstallStatusListener 
      
     listener 
      
     = 
      
     new 
      
     ModuleInstallProgressListener 
     (); 
    
  3. Configure the ModuleInstallRequest and add the OptionalModuleApi to the request:

    Kotlin

     val 
      
     optionalModuleApi 
      
     = 
      
     TfLite 
     . 
     getClient 
     ( 
     context 
     ) 
     val 
      
     moduleInstallRequest 
      
     = 
      
     ModuleInstallRequest 
     . 
     newBuilder 
     () 
      
     . 
     addApi 
     ( 
     optionalModuleApi 
     ) 
      
     // Add more APIs if you would like to request multiple modules. 
      
     // .addApi(...) 
      
     // Set the listener if you need to monitor the download progress. 
      
     // .setListener(listener) 
      
     . 
     build 
     () 
    

    Java

     OptionalModuleApi 
      
     optionalModuleApi 
      
     = 
      
     TfLite 
     . 
     getClient 
     ( 
     context 
     ); 
     ModuleInstallRequest 
      
     moduleInstallRequest 
      
     = 
      
     ModuleInstallRequest 
     . 
     newBuilder 
     () 
      
     . 
     addApi 
     ( 
     optionalModuleApi 
     ) 
      
     // Add more API if you would like to request multiple modules 
      
     //.addApi(...) 
      
     // Set the listener if you need to monitor the download progress 
      
     //.setListener(listener) 
      
     . 
     build 
     (); 
    
  4. Send the install request:

    Kotlin

     moduleInstallClient 
      
     . 
     installModules 
     ( 
     moduleInstallRequest 
     ) 
      
     . 
     addOnSuccessListener 
      
     { 
      
     if 
      
     ( 
     it 
     . 
     areModulesAlreadyInstalled 
     ()) 
      
     { 
      
     // Modules are already installed when the request is sent. 
      
     } 
      
     // The install request has been sent successfully. This does not mean 
      
     // the installation is completed. To monitor the install status, set an 
      
     // InstallStatusListener to the ModuleInstallRequest. 
      
     } 
      
     . 
     addOnFailureListener 
      
     { 
      
     // Handle failure… 
      
     } 
    

    Java

     moduleInstallClient 
     . 
     installModules 
     ( 
     moduleInstallRequest 
     ) 
      
     . 
     addOnSuccessListener 
     ( 
      
     response 
      
     -> 
      
     { 
      
     if 
      
     ( 
     response 
     . 
     areModulesAlreadyInstalled 
     ()) 
      
     { 
      
     // Modules are already installed when the request is sent. 
      
     } 
      
     // The install request has been sent successfully. This does not 
      
     // mean the installation is completed. To monitor the install 
      
     // status, set an InstallStatusListener to the 
      
     // ModuleInstallRequest. 
      
     }) 
      
     . 
     addOnFailureListener 
     ( 
      
     e 
      
     -> 
      
     { 
      
     // Handle failure... 
      
     }); 
    

Test your app with FakeModuleInstallClient

Google Play services SDKs provide the FakeModuleInstallClient to allow you to simulate the results of the module install APIs in tests using dependency injection. This helps you to test your app's behavior in different scenarios without needing to deploy it to a real device.

App prerequisites

Configure your app to use Hilt dependency injection framework .

Replace ModuleInstallClient with FakeModuleInstallClient in test

To use FakeModuleInstallClient in your tests, you need to replace the ModuleInstallClient binding with the fake implementation.

  1. Add dependency:

    In your module's Gradle build file (usually app/build.gradle ), add the Google Play services dependencies for play-services-base-testing in your test.

       
     dependencies 
      
     { 
      
     // other dependencies... 
      
     testImplementation 
      
     'com.google.android.gms:play-services-base-testing:16.1.0' 
      
     } 
     
    
  2. Create a Hilt module to provide ModuleInstallClient :

    Kotlin

     @Module 
     @InstallIn 
     ( 
     ActivityComponent 
     :: 
     class 
     ) 
     object 
      
     ModuleInstallModule 
      
     { 
      
     @Provides 
      
     fun 
      
     provideModuleInstallClient 
     ( 
      
     @ActivityContext 
      
     context 
     : 
      
     Context 
      
     ): 
      
     ModuleInstallClient 
      
     = 
      
     ModuleInstall 
     . 
     getClient 
     ( 
     context 
     ) 
     } 
    

    Java

     @Module 
     @InstallIn 
     ( 
     ActivityComponent 
     . 
     class 
     ) 
     public 
      
     class 
     ModuleInstallModule 
      
     { 
      
     @Provides 
      
     public 
      
     static 
      
     ModuleInstallClient 
      
     provideModuleInstallClient 
     ( 
      
     @ActivityContext 
      
     Context 
      
     context 
     ) 
      
     { 
      
     return 
      
     ModuleInstall 
     . 
     getClient 
     ( 
     context 
     ); 
      
     } 
     } 
    
  3. Inject the ModuleInstallClient in the activity:

    Kotlin

     @AndroidEntryPoint 
     class 
      
     MyActivity 
     : 
      
     AppCompatActivity 
     () 
      
     { 
      
     @Inject 
      
     lateinit 
      
     var 
      
     moduleInstallClient 
     : 
      
     ModuleInstallClient 
      
     ... 
     } 
    

    Java

     @AndroidEntryPoint 
     public 
      
     class 
     MyActivity 
      
     extends 
      
     AppCompatActivity 
      
     { 
      
     @Inject 
      
     ModuleInstallClient 
      
     moduleInstallClient 
     ; 
      
     ... 
     } 
    
  4. Replace the binding in test:

    Kotlin

     @UninstallModules 
     ( 
     ModuleInstallModule 
     :: 
     class 
     ) 
     @HiltAndroidTest 
     class 
      
     MyActivityTest 
      
     { 
      
     ... 
      
     private 
      
     val 
      
     context 
     : 
     Context 
      
     = 
      
     ApplicationProvider 
     . 
     getApplicationContext 
     () 
      
     private 
      
     val 
      
     fakeModuleInstallClient 
      
     = 
      
     FakeModuleInstallClient 
     ( 
     context 
     ) 
      
     @BindValue 
      
     @JvmField 
      
     val 
      
     moduleInstallClient 
     : 
      
     ModuleInstallClient 
      
     = 
      
     fakeModuleInstallClient 
      
     ... 
     } 
    

    Java

     @UninstallModules 
     ( 
     ModuleInstallModule 
     . 
     class 
     ) 
     @HiltAndroidTest 
     class 
     MyActivityTest 
      
     { 
      
     ... 
      
     private 
      
     static 
      
     final 
      
     Context 
      
     context 
      
     = 
      
     ApplicationProvider 
     . 
     getApplicationContext 
     (); 
      
     private 
      
     final 
      
     FakeModuleInstallClient 
      
     fakeModuleInstallClient 
      
     = 
      
     new 
      
     FakeModuleInstallClient 
     ( 
     context 
     ); 
      
     @BindValue 
      
     ModuleInstallClient 
      
     moduleInstallClient 
      
     = 
      
     fakeModuleInstallClient 
     ; 
      
     ... 
     } 
    

Simulate different scenarios

With FakeModuleInstallClient , you can simulate different scenarios, such as:

  • Modules are already installed.
  • Modules are not available on the device.
  • The installation process fails.
  • The deferred install request is successful or fails.
  • The urgent install request is successful or fails.

Kotlin

 @Test 
 fun 
  
 checkAvailability_available 
 () 
  
 { 
  
 // Reset any previously installed modules. 
  
 fakeModuleInstallClient 
 . 
 reset 
 () 
  
 val 
  
 availableModule 
  
 = 
  
 TfLite 
 . 
 getClient 
 ( 
 context 
 ) 
  
 fakeModuleInstallClient 
 . 
 setInstalledModules 
 ( 
 api 
 ) 
  
 // Verify the case where modules are already available... 
 } 
 @Test 
 fun 
  
 checkAvailability_unavailable 
 () 
  
 { 
  
 // Reset any previously installed modules. 
  
 fakeModuleInstallClient 
 . 
 reset 
 () 
  
 // Do not set any installed modules in the test. 
  
 // Verify the case where modules unavailable on device... 
 } 
 @Test 
 fun 
  
 checkAvailability_failed 
 () 
  
 { 
  
 // Reset any previously installed modules. 
  
 fakeModuleInstallClient 
 . 
 reset 
 () 
  
 fakeModuleInstallClient 
 . 
 setModulesAvailabilityTask 
 ( 
 Tasks 
 . 
 forException 
 ( 
 RuntimeException 
 ())) 
  
 // Verify the case where an RuntimeException happened when trying to get module's availability... 
 } 

Java

 @Test 
 public 
  
 void 
  
 checkAvailability_available 
 () 
  
 { 
  
 // Reset any previously installed modules. 
  
 fakeModuleInstallClient 
 . 
 reset 
 (); 
  
 OptionalModuleApi 
  
 optionalModuleApi 
  
 = 
  
 TfLite 
 . 
 getClient 
 ( 
 context 
 ); 
  
 fakeModuleInstallClient 
 . 
 setInstalledModules 
 ( 
 api 
 ); 
  
 // Verify the case where modules are already available... 
 } 
 @Test 
 public 
  
 void 
  
 checkAvailability_unavailable 
 () 
  
 { 
  
 // Reset any previously installed modules. 
  
 fakeModuleInstallClient 
 . 
 reset 
 (); 
  
 // Do not set any installed modules in the test. 
  
 // Verify the case where modules unavailable on device... 
 } 
 @Test 
 public 
  
 void 
  
 checkAvailability_failed 
 () 
  
 { 
  
 fakeModuleInstallClient 
 . 
 setModulesAvailabilityTask 
 ( 
 Tasks 
 . 
 forException 
 ( 
 new 
  
 RuntimeException 
 ())); 
  
 // Verify the case where an RuntimeException happened when trying to get module's availability... 
 } 

Simulate result for a deferred install request

Kotlin

 @Test 
 fun 
  
 deferredInstall_success 
 () 
  
 { 
  
 fakeModuleInstallClient 
 . 
 setDeferredInstallTask 
 ( 
 Tasks 
 . 
 forResult 
 ( 
 null 
 )) 
  
 // Verify the case where the deferred install request has been sent successfully... 
 } 
 @Test 
 fun 
  
 deferredInstall_failed 
 () 
  
 { 
  
 fakeModuleInstallClient 
 . 
 setDeferredInstallTask 
 ( 
 Tasks 
 . 
 forException 
 ( 
 RuntimeException 
 ())) 
  
 // Verify the case where an RuntimeException happened when trying to send the deferred install request... 
 } 

Java

 @Test 
 public 
  
 void 
  
 deferredInstall_success 
 () 
  
 { 
  
 fakeModuleInstallClient 
 . 
 setDeferredInstallTask 
 ( 
 Tasks 
 . 
 forResult 
 ( 
 null 
 )); 
  
 // Verify the case where the deferred install request has been sent successfully... 
 } 
 @Test 
 public 
  
 void 
  
 deferredInstall_failed 
 () 
  
 { 
  
 fakeModuleInstallClient 
 . 
 setDeferredInstallTask 
 ( 
 Tasks 
 . 
 forException 
 ( 
 new 
  
 RuntimeException 
 ())); 
  
 // Verify the case where an RuntimeException happened when trying to send the deferred install request... 
 } 

Simulate result for an urgent install request

Kotlin

 @Test 
 fun 
  
 installModules_alreadyExist 
 () 
  
 { 
  
 // Reset any previously installed modules. 
  
 fakeModuleInstallClient 
 . 
 reset 
 (); 
  
 OptionalModuleApi 
  
 optionalModuleApi 
  
 = 
  
 TfLite 
 . 
 getClient 
 ( 
 context 
 ); 
  
 fakeModuleInstallClient 
 . 
 setInstalledModules 
 ( 
 api 
 ); 
  
 // Verify the case where the modules already exist when sending the install request... 
 } 
 @Test 
 fun 
  
 installModules_withoutListener 
 () 
  
 { 
  
 // Reset any previously installed modules. 
  
 fakeModuleInstallClient 
 . 
 reset 
 (); 
  
 // Verify the case where the urgent install request has been sent successfully... 
 } 
 @Test 
 fun 
  
 installModules_withListener 
 () 
  
 { 
  
 // Reset any previously installed modules. 
  
 fakeModuleInstallClient 
 . 
 reset 
 (); 
  
 // Generates a ModuleInstallResponse and set it as the result for installModules(). 
  
 val 
  
 moduleInstallResponse 
  
 = 
  
 FakeModuleInstallUtil 
 . 
 generateModuleInstallResponse 
 () 
  
 fakeModuleInstallClient 
 . 
 setInstallModulesTask 
 ( 
 Tasks 
 . 
 forResult 
 ( 
 moduleInstallResponse 
 )) 
  
 // Verify the case where the urgent install request has been sent successfully... 
  
 // Generates some fake ModuleInstallStatusUpdate and send it to listener. 
  
 val 
  
 update 
  
 = 
  
 FakeModuleInstallUtil 
 . 
 createModuleInstallStatusUpdate 
 ( 
  
 moduleInstallResponse 
 . 
 sessionId 
 , 
  
 STATE_COMPLETED 
 ) 
  
 fakeModuleInstallClient 
 . 
 sendInstallUpdates 
 ( 
 listOf 
 ( 
 update 
 )) 
  
 // Verify the corresponding updates are handled correctly... 
 } 
 @Test 
 fun 
  
 installModules_failed 
 () 
  
 { 
  
 fakeModuleInstallClient 
 . 
 setInstallModulesTask 
 ( 
 Tasks 
 . 
 forException 
 ( 
 RuntimeException 
 ())) 
  
 // Verify the case where an RuntimeException happened when trying to send the urgent install request... 
 } 

Java

 @Test 
 public 
  
 void 
  
 installModules_alreadyExist 
 () 
  
 { 
  
 // Reset any previously installed modules. 
  
 fakeModuleInstallClient 
 . 
 reset 
 (); 
  
 OptionalModuleApi 
  
 optionalModuleApi 
  
 = 
  
 TfLite 
 . 
 getClient 
 ( 
 context 
 ); 
  
 fakeModuleInstallClient 
 . 
 setInstalledModules 
 ( 
 api 
 ); 
  
 // Verify the case where the modules already exist when sending the install request... 
 } 
 @Test 
 public 
  
 void 
  
 installModules_withoutListener 
 () 
  
 { 
  
 // Reset any previously installed modules. 
  
 fakeModuleInstallClient 
 . 
 reset 
 (); 
  
 // Verify the case where the urgent install request has been sent successfully... 
 } 
 @Test 
 public 
  
 void 
  
 installModules_withListener 
 () 
  
 { 
  
 // Reset any previously installed modules. 
  
 fakeModuleInstallClient 
 . 
 reset 
 (); 
  
 // Generates a ModuleInstallResponse and set it as the result for installModules(). 
  
 ModuleInstallResponse 
  
 moduleInstallResponse 
  
 = 
  
 FakeModuleInstallUtil 
 . 
 generateModuleInstallResponse 
 (); 
  
 fakeModuleInstallClient 
 . 
 setInstallModulesTask 
 ( 
 Tasks 
 . 
 forResult 
 ( 
 moduleInstallResponse 
 )); 
  
 // Verify the case where the urgent install request has been sent successfully... 
  
 // Generates some fake ModuleInstallStatusUpdate and send it to listener. 
  
 ModuleInstallStatusUpdate 
  
 update 
  
 = 
  
 FakeModuleInstallUtil 
 . 
 createModuleInstallStatusUpdate 
 ( 
  
 moduleInstallResponse 
 . 
 getSessionId 
 (), 
  
 STATE_COMPLETED 
 ); 
  
 fakeModuleInstallClient 
 . 
 sendInstallUpdates 
 ( 
 ImmutableList 
 . 
 of 
 ( 
 update 
 )); 
  
 // Verify the corresponding updates are handled correctly... 
 } 
 @Test 
 public 
  
 void 
  
 installModules_failed 
 () 
  
 { 
  
 fakeModuleInstallClient 
 . 
 setInstallModulesTask 
 ( 
 Tasks 
 . 
 forException 
 ( 
 new 
  
 RuntimeException 
 ())); 
  
 // Verify the case where an RuntimeException happened when trying to send the urgent install request... 
 } 
Create a Mobile Website
View Site in Mobile | Classic
Share by: