1 of 71

Build Applications Faster with Android Jetpack

Gilang Ramadhan,

Academy Content Writer at Dicoding

2 of 71

Gilang Ramadhan �Academy Content Writer at Dicoding

3 of 71

4 of 71

What is Android Jetpack?

5 of 71

Jetpack?

Kiri, Kanan, L1, L2, R1, R2, Atas, Bawah, Kiri, Kanan

6 of 71

Android Jetpack

Jetpack is a collection of Android software components to make it easier for you to develop great Android apps.

7 of 71

Advantages

Accelerate development

Eliminate boilerplate code

Build high quality, robust apps

8 of 71

Android Jetpack Components

Foundation

Architecture

UI

Behavior

9 of 71

10 of 71

Foundation - AppCompat

Before After

com.android.support:cardview-v7 androidx.cardview:cardview:1.0.0

com.android.support:appcompat-v7 androidx.appcompat:appcompat:1.0.0

com.android.support:recyclerview-v7 androidx.recyclerview:recyclerview:1.0.0

android.arch.persistence.room:common androidx.room:room-common:2.0.0-rc01

android.arch.core:common androidx.arch.core:core-common:2.0.0-rc01

android.arch.core:core androidx.arch.core:core:2.0.0-rc01

android.arch.paging:common androidx.paging:paging-common:2.0.0-rc01

.... ....

Degrade gracefully on older versions of Android

11 of 71

Foundation - Android KTX

Getting Started

dependencies {

implementation 'androidx.core:core-ktx:1.0.0'

}

Before

sharedPreferences.edit()

.putBoolean("key", value)

.apply()

After

sharedPreferences.edit {

putBoolean("key", value)

}

Write more concise, idiomatic Kotlin code

12 of 71

Foundation - Multidex

Multidex Support prior to Android 5.0 (Api 21)

android {

defaultConfig {

...

minSdkVersion 15

targetSdkVersion 28

multiDexEnabled true

}

...

}

dependencies {

compile 'com.android.support:multidex:1.0.3'

}

Provide support for apps with multiple DEX files

Enable multidex for apps with over 64K methods

13 of 71

Foundation - Test

An Android testing framework for unit and runtime UI tests

14 of 71

Foundation - Test

An Android testing framework for unit and runtime UI tests

15 of 71

Foundation - Unit Test

Getting Started

dependencies {

// Required -- JUnit 4 framework

testImplementation 'junit:junit:4.12'

// Optional -- Robolectric environment

testImplementation 'androidx.test:core:1.0.0'

// Optional -- Mockito framework

testImplementation 'org.mockito:mockito-core:1.10.19'

}

16 of 71

Foundation - Instrumental Testing

Getting Started

dependencies {

androidTestImplementation 'androidx.test:runner:1.1.0'

androidTestImplementation 'androidx.test:rules:1.1.0'

// Optional -- Hamcrest library

androidTestImplementation 'org.hamcrest:hamcrest-library:1.3'

// Optional -- UI testing with Espresso

androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'

// Optional -- UI testing with UI Automator

androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0'

}

17 of 71

18 of 71

Architecture Component

19 of 71

Architecture - ViewModel

Manage UI-related data in a lifecycle-conscious way

20 of 71

Architecture - LiveData

Ensures your UI matches your data state

No memory leaks

No crashes due to stopped activities

No more manual lifecycle handling

Always up to date data

Proper configuration changes

Sharing resources

Notify views when underlying database changes

21 of 71

Architecture - LiveData

public class NameViewModel extends ViewModel {

// Create a LiveData with a String

private MutableLiveData<String> currentName;

public MutableLiveData<String> getCurrentName() {

if (currentName == null) {

currentName = new MutableLiveData<String>();

}

return currentName;

}

// Rest of the ViewModel...

}

Notify views when underlying database changes

22 of 71

