66
77import android .annotation .SuppressLint ;
88import android .content .Context ;
9+ import android .content .pm .ApplicationInfo ;
10+ import android .content .pm .PackageManager ;
911import android .content .pm .PackageManager .NameNotFoundException ;
1012import android .content .res .AssetManager ;
1113import android .os .Build ;
14+ import android .os .Bundle ;
1215import android .util .SparseArray ;
1316import android .util .SparseIntArray ;
1417import androidx .annotation .NonNull ;
@@ -53,6 +56,8 @@ public class PlayStoreDeferredComponentManager implements DeferredComponentManag
5356 private @ NonNull SparseArray <String > sessionIdToState ;
5457 private @ NonNull Map <String , Integer > nameToSessionId ;
5558
59+ protected @ NonNull SparseArray <String > loadingUnitIdToModuleNames ;
60+
5661 private FeatureInstallStateUpdatedListener listener ;
5762
5863 private class FeatureInstallStateUpdatedListener implements SplitInstallStateUpdatedListener {
@@ -202,6 +207,9 @@ public PlayStoreDeferredComponentManager(
202207 sessionIdToLoadingUnitId = new SparseIntArray ();
203208 sessionIdToState = new SparseArray <>();
204209 nameToSessionId = new HashMap <>();
210+
211+ loadingUnitIdToModuleNames = new SparseArray <>();
212+ initLoadingUnitMappingToModuleNames ();
205213 }
206214
207215 public void setJNI (@ NonNull FlutterJNI flutterJNI ) {
@@ -222,19 +230,49 @@ public void setDeferredComponentChannel(DeferredComponentChannel channel) {
222230 this .channel = channel ;
223231 }
224232
225- private String loadingUnitIdToModuleName (int loadingUnitId ) {
226- // Loading unit id to module name mapping stored in android Strings
227- // resources.
228- int moduleNameIdentifier =
229- context
230- .getResources ()
231- .getIdentifier ("loadingUnit" + loadingUnitId , "string" , context .getPackageName ());
232- return context .getResources ().getString (moduleNameIdentifier );
233+ @ NonNull
234+ private ApplicationInfo getApplicationInfo () {
235+ try {
236+ return context
237+ .getPackageManager ()
238+ .getApplicationInfo (context .getPackageName (), PackageManager .GET_META_DATA );
239+ } catch (NameNotFoundException e ) {
240+ throw new RuntimeException (e );
241+ }
242+ }
243+
244+ // Obtain and parses the metadata string. An example encoded string is:
245+ //
246+ // "2:module2,3:module3,4:module1"
247+ //
248+ // Where loading unit 2 is included in module2, loading unit 3 is
249+ // included in module3, and loading unit 4 is included in module1.
250+ private void initLoadingUnitMappingToModuleNames () {
251+ String mappingKey = DeferredComponentManager .class .getName () + ".loadingUnitMapping" ;
252+ ApplicationInfo applicationInfo = getApplicationInfo ();
253+ if (applicationInfo != null ) {
254+ Bundle metaData = applicationInfo .metaData ;
255+ if (metaData != null ) {
256+ String rawMappingString = metaData .getString (mappingKey , null );
257+ if (rawMappingString == null ) {
258+ Log .e (
259+ TAG ,
260+ "No loading unit to dynamic feature module name found. Ensure '"
261+ + mappingKey
262+ + "' is defined in the base module's AndroidManifest." );
263+ } else {
264+ for (String entry : rawMappingString .split ("," )) {
265+ String [] splitEntry = entry .split (":" );
266+ loadingUnitIdToModuleNames .put (Integer .parseInt (splitEntry [0 ]), splitEntry [1 ]);
267+ }
268+ }
269+ }
270+ }
233271 }
234272
235273 public void installDeferredComponent (int loadingUnitId , String moduleName ) {
236274 String resolvedModuleName =
237- moduleName != null ? moduleName : loadingUnitIdToModuleName (loadingUnitId );
275+ moduleName != null ? moduleName : loadingUnitIdToModuleNames . get (loadingUnitId );
238276 if (resolvedModuleName == null ) {
239277 Log .e (
240278 TAG ,
@@ -297,7 +335,7 @@ public void installDeferredComponent(int loadingUnitId, String moduleName) {
297335
298336 public String getDeferredComponentInstallState (int loadingUnitId , String moduleName ) {
299337 String resolvedModuleName =
300- moduleName != null ? moduleName : loadingUnitIdToModuleName (loadingUnitId );
338+ moduleName != null ? moduleName : loadingUnitIdToModuleNames . get (loadingUnitId );
301339 if (resolvedModuleName == null ) {
302340 Log .e (
303341 TAG ,
@@ -400,7 +438,7 @@ public void loadDartLibrary(int loadingUnitId, String moduleName) {
400438
401439 public boolean uninstallDeferredComponent (int loadingUnitId , String moduleName ) {
402440 String resolvedModuleName =
403- moduleName != null ? moduleName : loadingUnitIdToModuleName (loadingUnitId );
441+ moduleName != null ? moduleName : loadingUnitIdToModuleNames . get (loadingUnitId );
404442 if (resolvedModuleName == null ) {
405443 Log .e (
406444 TAG ,
@@ -410,7 +448,9 @@ public boolean uninstallDeferredComponent(int loadingUnitId, String moduleName)
410448 List <String > modulesToUninstall = new ArrayList <>();
411449 modulesToUninstall .add (resolvedModuleName );
412450 splitInstallManager .deferredUninstall (modulesToUninstall );
413- sessionIdToState .delete (nameToSessionId .get (resolvedModuleName ));
451+ if (nameToSessionId .get (resolvedModuleName ) != null ) {
452+ sessionIdToState .delete (nameToSessionId .get (resolvedModuleName ));
453+ }
414454 return true ;
415455 }
416456
0 commit comments