How to build Sdk? Best practices

Preview:

Citation preview

SDK best practices

Rebecca Hamelsdorf13/9/2017

Hi!!

What is SDK

What is SDK?

what is SDK?

• SDK is a software development kit

• It’s a programing package that helps developers

to builds application for a specific platform.

• Typically it includes one or more API

Why?

Why do we need to develop an SDK?

Business need

Why do we need to develop an SDK?

But not for business reasons..

Why do we need to develop an SDK?

Business need

Internal use

Internal use..

Code reuse

Abstraction/black box

Why do we care about code reuse

● Saves time & money

Why do we care about code reuse

● Saves time & money

● Easier to maintain and change

Why do we care about code reuse

● Saves time & money

● Easier to maintain and change

● Solving bugs in a single place instead of bugs

all over the place

Developing SDK check list

1. Define the service for your SDK users

2. Plan your public API

3. Plan your internal code architecture

4. Code:)

5. Sample app + docs

6. Packaging

7. Ship!

Developing SDK check list

❏ Define the service for your SDK users

❏ Plan your public API

❏ Plan your internal code architecture

❏ Code:)

❏ Sample app + docs

❏ Packaging

❏ Ship!

Developing SDK check list

1. Define the service for your SDK users

2. Plan your public API

3. Plan your internal code architecture

4. Code:)

5. Sample app + docs

6. Packaging

7. Ship!

Plan your public API…

Public API is the contract between the app developer and

SDK developer.

you’re officially an API designer!

Plan your public API…

Put in your mind that the developer that integrate your sdk is

not sitting next to you..

Plan your public API…

Keep it:

Easy to learn- design for “stupid” developers

Plan your public API…

Keep it:

Easy to learn

Easy to use (even without docs!!), easy to integrate.

Someone did it really easy..

Plan your public API…

Keep it:

Easy to learn

Easy to use (even without docs!!), easy to integrate.

Hard to misused!

Plan your public API…

Keep it:

Easy to learn

Easy to use (even without docs!!), easy to integrate.

Hard to misused!

Custom exceptions

Custom Exception

class ServerURLException extends RuntimeException {

public ServerURLException(String message) {

super(message);

}

}

Custom Exception

class ServerURLException extends RuntimeException {

public ServerURLException(String message) {

super(message);

}

}