public class NameActivity extends AppCompatActivity {

private NameViewModel model;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

// Other code to setup the activity...

// Get the ViewModel.

model = ViewModelProviders.of(this).get(NameViewModel.class);

// Create the observer which updates the UI.

final Observer<String> nameObserver = new Observer<String>() {

@Override

public void onChanged(@Nullable final String newName) {

// Update the UI, in this case, a TextView.

nameTextView.setText(newName);

}

};

// Observe the LiveData, passing in this activity as the LifecycleOwner and the observer.

model.getCurrentName().observe(this, nameObserver);

}

}

23 of 71

Architecture - Data Binding

Getting Started

android {

....

dataBinding {

enabled = true

}

}

Declaratively bind observable data to UI elements

Activity

TextView textView = findViewById(R.id.sample_text);

textView.setText(viewModel.getUserName());

Layout

<TextView

android:text="@{viewmodel.userName}" />

24 of 71

Architecture - Lifecycles

class MyLocationListener {

public MyLocationListener(Context context, Callback callback) {

// ...

}

void start() {

// connect to system location service

}

void stop() {

// disconnect from system location service

}

}

Manage your activity and fragment lifecycles

25 of 71

class MyActivity extends AppCompatActivity {

private MyLocationListener myLocationListener;

@Override

public void onCreate(...) {

myLocationListener = new MyLocationListener(this, (location) -> {

// update UI

});

}

@Override

public void onStart() {

super.onStart();

myLocationListener.start();

// manage other components that need to respond to the activity lifecycle

}

@Override

public void onStop() {

super.onStop();

myLocationListener.stop();

// manage other components that need to respond to the activity lifecycle

}

}

26 of 71

class MyActivity extends AppCompatActivity {

...

@Override

public void onStart() {

super.onStart();

Util.checkUserStatus(result -> {

// what if this callback is invoked AFTER activity is stopped?

if (result) {

myLocationListener.start();

}

});

}

...

}

27 of 71

Architecture - Lifecycles

Manage your activity and fragment lifecycles

28 of 71

Architecture - Lifecycles

public class MyObserver implements LifecycleObserver {

@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)

public void connectListener() {

...

}

@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)

public void disconnectListener() {

...

}

}

myLifecycleOwner.getLifecycle().addObserver(new MyObserver());

Manage your activity and fragment lifecycles

29 of 71

Architecture - Room

Fluent SQLite database access

30 of 71

Architecture - Room

Entity

@Entity

public class User {

@PrimaryKey

public int uid;

@ColumnInfo(name = "first_name")

public String firstName;

@ColumnInfo(name = "last_name")

public String lastName;

}

31 of 71

Architecture - Room

Dao

@Dao

public interface UserDao {

@Query("SELECT * FROM user")

List<User> getAll();

@Query("SELECT * FROM user WHERE uid IN (:userIds)")

List<User> loadAllByIds(int[] userIds);

@Query("SELECT * FROM user WHERE first_name LIKE :first AND " + "last_name LIKE :last LIMIT 1")

User findByName(String first, String last);

@Insert

void insertAll(User... users);

@Delete

void delete(User user);

}

32 of 71

Architecture - Room

Database

@Database(entities = {User.class}, version = 1)

public abstract class AppDatabase extends RoomDatabase {

public abstract UserDao userDao();

}

Create Database

AppDatabase db = Room.databaseBuilder(getApplicationContext(),

AppDatabase.class, "database-name").build();

33 of 71

Architecture - Paging

Gradually load information on demand from your data source

34 of 71

Architecture - Paging

PagedList

public class ConcertViewModel extends ViewModel {

private ConcertDao concertDao;

public final LiveData<PagedList<Concert>> concertList;

// Creates a PagedList object with 50 items per page.

public ConcertViewModel(ConcertDao concertDao) {

this.concertDao = concertDao;

concertList = new LivePagedListBuilder<>(

concertDao.concertsByDate(), 50).build();

}

}

Gradually load information on demand from your data source

35 of 71

Architecture - Paging

Data

@Dao

public interface ConcertDao {

// The Integer type parameter tells Room to use a

// PositionalDataSource object.

@Query("SELECT * FROM concerts ORDER BY date DESC")

DataSource.Factory<Integer, Concert> concertsByDate();

}

Gradually load information on demand from your data source

36 of 71

Architecture - Paging

UI

