Getting Started with Android N



Getting Started with Android N

0 0


gdg-n-preview

Presentation about the new features in the Android N Developer Preview

On Github Mauin / gdg-n-preview

Getting Started with Android N

5 things that will change, break and help your app

Marvin Ramin

Chapter 0:

The basics

UI changes Development stack changes Behavior changes
Why are we talking about this? Dev Preview 1 was released a month ago.
Preview 4 will allow you to publish Apps to the Play Store that target N

Setup time!

The tools you need will need:

  • Android Studio 2.1
  • Android N Preview SDK
  • API Documentation
  • JDK 8
  • build.gradle
buildscript {
    dependencies {
        classpath 'com.android.tools.build:gradle:2.1.0-<some alpha/beta version here>'
    }
}

android {
    compileSdkVersion 'android-N'
    buildToolsVersion "24.0.0 rc1"

    defaultConfig {
        minSdkVersion 'N'
        targetSdkVersion 'N'
    }
}
Android Gradle Plugin update Compile Sdk Build Tools API version is just N for now

Prepare your device

Works with all Nexus deivces > Nexus 6

RIP Nexus 5

It's really quick! Click the button and get the notification that a new OS version is available.

Chapter 1:

The UI changes

Notifications

Notifications in N, in fact the whole status bar shade was updated.

Quick Reply Notifications

  • RemoteInput API
  • Same as Android Wear
If you have a wear app with reply functionality - done!

Quick Reply Notifications

RemoteInput remoteInput = new RemoteInput.Builder(RESULT_KEY_TEXT_REPLY)
        .setLabel("Reply")
        .build();

PendingIntent pendingIntent =
	PendingIntent.getActivity(context, 0, new Intent(context, MainActivity.class), 0);

NotificationCompat.Action action =
        new NotificationCompat.Action.Builder(R.mipmap.ic_launcher, "Reply", pendingIntent)
                .addRemoteInput(remoteInput)
                .build();

NotificationCompat.Builder builder = baseNotification(context, "Quick reply", "You can reply to this...")
        .addAction(action);

Quick Reply Notifications

RemoteInput remoteInput = new RemoteInput.Builder(RESULT_KEY_TEXT_REPLY)
        .setLabel("Reply")
        .build();

PendingIntent pendingIntent =
	PendingIntent.getActivity(context, 0, new Intent(context, MainActivity.class), 0);

NotificationCompat.Action action =
        new NotificationCompat.Action.Builder(R.mipmap.ic_launcher, "Reply", pendingIntent)
                .addRemoteInput(remoteInput)
                .build();

NotificationCompat.Builder builder = baseNotification(context, "Quick reply", "Title")
        .addAction(action);

Quick Reply Notifications

RemoteInput remoteInput = new RemoteInput.Builder(RESULT_KEY_TEXT_REPLY)
        .setLabel("Reply")
        .build();

PendingIntent pendingIntent =
	PendingIntent.getActivity(context, 0, new Intent(context, MainActivity.class), 0);

NotificationCompat.Action action =
        new NotificationCompat.Action.Builder(R.mipmap.ic_launcher, "Reply", pendingIntent)
                .addRemoteInput(remoteInput)
                .build();

NotificationCompat.Builder builder = baseNotification(context, "Quick reply", "Title")
        .addAction(action);

Quick Reply Notifications

RemoteInput remoteInput = new RemoteInput.Builder(RESULT_KEY_TEXT_REPLY)
	.setLabel("Reply")
	.build();

PendingIntent pendingIntent =
	PendingIntent.getActivity(context, 0, new Intent(context, MainActivity.class), 0);

NotificationCompat.Action action =
        new NotificationCompat.Action.Builder(R.mipmap.ic_launcher, "Reply", pendingIntent)
                .addRemoteInput(remoteInput)
                .build();

NotificationCompat.Builder builder = baseNotification(context, "Quick reply", "Title")
	.addAction(action);

Quick Reply Notifications

RemoteInput remoteInput = new RemoteInput.Builder(RESULT_KEY_TEXT_REPLY)
        .setLabel("Reply")
        .build();

PendingIntent pendingIntent =
	PendingIntent.getActivity(context, 0, new Intent(context, MainActivity.class), 0);

NotificationCompat.Action action =
        new NotificationCompat.Action.Builder(R.mipmap.ic_launcher, "Reply", pendingIntent)
                .addRemoteInput(remoteInput)
                .build();

NotificationCompat.Builder builder = baseNotification(context, "Quick reply", "Title")
        .addAction(action);
And then of course show the notification!

Handling the Remote Input

Bundle bundle = RemoteInput.getResultsFromIntent(getIntent());
if (bundle == null) {
	return;
}

String replyText = bundle.getString(RESULT_KEY_TEXT_REPLY);
// Do something with the reply text

// You have to remove the notification once you're finished processing it
NotificationManager.removeReplyNotification(this);
Read the intent

Handling the Remote Input

Bundle bundle = RemoteInput.getResultsFromIntent(getIntent());if (bundle == null) {
	return;
}

String replyText = bundle.getString(RESULT_KEY_TEXT_REPLY);
// Do something with the reply text

// You have to remove the notification once you're finished processing it
NotificationManager.removeReplyNotification(this);
And then of course show the notification!

Handling the Remote Input

Bundle bundle = RemoteInput.getResultsFromIntent(getIntent());
if (bundle == null) {
	return;
}