static void isUrlValid(String serverURL) {

if( isNullOrEmpty(serverURL) || !isValidUrl(serverURL))

{

throw new ServerURLException(“Server URL is invalid or empty");

}

}

Plan your public API…

Keep it:

Easy to learn

Easy to use (even without docs!!), easy to integrate.

Hard to misused!

Custom exceptions

No confusing constructors - use builder pattern, static

factory pattern etc.

Builder pattern

public class User {

private final String firstName; //required

private final String lastName; //required

private final int age; //optional

private final String phone; //optional

private final String address; //optional

...

}

Builder pattern

public User(String firstName, String lastName) {this(firstName, lastName, 0);}

public User(String firstName, String lastName, int age) {this(firstName, lastName, age, "");}

public User(String firstName, String lastName, int age, String phone) {

this(firstName, lastName, age, phone, "");}

public User(String firstName, String lastName, int age, String phone, String address) {

this.firstName = firstName;

this.lastName = lastName;

this.age = age;

this.phone = phone;

this.address = address;

}

Builder pattern

public class User {

private final String firstName; // required

private final String lastName; // required

private final int age; // optional

private final String phone; // optional

private final String address; // optional

private User(UserBuilder builder) {

this.firstName = builder.firstName;

this.lastName = builder.lastName;

this.age = builder.age;

this.phone = builder.phone;

this.address = builder.address;

}

public String getFirstName() {

return firstName;}

public String getLastName() {

return lastName;}

public int getAge() {

return age;}

public String getPhone() {

return phone; }

public String getAddress() {

return address; }

Builder pattern

public class User {

private final String firstName; // required

private final String lastName; // required

private final int age; // optional

private final String phone; // optional

private final String address; // optional

private User(UserBuilder builder) {

this.firstName = builder.firstName;

this.lastName = builder.lastName;

this.age = builder.age;

this.phone = builder.phone;

this.address = builder.address;

}

public String getFirstName() {

return firstName;}

public String getLastName() {

return lastName;}

public int getAge() {

return age;}

public String getPhone() {

return phone; }

public String getAddress() {

return address; }

Builder pattern

public static class UserBuilder {

private final String firstName;

private final String lastName;

private int age;

private String phone;

private String address;

public UserBuilder(String firstName,

String lastName) {

this.firstName = firstName;

this.lastName = lastName;

}

public UserBuilder age(int age) {

this.age = age;

return this;}

public UserBuilder phone(String phone) {

this.phone = phone;

return this;}

public UserBuilder address(String address) {

this.address = address;

return this; }

public User build() {

return new User(this);

}}}

Builder pattern

User.UserBuilder("Jhon", "Doe")

.age(30)

.phone("1234567")

.address("Fake address 1234")

.build();

Plan your public API…

● Keep it:

Easy to learn

Easy to use (even without docs!!), easy to integrate.

Hard to misused!

Custom exceptions

No confusing constructors - use builder pattern, static

factory pattern etc.

Use enums, public static variables when you can.

Plan your public API…

● We don’t choose the min sdk!

we want maximum compatibility

Plan your public API…

● We don’t choose the min sdk!

we want maximum compatibility

● Try to use minimum permissions - it’s hard for the developer

to explain to THEIR users the need for permissions.

Merged Manifest

<?xml version="1.0" encoding="utf-8"?>

<manifest

xmlns:android="http://schemas.android.com/apk/res/android"

package="com.academy.myapp">

<application

android:allowBackup="true"

android:icon="@mipmap/ic_launcher"

android:label="@string/app_name"

android:roundIcon="@mipmap/ic_launcher_round"

android:supportsRtl="true"

android:theme="@style/AppTheme">

<activity android:name=".MainActivity">

<intent-filter>

<action android:name="android.intent.action.MAIN" />

<category

android:name="android.intent.category.LAUNCHER" />

</intent-filter>

</activity>

</application>

</manifest>

Merged Manifest

https://developer.android.com/studio/build/manifest-merge.html

Plan your public API…

● We don’t choose the min sdk!

we want maximum compatibility

● Try to use minimum permissions - it’s hard for the developer

to explain to THEIR users the need for permissions.

● Think carefully - we REALLY don’t want to change it very

often (if at all!) *adding is OK

Developing SDK check list

❏ Define the service for your SDK users

❏ Plan your public API

❏ Plan your internal code architecture

❏ Code:)

❏ Sample app + docs

❏ Packaging

❏ Ship!

Developing SDK check list

1. Define the service for your SDK users

2. Plan your public API

3. Plan your internal code architecture

4. Code:)

5. Sample app + docs

6. Packaging

7. Ship!

Plan your internal code architecture

● Exception handling - the more the merrier :)

Plan your internal code architecture

● Exception handling - the more the merrier :)

● Use the minimum needed third-party libraries

a. we want to keep our SDK light

b. we avoid depending on others

Plan your internal code architecture

● Exception handling - the more the merrier :)

● Use the minimum needed third-party libraries

a. we want to keep our SDK light

b. we avoid depending on others

● Handle missing permission cases, you are not promised

to have them

Plan your internal code architecture

● Be very mindful to data consumption and battery usage!

Plan your internal code architecture

● Be very mindful to data consumption and battery usage!

● Remember your support phase during development:

○ Deprecate - don’t kill!

○ Write logs but don’t spam, use 2 log levels (debug/production)

Developing SDK check list

❏ Define the service for your SDK users

❏ Plan your public API

❏ Plan your internal code architecture

❏ Code:)

❏ Sample app + docs

❏ Packaging

❏ Ship!

