Slide 1

Slide 1 text

1

Slide 2

Slide 2 text

OSS Android libraries developed 2

Slide 3

Slide 3 text

How does Gradle process Android Libraries @nisrulz 3

Slide 4

Slide 4 text

How does Gradle process Android Libraries repositories { jCenter() } dependencies { implementation 'com.github.nisrulz:awesomelib:1.0' ... } 4 @nisrulz

Slide 5

Slide 5 text

How does Gradle process Android Libraries repositories { jCenter() } dependencies { implementation 'com.github.nisrulz:awesomelib:1.0' ... } 5 @nisrulz // Dependency Notation

Slide 6

Slide 6 text

How does Gradle process Android Libraries repositories { jCenter() } dependencies { implementation 'com/github/nisrulz/awesomelib/1.0' ... } 6 @nisrulz

Slide 7

Slide 7 text

How does Gradle process Android Libraries implementation 'com.github.nisrulz:awesomelib:1.0' 7 @nisrulz

Slide 8

Slide 8 text

How does Gradle process Android Libraries implementation 'com/github/nisrulz/awesomelib/1.0' 8 @nisrulz

Slide 9

Slide 9 text

How does Gradle process Android Libraries implementation 'com/github/nisrulz/awesomelib/1.0' 9 @nisrulz

Slide 10

Slide 10 text

How does Gradle process Android Libraries implementation 'com/github/nisrulz/awesomelib/1.0' 10 @nisrulz

Slide 11

Slide 11 text

How does Gradle process Android Libraries implementation 'com.github.nisrulz:awesomelib:1.0' 11 @nisrulz

Slide 12

Slide 12 text

Android ARchive(AAR) @nisrulz 12

Slide 13

Slide 13 text

13 @nisrulz

Slide 14

Slide 14 text

14 @nisrulz

Slide 15

Slide 15 text

AAR = Java ARchive(JAR) + Resources 15 @nisrulz

Slide 16

Slide 16 text

AAR = Java ARchive(JAR) + Resources Sensey: https://github.com/nisrulz/sensey 16 @nisrulz

Slide 17

Slide 17 text

AAR = Java ARchive(JAR) + Resources @nisrulz 17

Slide 18

Slide 18 text