String replyText = bundle.getString(RESULT_KEY_TEXT_REPLY);// Do something with the reply text

// You have to remove the notification once you're finished processing it
NotificationManager.removeReplyNotification(this);
Read the intent

Grouping Notifications

.setGroup(ID)

Create summary notification

.setGroupSummary(true)

Also the same API as on Wear

Quick Settings

Quick Settings tiles are reserved for controls or actions that are either urgently required or frequently used, and should not be used as shortcuts to launching an app.

TileService

onTileAdded()

onTileRemoved()

onStartListening()

onStopListening()

onClick()

Add/Remove when user added it Start/Stop when it's visible to update Click on click

TileService

AndroidManifest.xml

<service
    android:name=".QuickSettingsTileService"
    android:label="N Playground"
    android:icon="@drawable/wave"
    android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
    <intent-filter>
        <action android:name="android.service.quicksettings.action.QS_TILE" />
    </intent-filter>
</service>

TileService

AndroidManifest.xml

<service
    android:name=".QuickSettingsTileService"
    android:label="N Playground"
    android:icon="@drawable/wave"
    android:permission="android.permission.BIND_QUICK_SETTINGS_TILE"><intent-filter>
        <action android:name="android.service.quicksettings.action.QS_TILE" />
    </intent-filter>
</service>

TileService

AndroidManifest.xml

<service
    android:name=".QuickSettingsTileService"
    android:label="N Playground"
    android:icon="@drawable/wave"
    android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
    <intent-filter>
        <action android:name="android.service.quicksettings.action.QS_TILE" /></intent-filter>
</service>

Shortcuts

Quick actions on Launcher icons

Can be added/removed dynamically

Accessed with "a gesture"

Possibly Force Touch?

Sounds like 3D Touch functionality

Shortcuts

Possible 3D Touch-like functionality

Chapter 2:

The multiple windows

Multi Window

Split-Screen mode

Picture in Picture

Freeform mode

Split screen demo on emulator

Picture in Picture

Picture in Picture

Freeform

You can drag and drop between "windows"! Going towards desktop OS

Multi Window

Be careful with orientation

Be careful with the lifecycle

Activity can still be visible in onPause()

Fixed orientation disables multi-window

Device might be in portrait orientation, but activity is in landscape

Multi Window

android:resizeableActivity=["true" | "false"]
android:supportsPictureInPicture=["true" | "false"]
<activity android:name=".MyActivity">
	<layout
			android:defaultHeight="500dp"
			android:defaultWidth="600dp"
			android:gravity="top|end"
			android:minimalHeight="450dp"
			android:minimalWidth="300dp" />
</activity>
resizable Activity defaults to true if you use a fixed orientation for your activity, it cannot be put into multi window mode

Multi Window

Intent.FLAG_ACTIVITY_LAUNCH_TO_ADJACENT

Drag and Drop

Helper methods and callbacks for mode changes

Chapter 3:

The developer toolchain

Java 8

Java 8 (kind of)

Java 8 Language Features with N

Lambdas

Default interface methods

Reflection APIs

java.util.function

java.util.stream

Java 8 Language Features below N

Lambdas

Default interface methods

Reflection APIs

java.util.function

java.util.stream

Jack & Jill

android {
  ...
  defaultConfig {
    ...
    jackOptions {
      enabled true
    }
  }
  compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
  }
}
To use Java8 features you need to use Jack and Jill, a new compiler toolchain It operates differently than javac, and outputs a .jack format

Jack & Jill

android {
  ...
  defaultConfig {
    ...
    jackOptions {
      enabled true
    }
  }
  compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
  }
}
Right now you need to enable jack, probably won't be the case in the future

Jack & Jill

android {
  ...
  defaultConfig {
    ...
    jackOptions {
      enabled true
    }
  }
  compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
  }
}

Jack & Jill

Slightly slower than javac (currently)

Breaks Annotation Processing (currently)

No Instant Run (currently)

Breaks Kotlin (currently)

source.android.com

Chapter 4:

The small changes

X509TrustManager

Network Security Configuration

Network Security Configuration

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
  <domain-config>
      <domain includeSubdomains="true">example.com</domain>
      <trust-anchors>
          <certificates src="@raw/my_ca"/>
      </trust-anchors>
  </domain-config>
</network-security-config>
Defined with param in the AndroidManifest.xml meta-data Also possible to just have this for debug builds if your test servers have custom certs

Data Saver

ConnectivityManager.isActiveNetworkMetered()

ConnectivityManager.getRestrictBackgroundStatus()

Tells you if user has enabled data saver or not App should make an effort to reduce data consumption

Changed behavior

file://

Doze

Multi-language support

android.test deprecation

android.permission.GET_ACCOUNTS deprecated

Stop using file:// URIs. --> FileUriExposedException Migrate to content: URIs with FileProvider Doze can now kick in at any time, might cause you trouble Secondary language might be shown, not your default. Make sure your translations are complete. All old AndroidTestCases are deprecated --> Testing support lib

Chapter 5:

The mysteries

AutomaticZenRule

android.os.Health

Zen? Lots more statistics about apps, it seems like awake time, cpu time, ect.

Honorable mentions

Vulkan

NDK API

Vulkan Graphics API NDK restrictions, only use the public APIs, please!

Reading material

Thank you!

   @Mauin
1 / 57
Getting Started with Android N 5 things that will change, break and help your app Marvin Ramin