Developing SDK check list

1. Define the service for your SDK users

2. Plan your public API

3. Plan your internal code architecture

4. Code:)

5. Sample app + docs

6. Packaging

7. Ship!

Code..

● Remember resource are public by default - hide what

you need hidden.

public.xml

<resources><public name="mylib_app_name" type="string"/><public name="mylib_public_string" type="string"/>

</resources>

Code..

● Add unique prefix to resources - the developers may

have their own resources that can conflict with yours!

Code..

● Add unique prefix to resources - the developers may

have their own resources that can conflict with yours!

● Test it on different Kind of apps..

Code..

● Add unique prefix to resources - the developers may

have their own resources that can conflict with yours!

● Test it on different Kind of apps..

● you must take the life cycle of the app in consideration!

Developing SDK check list

❏ Define the service for your SDK users

❏ Plan your public API

❏ Plan your internal code architecture

❏ Code:)

❏ Sample app + docs

❏ Packaging

❏ Ship!

Developing SDK check list

1. Define the service for your SDK users

2. Plan your public API

3. Plan your internal code architecture

4. Code:)

5. Sample app + docs

6. Packaging

7. Ship!

Sample app +docs

Provide 2 kinds of docs:

Simple integration instructions + sample app

Api Overview

Sample app +docs

● Provide 2 kinds of docs:

Simple integration instructions + sample app

Api Overview

• Remember Proguard docs

proguard.config

-keep class javax.** { *; } -keep class org.** { *; } -keep class twitter4j.** { *; }

Developing SDK check list

❏ Define the service for your SDK users

❏ Plan your public API

❏ Plan your internal code architecture

❏ Code:)

❏ Sample app + docs

❏ Packaging

❏ Ship!

Developing SDK check list

1. Define the service for your SDK users

2. Plan your public API

3. Plan your internal code architecture

4. Code:)

5. Sample app + docs

6. Packaging

7. Ship!

Packaging

Once we had a jar..

What can we do?

We have AAR!

What does aar contain?

The file extension for an AAR file is .aar, actually the file itself is

a zip file containing the following mandatory entries:

/AndroidManifest.xml

/classes.jar

/res/

/R.txt

/public.txt

There are also optional entries :

/assets/

/libs/name.jar

/proguard.txt

/lint.jar

Migrate from AAR to JAR ..

The file extension for an AAR file is .aar, actually the file itself is

a zip file containing the following mandatory entries:

/AndroidManifest.xml

/classes.jar

/res/

/R.txt

/public.txt

step by step..

https://developer.android.com/studio/projects/android-library.html

Developing SDK check list

❏ Define the service for your SDK users

❏ Plan your public API

❏ Plan your internal code architecture

❏ Code:)

❏ Sample app + docs

❏ Packaging

❏ Ship!

Developing SDK check list

❏ Define the service for your SDK users

❏ Plan your public API

❏ Plan your internal code architecture

❏ Code:)

❏ Sample app + docs

❏ Packaging

❏ Ship!

Battery Historian

• Battery Historian is a tool to analyze battery consumers

and events(DOZE mode).

Battery Historian

• Battery Historian is a tool to analyze battery consumers

and events(DOZE mode).

• It uses Android "bugreport" files

Battery Historian

• Battery Historian is a tool to analyze battery consumers

and events(DOZE mode).

• It uses Android "bugreport" files

• Supports Lollipop (API level 21) and later.

Battery Historian

• Battery Historian is a tool to analyze battery consumers

and events(DOZE mode).

• It uses Android "bugreport" files

• Supports Lollipop (API level 21) and later.

• Shows you where and how processes are drawing current

from the battery.

Battery Historian

• https://developer.android.com/studio/profile/battery-historian.html

• https://github.com/google/battery-historian

Stetho

• Stetho is a very powerful tool for debugging.

• It enables developers have access to the Chrome

Developer Tools feature

http://facebook.github.io/stetho/

Stetho

Questions?

Recommended