Sensey’s build.gradle dependencies { ... // Other testing dependencies // Transitive dependency: Support Compat library implementation "com.android.support:support-compat:27.0.2" } 18 @nisrulz

Slide 19

Slide 19 text

Using AAR as dependency @nisrulz 19

Slide 20

Slide 20 text

Using an AAR as dependency repositories{ flatDir{ dirs 'libs' } } dependencies { implementation(name:'nameOfYourAARFileWithoutExtension', ext:'aar') } @nisrulz 20

Slide 21

Slide 21 text

Using an AAR as dependency repositories{ flatDir{ dirs 'libs' } } dependencies { implementation(name:'nameOfYourAARFileWithoutExtension', ext:'aar') } // No transitive dependencies of the library are downloaded 21 @nisrulz

Slide 22

Slide 22 text

Why doesn’t my AAR download transitive dependencies? @nisrulz 22

Slide 23

Slide 23 text

Sensey’s AAR 23 @nisrulz

Slide 24

Slide 24 text

Sensey’s AAR No build.gradle file 24 @nisrulz

Slide 25

Slide 25 text

Maven Artifact 25 @nisrulz

Slide 26

Slide 26 text

Maven Artifact 26 @nisrulz

Slide 27

Slide 27 text

POM? 27 @nisrulz

Slide 28

Slide 28 text

POM ● Project Object Model ● XML file ● Configuration details used by Maven to build the project 28 @nisrulz

Slide 29

Slide 29 text

POM POM of Sensey Android Library 4.0.0 com.github.nisrulzsensey1.8.0 aarsensey Android library which makes playing with sensor events & detecting gestures a breeze. https://github.com/nisrulz/sensey The Apache Software License, Version 2.0http://www.apache.org/licenses/LICENSE-2.0.txt nisrulzNishant [email protected] https://github.com/nisrulz/sensey.git https://github.com/nisrulz/sensey.git https://github.com/nisrulz/sensey com.android.support support-compat27.0.2 runtime ... 29 @nisrulz

Slide 30

Slide 30 text

POM POM of Sensey Android Library 4.0.0 com.github.nisrulzsensey1.8.0 aarsensey Android library which makes playing with sensor events & detecting gestures a breeze. https://github.com/nisrulz/sensey The Apache Software License, Version 2.0http://www.apache.org/licenses/LICENSE-2.0.txt nisrulzNishant [email protected] https://github.com/nisrulz/sensey.git https://github.com/nisrulz/sensey.git https://github.com/nisrulz/sensey com.android.support support-compat27.0.2 runtime ... 30 @nisrulz

Slide 31

Slide 31 text

POM POM of Sensey Android Library ... com.android.support support-compat27.0.2 runtime ... 31 @nisrulz

Slide 32

Slide 32 text

Bundled Proguard Configs 32 @nisrulz

Slide 33

Slide 33 text

Bundled Proguard Configs android { release { minifyEnabled true // Rules to be used during the AAR generation proguardFiles 'proguard-rules-for-building-library.pro' } ... } 33 @nisrulz

Slide 34

Slide 34 text

Bundled Proguard Configs android { release { minifyEnabled true // Rules to be used during the AAR generation proguardFiles 'proguard-rules-for-building-library.pro' // Rules appended to the integrating app consumerProguardFiles 'proguard-rules-for-using-library.pro' } ... } 34 @nisrulz

Slide 35

Slide 35 text

Bundled Proguard Configs 35 @nisrulz

Slide 36

Slide 36 text

Bundled Proguard Configs 36 @nisrulz

Slide 37

Slide 37 text

Bundled Proguard Configs # Fuel’s bundled Proguard file # Without specifically keeping this class, # callbacks on android don't function properly. -keep class com.github.kittinunf.fuel.android.util.AndroidEnvironment 37 @nisrulz

Slide 38

Slide 38 text

Bundled Proguard Configs # DON'T DO THIS # Do not obfuscate the input class files -dontobfuscate # Optimizes variable allocation on the local variable frame. -optimizations !code/allocation/variable # Preserved as entry points -keep public class * { public protected *; } 38 @nisrulz

Slide 39

Slide 39 text

Bundled Proguard Configs # DON'T DO THIS # Adding the below in library proguard rules disables # the optimizations in the Android app -dontoptimize 39 @nisrulz

Slide 40

Slide 40 text

Bundled Proguard Configs # To check the merged configuration # Add the below to your app’s current proguard rules -printconfiguration proguard-merged-config.txt 40 @nisrulz

Slide 41

Slide 41 text

Bundled Proguard Configs 41 @nisrulz

Slide 42

Slide 42 text

Modularization 42 @nisrulz

Slide 43

Slide 43 text

Modularization 43 @nisrulz

Slide 44

Slide 44 text

Modularization EasyDeviceInfo: https://github.com/nisrulz/easydeviceinfo 44 @nisrulz

Slide 45

Slide 45 text

Modularization dependencies { def libVer = {latest_version} // Base + Ads Bundled Library implementation "com.github.nisrulz:easydeviceinfo:$libVer" // Base Library implementation "com.github.nisrulz:easydeviceinfo-base:$libVer" // Ads Library implementation "com.github.nisrulz:easydeviceinfo-ads:$libVer" } 45 @nisrulz

Slide 46

Slide 46 text

Modularization ... com.github.nisrulz easydeviceinfo-ads 2.5.0 compile com.github.nisrulz easydeviceinfo-base 2.5.0 compile ... 46 @nisrulz

Slide 47

Slide 47 text

Modularization ... com.github.nisrulz easydeviceinfo-ads 2.5.0 compile com.github.nisrulz easydeviceinfo-base 2.5.0 compile ... 47 @nisrulz

Slide 48

Slide 48 text

Modularization ... com.github.nisrulz easydeviceinfo-ads 2.5.0 compile com.github.nisrulz easydeviceinfo-base 2.5.0 compile ... 48 @nisrulz

Slide 49

Slide 49 text

Modularization ... com.github.nisrulz easydeviceinfo-common2.5.0 compile com.google.android.gms play-services-ads-identifier16.0.0 runtime ... 49 @nisrulz

Slide 50

Slide 50 text

Modularization ... com.github.nisrulz easydeviceinfo-common2.5.0 compile com.google.android.gms play-services-ads-identifier16.0.0 runtime ... 50 @nisrulz

Slide 51

Slide 51 text

Avoiding Resource Name Conflicts 51 @nisrulz

Slide 52

Slide 52 text

Conflict occurs between a library & app resource > Project will not compile What happens when... 52 @nisrulz

Slide 53

Slide 53 text

Conflict occurs between 2 libraries integrated in the app > Resources from library defined first in build.gradle gets included What happens when... 53 @nisrulz

Slide 54

Slide 54 text

Solution? 54 @nisrulz

Slide 55

Slide 55 text

Add a prefix to all your resources. Solution? 55 @nisrulz

Slide 56

Slide 56 text

Add a prefix to all your resources. How? Solution? 56 @nisrulz

Slide 57

Slide 57 text

Add a prefix to all your resources. How? ● Enforce this in Android Studio Solution? 57 @nisrulz

Slide 58

Slide 58 text

Add a prefix to all your resources. How? ● Enforce this in Android Studio ● Declare in build.gradle of library android { resourcePrefix 'YOUR_PREFIX_' // i.e 'sensey_' } Solution? 58 @nisrulz

Slide 59

Slide 59 text

Solution? Resource named ‘app_name’ does not start with the project’s resource prefix ‘sensey_’; Rename to `sensey_app_name`? 59 @nisrulz

Slide 60

Slide 60 text

minSdkVersion Restriction 60 @nisrulz

Slide 61

Slide 61 text

minSdkVersion of app >= minSdkVersion of library minSdk Restriction 61 @nisrulz

Slide 62

Slide 62 text

minSdk Restriction 62 @nisrulz

Slide 63

Slide 63 text

Manifest merger failed : uses-sdk:minSdkVersion 14 cannot be smaller than version 21 declared in library [:sensey] Suggestion: + Use a compatible library with a minSdk of at most 14 + Increase this project's minSdk version to at least 21 + Use tools:overrideLibrary="com.github.nisrulz.sensey" to force usage (may lead to runtime failures) minSdk Restriction 63 @nisrulz

Slide 64

Slide 64 text

Manifest merger failed : uses-sdk:minSdkVersion 14 cannot be smaller than version 21 declared in library [:sensey] Suggestion: + Use a compatible library with a minSdk of at most 14 + Increase this project's minSdk version to at least 21 + Use tools:overrideLibrary="com.github.nisrulz.sensey" to force usage (may lead to runtime failures) minSdk Restriction 64 @nisrulz

Slide 65

Slide 65 text

Manifest merger failed : uses-sdk:minSdkVersion 14 cannot be smaller than version 21 declared in library [:sensey] Suggestion: + Use a compatible library with a minSdk of at most 14 + Increase this project's minSdk version to at least 21 + Use tools:overrideLibrary="com.github.nisrulz.sensey" to force usage (may lead to runtime failures) minSdk Restriction 65 @nisrulz

Slide 66

Slide 66 text

... minSdk Restriction 66 @nisrulz

Slide 67

Slide 67 text

... minSdk Restriction 67 @nisrulz

Slide 68

Slide 68 text

Access Visibility vs Code Organization 68 @nisrulz

Slide 69

Slide 69 text

Visibility vs Organization 69 @nisrulz

Slide 70

Slide 70 text

Visibility vs Organization ● Code organized in individual packages; everything is public 70 @nisrulz

Slide 71

Slide 71 text

Visibility vs Organization ● Code organized inside one package; Classes and methods are package private and only public on demand 71 @nisrulz

Slide 72

Slide 72 text

Visibility vs Organization ● Code organized inside the module i.e individual packages Classes and methods are internal and only public on demand (in Kotlin land) 72 @nisrulz

Slide 73

Slide 73 text

Visibility vs Organization ● internal and only public on demand (in Kotlin land) 73 @nisrulz

Slide 74

Slide 74 text

Visibility vs Organization ● Code organized inside the module i.e individual packages Classes and methods are internal and only public on demand (in Kotlin land) ● Drawback ○ Need dependency on kotlin std library 74 @nisrulz

Slide 75

Slide 75 text

Lifecycle-Aware Android Library 75 @nisrulz

Slide 76

Slide 76 text

Lifecycle Components Classes designed to help deal with Android lifecycle ● Lifecycle ● LifecycleOwner ● LifecycleObserver 76 @nisrulz

Slide 77

Slide 77 text

Lifecycle Owner 77 @nisrulz

Slide 78

Slide 78 text

Lifecycle Owner + Lifecycle 78 @nisrulz

Slide 79

Slide 79 text

Lifecycle Owner + Lifecycle ● ● ● ● 79 @nisrulz

Slide 80

Slide 80 text

Lifecycle Owner + Lifecycle class MainActivity extends AppCompatActivity() {...} 80 @nisrulz

Slide 81

Slide 81 text

Lifecycle Owner + Lifecycle class MainActivity extends AppCompatActivity() {...} public class AppCompatActivity extends FragmentActivity{...} 81 @nisrulz

Slide 82

Slide 82 text

Lifecycle Owner + Lifecycle class MainActivity extends AppCompatActivity() {...} public class AppCompatActivity extends FragmentActivity{...} public class FragmentActivity extends SupportActivity {...} 82 @nisrulz

Slide 83

Slide 83 text

Lifecycle Owner + Lifecycle class MainActivity extends AppCompatActivity() {...} public class AppCompatActivity extends FragmentActivity{...} public class FragmentActivity extends SupportActivity {...} public class SupportActivity extends Activity implements LifecycleOwner, Component { ... public Lifecycle getLifecycle() {return this.mLifecycleRegistry();} ... } 83 @nisrulz

Slide 84

Slide 84 text

Lifecycle Owner + Lifecycle class MainActivity extends AppCompatActivity() {...} public class AppCompatActivity extends FragmentActivity{...} public class FragmentActivity extends SupportActivity {...} public class SupportActivity extends Activity implements LifecycleOwner, Component { ... public Lifecycle getLifecycle() {return this.mLifecycleRegistry();} ... } 84 @nisrulz

Slide 85

Slide 85 text

Lifecycle Observer 85 @nisrulz

Slide 86

Slide 86 text

Lifecycle Observer 86 @nisrulz

Slide 87

Slide 87 text

LifecycleObserver dependencies { def lifecycleVer = "2.0.0" // Runtime implementation "androidx.lifecycle:lifecycle-runtime:$lifecycleVer" // Annotation Support annotationProcessor "androidx.lifecycle:lifecycle-compiler:$lifecycleVer" ... } 87 @nisrulz

Slide 88

Slide 88 text

LifecycleObserver public class AwesomeLib implements LifecycleObserver { @OnLifecycleEvent(Lifecycle.Event.ON_CREATE) public void init() { ... } @OnLifecycleEvent(Lifecycle.Event.ON_START) public void libOnStart() { ... } ... @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) public void cleanup() { ... } } 88 @nisrulz

Slide 89

Slide 89 text

LifecycleOwner class MainActivity : AppCompatActivity() { val awesomeLib = AwesomeLib() override fun onStart() { ... // Add lifecycle observer lifecycle.addObserver(awesomeLib) } override fun onStop() { ... // Remove lifecycle observer lifecycle.removeObserver(awesomeLib) } } 89 @nisrulz

Slide 90

Slide 90 text

LifecycleAware Library 90 @nisrulz

Slide 91

Slide 91 text

ProcessLifecycleOwner Class that tracks the lifecycle of whole application process 91 @nisrulz

Slide 92

Slide 92 text

ProcessLifecycleOwner dependencies { // For ProcessLifecycleOwner implementation "androidx.lifecycle:lifecycle-extensions:2.0.0" ... } 92 @nisrulz

Slide 93

Slide 93 text

ProcessLifecycleOwner Does something weird… 93 @nisrulz

Slide 94

Slide 94 text

ProcessLifecycleOwner Does something weird… Adding lifecycle-extensions artifact > automatically adds element to the merged manifest 94 @nisrulz

Slide 95

Slide 95 text

ProcessLifecycleOwner 95 @nisrulz

Slide 96

Slide 96 text

ProcessLifecycleOwner ... 96 @nisrulz

Slide 97

Slide 97 text

ProcessLifecycleOwner ... 97 @nisrulz

Slide 98

Slide 98 text

ProcessLifecycleOwner ... 98 @nisrulz Pre-AndroidX

Slide 99

Slide 99 text

ProcessLifecycleOwner ... 99 @nisrulz Pre-AndroidX

Slide 100

Slide 100 text

ProcessLifecycleOwner 100 @nisrulz Pre-AndroidX

Slide 101

Slide 101 text

ProcessLifecycleOwner ... 101 @nisrulz AndroidX

Slide 102

Slide 102 text

ProcessLifecycleOwner ... 102 @nisrulz AndroidX

Slide 103

Slide 103 text

ProcessLifecycleOwner // Internal class to initialize Lifecycles. public class ProcessLifecycleOwnerInitializer extends ContentProvider { @Override public boolean onCreate() { ... ProcessLifecycleOwner.init(getContext()); return true; } ... } 103 @nisrulz

Slide 104

Slide 104 text

ProcessLifecycleOwner Why? To invoke ProcessLifecycleOwner as soon as process starts 104 @nisrulz

Slide 105

Slide 105 text

ProcessLifecycleOwner Why? To invoke ProcessLifecycleOwner as soon as process starts Drawback? Initializes ProcessLifecycleOwner even if your app does not use it! 105 @nisrulz

Slide 106

Slide 106 text

ProcessLifecycleOwner How to get rid of it in app? 106 @nisrulz

Slide 107

Slide 107 text

ProcessLifecycleOwner How to get rid of it in app? Use Merge rule marker in app’s AndroidManifest.xml: // Remove marked element from the merged manifest tools:node="remove" 107 @nisrulz

Slide 108

Slide 108 text

ProcessLifecycleOwner ... 108 @nisrulz App’s AndroidManifest.xml

Slide 109

Slide 109 text

ProcessLifecycleOwner ... 109 @nisrulz App’s AndroidManifest.xml

Slide 110

Slide 110 text

ProcessLifecycleOwner ... 110 @nisrulz App’s AndroidManifest.xml

Slide 111

Slide 111 text

ProcessLifecycleOwner ... 111 @nisrulz App’s AndroidManifest.xml

Slide 112

Slide 112 text

Auto Initialize Android Library 112 @nisrulz

Slide 113

Slide 113 text

AutoInit Android Library Android Libraries need Android context to handle simple tasks such as ● Hook into Android Runtime ● Access app resources ● Use System Services ● Register BroadcastReceiver 113 @nisrulz

Slide 114

Slide 114 text

AutoInit Android Library public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); // Init android library AwesomeLib.getInstance().init(this); } } 114 @nisrulz

Slide 115

Slide 115 text

AutoInit Android Library public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); // Init android library AwesomeLib.getInstance().init(this); } } 115 @nisrulz

Slide 116

Slide 116 text

AutoInit Android Library public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); // Init android library AwesomeLib.getInstance().init(this); } } 116 @nisrulz

Slide 117

Slide 117 text

AutoInit Android Library 117 @nisrulz

Slide 118

Slide 118 text

AutoInit Android Library 118 @nisrulz

Slide 119

Slide 119 text

AutoInit Android Library ContentProvider can be used to simplify the process. 119 @nisrulz

Slide 120

Slide 120 text

AutoInit Android Library ContentProvider can be used to simplify the process. Simply because ContentProvider ● Is created and initialized (on the main thread) before all other components ● Participate in manifest merging at build time. 120 @nisrulz

Slide 121

Slide 121 text

AutoInit Android Library public class AwesomeLibInitProvider extends ContentProvider { ... @Override public boolean onCreate() { // get the context (Application context) Context context = getContext(); // initialize AwesomeLib here AwesomeLib.getInstance().init(context); return false; } ... } 121 @nisrulz

Slide 122

Slide 122 text

AutoInit Android Library public class AwesomeLibInitProvider extends ContentProvider { ... @Override public boolean onCreate() { // get the context (Application context) Context context = getContext(); // initialize AwesomeLib here AwesomeLib.getInstance().init(context); return false; } ... } 122 @nisrulz

Slide 123

Slide 123 text

AutoInit Android Library 123 @nisrulz

Slide 124

Slide 124 text

AutoInit Android Library 124 @nisrulz

Slide 125

Slide 125 text

AutoInit Android Library 125 @nisrulz

Slide 126

Slide 126 text

AutoInit Android Library 126 @nisrulz

Slide 127

Slide 127 text

AutoInit Android Library ContentProvider can be used to simplify the process. 127 @nisrulz

Slide 128

Slide 128 text

AutoInit Android Library ContentProvider can be used to simplify the process. Challenges: ● There can be only one Content Provider with a given “authority” string ● Only run on main thread 128 @nisrulz

Slide 129

Slide 129 text

AutoInit Android Library ContentProvider can be used to simplify the process. 129 @nisrulz

Slide 130

Slide 130 text

AutoInit Android Library ContentProvider can be used to simplify the process. Why this is a bad idea: ● Increases startup time ● Bloats applications even when not used ● Abusing functionality of ContentProvider 130 @nisrulz

Slide 131

Slide 131 text

AutoInit Android Library ContentProvider can be used to simplify the process. Why this is a bad idea: ● Increases startup time (Solution: async initialize) ● Bloats applications even when not used ● Abusing functionality of ContentProvider 131 @nisrulz

Slide 132

Slide 132 text

AutoInit Android Library Some android libraries that use this... 132 @nisrulz

Slide 133

Slide 133 text

AutoInit Android Library ProcessLifecycleOwner [androidx.lifecycle:lifecycle-extensions:2.0.0] 133 @nisrulz

Slide 134

Slide 134 text

AutoInit Android Library Firebase [com.google.firebase:firebase-common:16.0.5] 134 @nisrulz

Slide 135

Slide 135 text

AutoInit Android Library Facebook-Core [com.facebook.android:facebook-core:4.34.0] 135 @nisrulz

Slide 136

Slide 136 text

AutoInit Android Library Facebook-Marketing [com.facebook.android:facebook-marketing:4.34.0] 136 @nisrulz

Slide 137

Slide 137 text

AutoInit Android Library Crashlytics [com.crashlytics.sdk.android:crashlytics:2.9.5] 137 @nisrulz

Slide 138

Slide 138 text

AutoInit Android Library Picasso // Pre - v2.71828 Picasso.with(this).load("......").into(imageView); // After - v2.71828 Picasso.get().load("......").into(imageView); 138 @nisrulz

Slide 139

Slide 139 text

AutoInit Android Library Picasso // Pre - v2.71828 Picasso.with(this).load("......").into(imageView); // After - v2.71828 Picasso.get().load("......").into(imageView); 139 @nisrulz

Slide 140

Slide 140 text

AutoInit Android Library Picasso [com.squareup.picasso:picasso:2.71828] 140 @nisrulz

Slide 141

Slide 141 text

Links/References Android Libraries I have built: https://github.com/nisrulz/nisrulz.github.io#open-source-co ntributions Auto initialize android library example: https://github.com/nisrulz/android-examples/tree/develop/Au toInitLibrary Lifecycle Aware android library example: https://github.com/nisrulz/android-examples/tree/develop/Li feCycleCompForLib 141 @nisrulz

Slide 142

Slide 142 text

142 twitter.com/nisrulz github.com/nisrulz www.nisrulz.com

Slide 143

Slide 143 text

twitter.com/nisrulz github.com/nisrulz www.nisrulz.com 143