public class BookmarkPagedAdapter extends PagedListAdapter<DataModel, ViewHolder> {

...

}

Gradually load information on demand from your data source

37 of 71

Architecture - Navigation

  • Handling Fragment transactions
  • Handling Up and Back actions correctly by default
  • Providing standardized resources for animations and transitions
  • Treating deep linking as a first-class operation
  • Including Navigation UI patterns, such as navigation drawers and bottom navigation, with minimal additional work
  • Providing type safety when passing information while navigating
  • Visualizing and editing navigation graphs with Android Studio's Navigation Editor

Handle everything needed for in-app navigation

If you want to use the Navigation Architecture Component with Android Studio, you must use Android Studio 3.2 Canary 14 or higher.

38 of 71

Architecture - Navigation

Handle everything needed for in-app navigation

39 of 71

Architecture - WorkManager

Key features:

  • Backwards compatible up to API 14
    • Uses JobScheduler on devices with API 23+
    • Uses a combination of BroadcastReceiver + AlarmManager on devices with API 14-22
  • Add work constraints like network availability or charging status
  • Schedule asynchronous one-off or periodic tasks
  • Monitor and manage scheduled tasks
  • Chain tasks together
  • Guarantees task execution, even if the app or device restarts

Manage your Android background jobs

40 of 71

Architecture - WorkManager

public class UploadWorker extends Worker {

public UploadWorker(@NonNull Context context, @NonNull WorkerParameters params) {

super(context, params);

}

@Override

public Result doWork() {

// Do the work here--in this case, upload the images.

uploadImages()

// Indicate whether the task finished successfully with the Result

return Result.success()

}

}

Manage your Android background jobs

41 of 71

Architecture - WorkManager

OneTimeWorkRequest

OneTimeWorkRequest uploadWorkRequest = new OneTimeWorkRequest.Builder(UploadWorker.class).build()

PeriodicWorkRequest

Constraints constraints = new Constraints.Builder().setRequiresCharging(true).build();

PeriodicWorkRequest saveRequest = new PeriodicWorkRequest.Builder(SaveImageFileWorker.class, 1, TimeUnit.HOURS).setConstraints(constraints).build();

WorkManager.getInstance().enqueue(saveRequest);

Manage your Android background jobs

42 of 71

Architecture - WorkManager

WorkContinuation chain1 = WorkManager.getInstance()

.beginWith(workA)

.then(workB);

WorkContinuation chain2 = WorkManager.getInstance()

.beginWith(workC)

.then(workD);

WorkContinuation chain3 = WorkContinuation

.combine(Arrays.asList(chain1, chain2))

.then(workE);

chain3.enqueue();

Manage your Android background jobs

43 of 71

Behavior - Download Manager

class DownloadManager.Query

This class may be used to filter download manager queries.

class DownloadManager.Request

This class contains all the information necessary to request a new download.

Schedule and manage large downloads

44 of 71

Behavior - Media & Playback

A multimedia application that plays audio or video usually has two parts:

  • A player that takes digital media in and renders it as video and/or audio.
  • A UI with transport controls to run the player and optionally display the player's state.

Backwards compatible APIs for media playback and routing (including Google Cast)

45 of 71

Behavior - Media & Playback

A multimedia application that plays audio or video usually has two parts:

  • A player that takes digital media in and renders it as video and/or audio.
  • A UI with transport controls to run the player and optionally display the player's state.

Backwards compatible APIs for media playback and routing (including Google Cast)

46 of 71

Behavior - Media & Playback

Backwards compatible APIs for media playback and routing (including Google Cast)

47 of 71

Behavior - Media & Playback

Video apps versus audio apps

48 of 71

Behavior - Notifications

Status bar and notification drawer Heads-up notification

Provides a backwards-compatible notification API with support for Wear and Auto

49 of 71

Behavior - Notifications

Lock screen App icon badge Wear OS devices

Provides a backwards-compatible notification API with support for Wear and Auto

50 of 71

