package Ġcom . j ep pe man . glob ally dynamic . gradle Ċ Ċ import Ġcom . google . common . truth . Truth . assertThat Ċ import Ġcom . google . gson . Gson Ċ import Ġorg . gradle . test kit . runner . Task Outcome Ċ import Ġorg . junit . jupiter . api . Test Ċ import Ġorg . junit . platform . runner . JUnit Platform Ċ import Ġorg . junit . runner . RunWith Ċ import Ġjava . io . ByteArray OutputStream Ċ import Ġjava . io . OutputStream Ċ import Ġjava . io . PrintWriter Ċ import Ġjava . io . String Writer Ċ import Ġjava . net . URI Ċ import Ġjava . nio . file . Path Ċ import Ġjava . util .* Ċ import Ġjavax . tools .* Ċ Ċ @ RunWith ( JUnit Platform :: class ) Ċ class ĠWrite Configuration Source Files Task Test Ġ: ĠBase Task Test () Ġ{ ĊĠĠĠ Ġprivate Ġlateinit Ġvar Ġconfiguration Path : ĠPath ĊĠĠĠ Ġprivate Ġlateinit Ġvar Ġglobally Dynamic Build ConfigPath : ĠPath ĊĠĠĠ Ġprivate Ġlateinit Ġvar Ġdevice Feature Condition Path : ĠPath ĊĠĠĠ Ġprivate Ġlateinit Ġvar Ġmodule Conditions Path : ĠPath ĊĠĠĠ Ġprivate Ġlateinit Ġvar Ġuser Countries Condition Path : ĠPath ĊĠĠĠ Ġoverride Ġval Ġon Demand Feature Name : ĠString Ġ= Ġ" dynamic " ĊĠĠĠ Ġoverride Ġval Ġinstall Time Feature Name : ĠString Ġ= Ġ" install time feature " ĊĠĠĠ Ġoverride Ġval Ġtask Name : ĠString Ġ= Ġ": app : write Glob ally Dynamic Configuration Source Files For ${ VARIANT . capitalize () }" ĊĊĠĠĠ Ġoverride Ġfun ĠbeforeEach () Ġ{ ĊĠĠĠĠĠĠĠ Ġconfiguration Path Ġ= Ġapp Module Project DirPath . resolve (" build ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. resolve (" generated ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. resolve (" source ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. resolve (" glob ally dynamic ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. resolve ( VARIANT ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. resolve (" com ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. resolve (" j ep pe man ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. resolve (" glob ally dynamic ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. resolve (" generated ") ĊĊĠĠĠĠĠĠĠ Ġglobally Dynamic Build ConfigPath Ġ= Ġconfiguration Path . resolve (" Glob ally Dynamic Build Config . java ") ĊĠĠĠĠĠĠĠ Ġdevice Feature Condition Path Ġ= Ġconfiguration Path . resolve (" Device Feature Condition . java ") ĊĠĠĠĠĠĠĠ Ġmodule Conditions Path Ġ= Ġconfiguration Path . resolve (" Module Conditions . java ") ĊĠĠĠĠĠĠĠ Ġuser Countries Condition Path Ġ= Ġconfiguration Path . resolve (" User Countries Condition . java ") ĊĠĠĠĠĠĠĠĠĊĠĠĠĠĠĠĠ Ġapp Module Android Manifest FilePath . to File (). write Text ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ""" ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ< manifest Ġxmlns : android =" http :// schemas . android . com / apk / res / android " ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpackage ="$ BASE _ PACKAGE _ NAME "> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ< application > ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ< activity Ġandroid : exported =" true " Ġandroid : name ="$ MAIN _ ACTIVITY _ NAME " Ġ> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ< intent - filter > ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ< action Ġandroid : name =" android . intent . action . VIEW " Ġ/> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ< action Ġandroid : name =" android . intent . action . MAIN " Ġ/> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ< category Ġandroid : name =" android . intent . category . LA UNCH ER " Ġ/> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ</ intent - filter > ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ</ activity > ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ</ application > ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ</ manifest > ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ""" . trim Indent () ĊĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠ Ġapp Module Build FilePath . to File (). write Text ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ""" ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġplugins Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġid Ġ' com . android . application ' ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġid Ġ' com . j ep pe man . glob ally dynamic ' ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġandroid Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdefault Config Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcompile Sdk Version Ġ 3 2 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmin Sdk Version Ġ 1 6 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtarget Sdk Version Ġ 3 2 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġversion Code Ġ$ VERSION _ CODE ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbuild Types Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ$ VARIANT Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmatching Fallback s Ġ= Ġ[' debug '] ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġglobally Dynamic Servers Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġserver Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġserver Url Ġ= Ġ"$ SERVER _ URL " ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġusername Ġ= Ġ"$ USERNAME " ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpassword Ġ= Ġ"$ PASSWORD " ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrottle Download By Ġ= Ġ$ TH RO TT LE _ DOWNLOAD _ BY ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġapply To Build Variants Ġ'$ VARIANT ' ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdynamic Features Ġ= Ġ[ ': $ on Demand Feature Name ', Ġ': $ install Time Feature Name '] ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdependencies Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġimplementation Ġ' com . j ep pe man . glob ally dynamic . android : self hosted :${ ANDROID _ LIB _ VERSION }' ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġimplementation Ġ' android x . appcompat : appcompat : 1 . 4 . 2 ' ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ""" . trim Indent () ĊĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠ Ġon Demand Feature Android Manifest FilePath . to File (). write Text ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ""" ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ< manifest Ġxmlns : android =" http :// schemas . android . com / apk / res / android " ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġxmlns : dist =" http :// schemas . android . com / apk / distribution " ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpackage ="$ BASE _ PACKAGE _ NAME "> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ< application /> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ< dist : module ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdist : instant =" false " ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdist : title =" Dynamic "> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ< dist : delivery > ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ< dist : on - demand Ġ/> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ</ dist : delivery > ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ< dist : f using Ġdist : include =" true " Ġ/> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ</ dist : module > ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ</ manifest > ĠĊĠĠĠĠĠĠĠĠĠĠĠ Ġ""" . trim Indent () ĊĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠ Ġinstall Time Feature Android Manifest FilePath . to File (). write Text ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ""" ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ< manifest Ġxmlns : android =" http :// schemas . android . com / apk / res / android " ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġxmlns : dist =" http :// schemas . android . com / apk / distribution " ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpackage ="$ BASE _ PACKAGE _ NAME "> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ< application /> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ< dist : module ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdist : instant =" false " ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdist : title =" Install ĠTime "> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ< dist : delivery > ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ< dist : install - time > ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ< dist : conditions > ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ< dist : user - countries Ġdist : exclude =" false "> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ< dist : country Ġdist : code ="${ INSTALL _ TIME _ USER _ COUN TR IES [ 0 ]} "/> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ< dist : country Ġdist : code ="${ INSTALL _ TIME _ USER _ COUN TR IES [ 1 ]} "/> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ</ dist : user - countries > ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ< dist : device - feature Ġdist : name ="${ INSTALL _ TIME _ DEVICE _ FEATURES [ 0 ]} "/> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ< dist : device - feature Ġdist : name ="${ INSTALL _ TIME _ DEVICE _ FEATURES [ 1 ]} "/> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ< dist : min - sdk Ġdist : value ="$ INSTALL _ TIME _ MIN _ SDK "/> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ</ dist : conditions > ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ</ dist : install - time > ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ</ dist : delivery > ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ< dist : f using Ġdist : include =" true " Ġ/> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ</ dist : module > ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ</ manifest > ĠĊĠĠĠĠĠĠĠĠĠĠĠ Ġ""" . trim Indent () ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġcompile Generated Files (): ĠAny Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġcompiler Ġ= ĠTool Provider . getSystem Java Compiler () ĊĠĠĠĠĠĠĠ Ġval Ġfm Ġ= Ġcompiler . get Standard FileManager ( null , ĠLocale . EN GL ISH , ĠChar sets . UTF _ 8 ) ĊĠĠĠĠĠĠĠ Ġval Ġfile Manager Ġ= ĠSimple Java FileManager ( fm ) ĊĠĠĠĠĠĠĠ Ġval Ġfiles Ġ= Ġfm . get Java File Objects ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdevice Feature Condition Path . to File (), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmodule Conditions Path . to File (), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġuser Countries Condition Path . to File (), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġglobally Dynamic Build ConfigPath . to File () ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġval Ġstring Writer Ġ= ĠString Writer () ĊĠĠĠĠĠĠĠ Ġval Ġwriter Ġ= ĠPrintWriter ( string Writer ) ĊĠĠĠĠĠĠĠ Ġval Ġtask Ġ= Ġcompiler . get Task ( writer , Ġfile Manager , Ġnull , Ġnull , Ġnull , Ġfiles ) ĊĠĠĠĠĠĠĠ Ġval Ġsuccess Ġ= Ġtask . call () ĊĠĠĠĠĠĠĠ Ġreturn Ġif Ġ( success ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġclass Loader Ġ= ĠComp iled ClassLoader ( file Manager . generated Output Files ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġclass Loader . load Class ( GLOB ALLY _ DYNAMIC _ BUILD _ CONFIG _ CLASS ). newInstance () ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠException ( string Writer . toString ()) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġwhen Configuration Is Provided Through Dsl _ task _ should Generate Files Acc ording ly () Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġresult Ġ= Ġrun Task () ĊĠĠĠĠĠĠĠ Ġval Ġglobally Dynamic Build Config Ġ= Ġcompile Generated Files () ĊĠĠĠĠĠĠĠ Ġval Ġinstall Time Features Ġ= Ġglobally Dynamic Build Config . invoke Method < Map < String , ĠAny >> (" get Install Time Features ") ĊĠĠĠĠĠĠĠ Ġval Ġinstall Time Feature Module Conditions Ġ= Ġinstall Time Features [ install Time Feature Name ] Ġ?: Ġerror ("") ĊĠĠĠĠĠĠĠ Ġval Ġinstall Time Min Sdk Ġ= Ġinstall Time Feature Module Conditions . invoke Method < Int >(" getMin Sdk Condition ") ĊĠĠĠĠĠĠĠ Ġval Ġinstall Time User Countries Condition Ġ= Ġinstall Time Feature Module Conditions . invoke Method < Any >(" getUser Countries Condition ") ĊĠĠĠĠĠĠĠ Ġval Ġinstall Time User Countries Ġ= Ġinstall Time User Countries Condition . invoke Method < Array < String >> (" getCount ries "). toList () ĊĠĠĠĠĠĠĠ Ġval Ġinstall Time User Countries Exclude Ġ= Ġinstall Time User Countries Condition . invoke Method < Boolean >(" get Exclude ") ĊĠĠĠĠĠĠĠ Ġval Ġinstall Time Device Feature Conditions Ġ= Ġinstall Time Feature Module Conditions . invoke Method < Array < Any >> (" getDevice Feature Conditions ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġit . invoke Method < String >(" get Feature Name ") Ġ} ĊĊĠĠĠĠĠĠĠ ĠassertThat ( result . task ( task Name )?. outcome ). isEqualTo ( Task Outcome . SUCCESS ) ĊĠĠĠĠĠĠĠ ĠassertThat ( install Time Min Sdk ). isEqualTo ( INSTALL _ TIME _ MIN _ SDK ) ĊĠĠĠĠĠĠĠ ĠassertThat ( install Time User Countries ). isEqualTo ( INSTALL _ TIME _ USER _ COUN TR IES ) ĊĠĠĠĠĠĠĠ ĠassertThat ( install Time User Countries Exclude ). isFalse () ĊĠĠĠĠĠĠĠ ĠassertThat ( install Time Device Feature Conditions ). isEqualTo ( INSTALL _ TIME _ DEVICE _ FEATURES ) ĊĠĠĠĠĠĠĠ ĠassertThat ( glob ally Dynamic Build Config . invoke Method < String >(" get MainActivity Fully QualifiedName ")). isEqualTo ( MAIN _ ACTIVITY _ NAME ) ĊĠĠĠĠĠĠĠ ĠassertThat ( glob ally Dynamic Build Config . invoke Method < String >(" getServer Url ")). isEqualTo ( SERVER _ URL ) ĊĠĠĠĠĠĠĠ ĠassertThat ( glob ally Dynamic Build Config . invoke Method < String >(" get Variant Name ")). isEqualTo ( VARIANT ) ĊĠĠĠĠĠĠĠ ĠassertThat ( glob ally Dynamic Build Config . invoke Method < Long >(" get Throttle Download By ")). isEqualTo ( TH RO TT LE _ DOWNLOAD _ BY ) ĊĠĠĠĠĠĠĠ ĠassertThat ( glob ally Dynamic Build Config . invoke Method < Int >(" getVersion Code ")). isEqualTo ( VERSION _ CODE ) ĊĠĠĠĠĠĠĠ ĠassertThat ( glob ally Dynamic Build Config . invoke Method < Array < String >> (" get On Demand Features ")). isEqualTo ( array Of ( on Demand Feature Name )) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġwhen Configuration Is Provided Through Arguments _ task _ should Generate Files Acc ording ly () Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġserver Url Argument Ġ= Ġ" http :// program . argument " ĊĠĠĠĠĠĠĠ Ġval Ġthrottle By Argument Ġ= Ġ 1 0 0 0 ĊĊĠĠĠĠĠĠĠ Ġval Ġresult Ġ= Ġrun Task ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ"- P glob ally Dynamic Server . server Url =$ server Url Argument ", ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ"- P glob ally Dynamic Server . throttle Download By =$ throttle By Argument ") ĊĠĠĠĠĠĠĠ Ġval Ġglobally Dynamic Build Config Ġ= Ġcompile Generated Files () ĊĊĠĠĠĠĠĠĠ ĠassertThat ( result . task ( task Name )?. outcome ). isEqualTo ( Task Outcome . SUCCESS ) ĊĠĠĠĠĠĠĠ ĠassertThat ( glob ally Dynamic Build Config . invoke Method < String >(" getServer Url ")). isEqualTo ( server Url Argument ) ĊĠĠĠĠĠĠĠ ĠassertThat ( glob ally Dynamic Build Config . invoke Method < Long >(" get Throttle Download By ")). isEqualTo ( throttle By Argument ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġwhen Configuration Is Provided Through File _ task _ should Generate Files Acc ording ly () Ġ{ ĊĠĠĠĠĠĠĠ Ġapp Module Build FilePath . to File (). write Text ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ""" ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġplugins Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġid Ġ' com . android . application ' ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġid Ġ' com . j ep pe man . glob ally dynamic ' ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġandroid Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdefault Config Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcompile Sdk Version Ġ 3 2 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmin Sdk Version Ġ 1 6 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtarget Sdk Version Ġ 3 2 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġversion Code Ġ$ VERSION _ CODE ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbuild Types Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ$ VARIANT Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmatching Fallback s Ġ= Ġ[' debug '] ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġglobally Dynamic Servers Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġserver Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrottle Download By Ġ= Ġ$ TH RO TT LE _ DOWNLOAD _ BY ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġapply To Build Variants Ġ'$ VARIANT ' ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdynamic Features Ġ= Ġ[ ': $ on Demand Feature Name ', Ġ': $ install Time Feature Name '] ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdependencies Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġimplementation Ġ' com . j ep pe man . glob ally dynamic . android : self hosted :${ ANDROID _ LIB _ VERSION }' ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġimplementation Ġ' android x . appcompat : appcompat : 1 . 4 . 2 ' ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ""" . trim Indent () ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġval Ġglobally Dynamic Server Info Ġ= ĠG lob ally Dynamic Server Info Dto ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġserver Url Ġ= Ġ" http :// server . url ", ĊĠĠĠĠĠĠĠĠĠĠĠ Ġusername Ġ= Ġ" username ", ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpassword Ġ= Ġ" password " ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġapp Module Project DirPath . resolve (" build ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. resolve (" glob ally dynamic ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. apply Ġ{ Ġto File (). mkdir s () Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. resolve (" server _ info . json ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. to File () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. write Text ( Gson (). toJson ( glob ally Dynamic Server Info )) ĊĊĠĠĠĠĠĠĠ Ġval Ġresult Ġ= Ġrun Task () ĊĠĠĠĠĠĠĠ Ġval Ġglobally Dynamic Build Config Ġ= Ġcompile Generated Files () ĊĊĠĠĠĠĠĠĠ ĠassertThat ( result . task ( task Name )?. outcome ). isEqualTo ( Task Outcome . SUCCESS ) ĊĠĠĠĠĠĠĠ ĠassertThat ( glob ally Dynamic Build Config . invoke Method < String >(" getServer Url ")). isEqualTo ( glob ally Dynamic Server Info . server Url ) ĊĠĠĠĠĠĠĠ ĠassertThat ( glob ally Dynamic Build Config . invoke Method < Long >(" get Throttle Download By ")). isEqualTo ( TH RO TT LE _ DOWNLOAD _ BY ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠCLASS _ PREFIX Ġ= Ġ" com . j ep pe man . glob ally dynamic . generated " ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠG LOB ALLY _ DYNAMIC _ BUILD _ CONFIG _ CLASS Ġ= Ġ"$ CLASS _ PREFIX . Glob ally Dynamic Build Config " ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠMAIN _ ACTIVITY _ NAME Ġ= Ġ"$ BASE _ PACKAGE _ NAME . Glob ally Dynamic Activity " ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠSERVER _ URL Ġ= Ġ" http :// glob ally dynamic . io " ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠUSER NAME Ġ= Ġ" username " ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠPASSWORD Ġ= Ġ" password " ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠTH RO TT LE _ DOWNLOAD _ BY Ġ= Ġ 5 0 0 0 ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠVARI ANT Ġ= Ġ" instrumentation " ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠVERSION _ CODE Ġ= Ġ 5 ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠINSTALL _ TIME _ MIN _ SDK Ġ= Ġ 1 6 ĊĠĠĠĠĠĠĠ Ġprivate Ġval ĠINSTALL _ TIME _ USER _ COUN TR IES Ġ= ĠlistOf (" CN ", Ġ" HK ") ĊĠĠĠĠĠĠĠ Ġprivate Ġval ĠINSTALL _ TIME _ DEVICE _ FEATURES Ġ= ĠlistOf (" android . hardware . camera . ar ", Ġ" android . hardware . camera . vr ") ĊĠĠĠ Ġ} Ċ } Ċ Ċ private Ġfun Ġ< T Ġ: ĠAny > ĠAny . invoke Method ( method : ĠString ): ĠT Ġ= ĊĠĠĠ Ġthis :: class . java . getDeclared Method ( method ). invoke ( this ) Ġas ĠT Ċ Ċ private Ġclass ĠClass Java FileObject ( val ĠclassName : ĠString , Ġkind : ĠJava FileObject . Kind ) Ġ: ĠSimple Java FileObject ( ĊĠĠĠ ĠURI . create (" mem :// /" Ġ+ ĠclassName . replace ('.', Ġ'/') Ġ+ Ġkind . extension ), Ġkind Ċ ) Ġ{ ĊĠĠĠ Ġprivate Ġval ĠoutputStream Ġ= ĠByteArrayOutputStream () ĊĊĠĠĠ Ġoverride Ġfun Ġopen OutputStream (): ĠOutputStream Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn ĠoutputStream ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġget Bytes (): ĠByteArray Ġ= ĠoutputStream . toByteArray () Ċ } Ċ Ċ private Ġclass ĠComp iled ClassLoader ( private Ġval Ġfiles : ĠMutable List < Class Java FileObject >) Ġ: ĠClassLoader () Ġ{ ĊĠĠĠ Ġoverride Ġfun Ġfind Class ( name : ĠString ?): ĠClass < *> Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġiterator Ġ= Ġfiles . iterator () ĊĠĠĠĠĠĠĠ Ġwhile Ġ( iterator . hasNext ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġfile Ġ= Ġiterator . next () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( file . className Ġ== Ġname ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġiterator . remove () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġbytes Ġ= Ġfile . getBytes () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġsuper . define Class ( name , Ġbytes , Ġ 0 , Ġbytes . size ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn Ġsuper . find Class ( name ) ĊĠĠĠ Ġ} Ċ } Ċ Ċ private Ġclass ĠSimple Java FileManager ( ĊĠĠĠ Ġjava FileManager : ĠJava FileManager Ċ ) Ġ: ĠForward ing Java FileManager < Java FileManager >( ĊĠĠĠ Ġjava FileManager Ċ ) Ġ{ ĊĠĠĠ Ġval Ġgenerated Output Files Ġ= Ġmutable ListOf < Class Java FileObject >() ĊĊĠĠĠ Ġoverride Ġfun Ġget Java File For Output ( location : ĠJava FileManager . Location ?, ĠclassName : ĠString ?, Ġkind : ĠJava FileObject . Kind ?, Ġsibling : ĠFile Object ?): ĠJava FileObject Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġclass Java FileObject Ġ= ĠClass Java FileObject ( className !! , Ġkind !! ) ĊĠĠĠĠĠĠĠ Ġgenerated Output Files . add ( class Java FileObject ) ĊĠĠĠĠĠĠĠ Ġreturn Ġclass Java FileObject ĊĠĠĠ Ġ} Ċ }