Behavior - Notifications

  1. Small icon: This is required and set with setSmallIcon().
  2. App name: This is provided by the system.
  3. Time stamp: This is provided by the system but you can override with setWhen() or hide it with setShowWhen(false).
  4. Large icon: This is optional (usually used only for contact photos; do not use it for your app icon) and set withsetLargeIcon().
  5. Title: This is optional and set with setContentTitle().
  6. Text: This is optional and set with setContentText().

Provides a backwards-compatible notification API with support for Wear and Auto

51 of 71

Behavior - Permissions

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

package="com.example.snazzyapp">

<uses-permission android:name="android.permission.SEND_SMS"/>

<application ...>

...

</application>

</manifest>

Compatibility APIs for checking and requesting app permissions

52 of 71

Behavior - Preferences

<androidx.preference.PreferenceScreen

xmlns:app="http://schemas.android.com/apk/res-auto">

<SwitchPreferenceCompat

app:key="notifications"

app:title="Enable message notifications"/>

<Preference

app:key="feedback"

app:title="Send feedback"

app:summary="Report technical issues or suggest new features"/>

</androidx.preference.PreferenceScreen>

Create interactive settings screens

53 of 71

Behavior - Sharing

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

<item

android:id="@+id/menu_item_share"

android:showAsAction="ifRoom"

android:title="Share"

android:actionProviderClass=

"android.widget.ShareActionProvider" />

...

</menu>

Provides a share action suitable for an app’s action bar

54 of 71

private ShareActionProvider shareActionProvider;

...

@Override

public boolean onCreateOptionsMenu(Menu menu) {

// Inflate menu resource file.

getMenuInflater().inflate(R.menu.share_menu, menu);

// Locate MenuItem with ShareActionProvider

MenuItem item = menu.findItem(R.id.menu_item_share);

// Fetch and store ShareActionProvider

shareActionProvider = (ShareActionProvider) item.getActionProvider();

// Return true to display menu

return true;

}

// Call to update the share intent

private void setShareIntent(Intent shareIntent) {

if (shareActionProvider != null) {

shareActionProvider.setShareIntent(shareIntent);

}

}

55 of 71

Behavior - Slices

Android’s new approach to remote content :

  • Templated
  • Interactive
  • Updatable
  • Backwards-compatible

Create flexible UI elements that can display app data outside the app

dependencies {

// ...

implementation "androidx.slice:slice-builders:(latest version)"

// ...

}

56 of 71

Behavior - Slices

Dynamic and interactive content Enables rich and flexible layout

Templated

57 of 71

Behavior - Slices

Enhance predictions with rich app content

Accelerate navigation, task completion and discovery of app content.

App names

eg. [maps], [lyft], [airbnb]

General trems

eg. [get a ride], [trending videos]

Launching in search

58 of 71

Behavior - Slices

Example Use Case

59 of 71

Behavior - Slices

adb install -r -t slice-viewer.apk

Enter slice-<your slice URI> in the URL field

Example: slice-content://com.example.your.sliceuri

Example Use Case

60 of 71

Behavior - Slices

Slice Structure

61 of 71

UI - Animations & Transitions

Move widgets and transition between screens

62 of 71

UI - Emoji

Enable an up-to-date emoji font on older platforms

63 of 71

UI - Emoji

How does EmojiCompat work?

dependencies {

...

implementation "androidx.emoji:emoji:1.0.0"

}

64 of 71

UI - Fragment

A basic unit of composable UI

65 of 71

UI - Layout

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

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

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical" >

<TextView android:id="@+id/text"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="Hello, I am a TextView" />

<Button android:id="@+id/button"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="Hello, I am a Button" />

</LinearLayout>

Lay out widgets using different algorithms

66 of 71

UI - Palette

dependencies {

...

implementation 'androidx.palette:palette:1.0.0'

}

Pull useful information out of color palettes

67 of 71

UI - Auto

Components to help develop apps for Android Auto

68 of 71

UI - TV

Components to help develop apps for Android TV

69 of 71

UI - Wear OS by Google

Components to help develop apps for Wear

70 of 71

What’s Next?

Create useful applications!

https://developer.android.com/jetpack

71 of 71

Thank you

Gilang Ramadhan

+6281904996393

gilang@dicoding.com