Android Crash Course Lunch and Learn

62
Android Crash Course Paul Irwin feature[23]

Transcript of Android Crash Course Lunch and Learn

Page 1: Android Crash Course Lunch and Learn

Android Crash CoursePaul Irwin

feature[23]

Page 2: Android Crash Course Lunch and Learn

Prerequisites• Android Studio• Includes Android SDK Manager needed below

• Emulator image or device• Emulator: (from Android SDK Manager)

• Install Android 6.0 Intel x86 Atom System Image• Install Intel x86 Emulator Accelerator

• Device:• From Android SDK Manager: install Google USB Driver• On device: go to Settings, About, tap on Build Number 7 times• Plug in device, approve connection to PC on device

• Recommended reading: Android Programming by Big Nerd Ranch

Page 3: Android Crash Course Lunch and Learn

Android Version History – The Dark Ages

Version(s) API Level(s)

Year(s) SDK Notes / New Features

1.0-1.1 1-2 2008-2009

First releases, Android Market

1.5 “Cupcake” 3 2009 3rd party keyboards, Widgets1.6 “Donut” 4 2009 Speech engine2.0-2.1 “Éclair” 5-7 2009 HTML5, Bluetooth API, Multi-touch SDK2.2 “Froyo” 8 2010 Performance, JIT, V8 engine, push

notifications, Hi-DPI2.3 “Gingerbread”

9-10 2010-2011

New UI, WXGA, VoIP, NFC, multiple cameras, concurrent GC, more sensors supported

3.0-3.2 “Honeycomb”

11-13 2011 Holo UI, tablets only, System bar, Action bar, two-pane UI, multi-core processors, external keyboards/mice

Page 4: Android Crash Course Lunch and Learn

Android Version History – Modern Age

Version(s) API Level(s)

Year(s) SDK Notes / New Features

4.0 “Ice Cream Sandwich”

14-15 2011 Brings 3.x features to phones, speech to text

4.1-4.3 “Jelly Bean” 16-18 2012-2013

“Project Butter”, expandable notifications, 7” tablet UI, geofencing, native emojis

4.4 “KitKat” 19 2013 Low RAM device support, cleaner Holo UI, immersive mode apps, WebView uses Chromium, Storage Access Framework, UI transition framework

4.4W “KitKat” 20 2013 Wearable extensions (smartwatches)5.0-5.1 “Lollipop” 21-22 2014-

2015Android Runtime (ART), 64-bit support, vector drawables, Material Design, WebView updated through Play Store

6.0 “Marshmallow” 23 2015 Data backup/restore for apps, in-app permission checks

Page 5: Android Crash Course Lunch and Learn

Why native?• First-class support from Google• Free!• Android Studio: Free IDE developed by Google and

JetBrains• Documentation and Stack Overflow• Use the latest APIs as soon as possible• 3rd party libraries• Compiler-guaranteed compatibility

Page 6: Android Crash Course Lunch and Learn

Why Java?• #1 programming language in the world (Jan 2016

TIOBE)• Documentation and Stack Overflow• Android Studio IDE support• Android itself is mainly Java – no impedance mismatch• … but yes Java has (many) shortcomings

Page 7: Android Crash Course Lunch and Learn

Android Studio• Free download: developer.android.com• Developed by JetBrains and Google, based on IntelliJ

IDEA• Supports IntelliJ plug-ins• Same powerful refactoring, analysis, etc.

• Replaces older, awful Eclipse Android Development Tools (ADT)• USB/emulator debugging with integrated adb support• Performance monitoring• (coming in 2.0) Live reload of activities

Page 8: Android Crash Course Lunch and Learn

Activities• Fundamental building block of Android apps• Java class that extends android.app.Activity• Like a Controller in MVC• App must have a main activity that starts by default• Usually has a layout (view)• Activities can start other activities• Other apps can start your activities too (if you want

them to)

Page 9: Android Crash Course Lunch and Learn

Layouts• Like the View in MVC• XML files representing view hierarchy, similar to

XAML/HTML• XML is “Inflated” into real Java objects• Views: “controls” that extend android.view.View• ViewGroup: a View that has children• Get a reference to a view with findViewById• XML namespace “android:” contains most attributes

i.e. <Button android:id=“@+id/btn” />

Page 10: Android Crash Course Lunch and Learn

Layout Sizing• android:layout_width and android:layout_height attributes• Can be explicit value, or:

• match_parent – fills to the parent ViewGroup’s width or height• wrap_content – will use minimum width or height to display content

inside it, but width will not exceed parent, wrapping text if necessary• Units typically are in dp (density-independent pixels)• Commonly multiples of 16dp or 8dp• Touch targets should be at least 48dp• Also: sp – scale-independent pixels for text

• android:layout_margin, android:layout_weight, android:layout_gravity

Page 11: Android Crash Course Lunch and Learn

DemoHello World

Page 12: Android Crash Course Lunch and Learn

Resources• All resources get an int identifier at build time• Layouts have IDs

• Used in Java as R.layout.activity_main• Used in other layouts as @layout/activity_main

• View IDs created with @+id/hello• Referenced by other views in layout with @id/hello – not common• Used in Java as R.id.hello

• res/values/strings.xml – default string values• Used in Java as R.string.hello• Used in layout XML as @string/hello

• Same goes for styles, colors, menus, drawables, etc.

Page 13: Android Crash Course Lunch and Learn

I18n• Alternate language strings.xml files• Add strings.xml to res/values-es or res/values-fr• res/values/strings.xml is default (i.e. English)

• Still referenced same way: @string/hello or R.string.hello• Locale at runtime determines resource to use• Can also be used for drawables:

res/drawable-es/myimg.png• And for layouts: res/layout-es/activity_main.xml

Page 14: Android Crash Course Lunch and Learn

Dialogs• Toast• Non-modal, doesn’t disrupt user• Dismisses itself

• AlertDialog• Modal• Can customize layout

• ProgressDialog• Loading indicator

• DatePickerDialog and TimePickerDialog

Page 15: Android Crash Course Lunch and Learn

Demo¡Hola, mundo!

Page 16: Android Crash Course Lunch and Learn

Java for C# Devs: KeywordsC# Keyword / Usage Java Keyword / Usagebool booleanstring <none> (use String type)namespace (block scoped) package (file scoped)using (a namespace or “static”) import (a package, class, or wildcard)base superMyClass : MyBaseClass, IMyInterface

MyClass extends MyBaseClass implements MyInterface

const (field) static finalreadonly finalsealed final<none> (variable used in lambda) final (variable used in anonymous inner class)is instanceoflock synchronizedforeach (Type item in collection) for (Type item : collection)typeof(MyClass) MyClass.class

Page 17: Android Crash Course Lunch and Learn

Java for C# Devs: Primitive Types• boolean, byte, char, double, float, int, long, short• Also: Boolean, Byte, Character, Double, Float, Integer, Long, Short• Primitives are not objects• Wrapper classes (Double) around primitives (double)

• C#: typeof(double) == typeof(Double)• Java: double.class != Double.class

• Wrapper classes are nullable• C#: Double x = null // compiler error• Java: Double x = null // okay!

• But: double x = null // compiler error• Wrapper classes are not value types

• .NET: struct System.Int32• Java: class java.lang.Integer

Page 18: Android Crash Course Lunch and Learn

Java for C# Devs: Exceptions/Try• Error vs Exception

• Both extend java.lang.Throwable• Checked exceptions

• public void foo() throws IOException { … }• public void bar1() { foo(); } // compiler error• public void bar2() { try { foo(); } catch (IOException e) { … } } // okay!• public void bar3() throws IOException { foo(); } // okay!

• Java 7: catch multiple exceptions• catch (IOException|SQLException ex)

• Java 7: try-with-resources• try (BufferedReader br = new BufferedReader(…)) { … } // no catch/finally• Android: minimum API level 19

Page 19: Android Crash Course Lunch and Learn

Java for C# Devs: EnumsGet ready for a major WTF!

Page 20: Android Crash Course Lunch and Learn

Java for C# Devs: Generics• Forget everything you know about generics in .NET• Type erasure• Type parameters not in bytecode (List<T> becomes List)• Type parameters not available via reflection

• Except for fields and method return types• public class MyClass<T> { private T value; }

• Compiles to: public class MyClass { private Object value; }• ArrayList x = new ArrayList<String>(); // okay, and is not an implicit

cast• Type parameters can’t be primitives• Always boxed (int becomes Integer)

• Type inference: ArrayList<T> x = new ArrayList<>();

Page 21: Android Crash Course Lunch and Learn

Java for C# Devs: Collection Types

.NET Type Java TypeIEnumerable, IEnumerable<T> Iterable<T>IEnumerator, IEnumerator<T> Iterator<T>IList, IList<T> List<E>List<T> ArrayList<E> implements List<E>IDictionary<TKey, TValue> Map<K, V>Dictionary<TKey, TValue> HashMap<K, V> implements Map<K, V>KeyValuePair<TKey, TValue> Map.Entry<K, V>ICollection<T> Collection<E>ISet<T> Set<E>HashSet<T> HashSet<E> implements Set<E>

Page 22: Android Crash Course Lunch and Learn

Java for C# Devs: Common Types

.NET Type Java Type(s)System.Guid java.util.UUIDSystem.DateTime java.util.DateSystem.IDisposable java.io.CloseableSystem.ISerializable java.io.SerializableSystem.IO.Stream java.io.InputStream, java.io.OutputStreamSystem.Type java.lang.Class<T>System.Uri java.net.URI, java.net.URL, android.net.UriSystem.Text.RegularExpressions.Regex

java.util.regex.Matcher, java.util.regex.Pattern

Page 23: Android Crash Course Lunch and Learn

Java for C# Devs: Inner Classes• Equivalent to nested types in C#• public class X { private int z; private class Y { … } }

• Y has access to z• Can reference z as X.this.z in case of conflict

• public class X { private int z; private static class Y { … } }• Y does not have access to z• Unlike C#, static class Y can be instantiated

• There’s also funky local classes…

Page 24: Android Crash Course Lunch and Learn

Java for C# Devs: Anonymous Classes• Used in Android as event handlers (i.e. button clicks)• Java 8’s lambdas not yet supported in Android

Notice: final keyword, MainActivity.this, and that View.OnClickListener is an interface

Page 25: Android Crash Course Lunch and Learn

Listeners• Usually an interface, set to an anonymous class• Listeners can have multiple methods, unlike C#

events• Don’t block the UI thread!• Convention: {view}.setOn{event}Listener• i.e. button.setOnClickListener,

listView.setOnItemSelectedListener• Corresponding interface: View.OnClickListener,

AdapterView.OnItemSelectedListener, etc.• Java convention: interfaces don’t start with I!

Page 26: Android Crash Course Lunch and Learn

DemoClick Handler

Page 27: Android Crash Course Lunch and Learn

Fragments• Introduced in Android 3.0 “Honeycomb” (API 11)

• Support library enables fragments back to API level 4• Enables two-pane tablet UIs

• i.e. list of emails on left, email body on right• “Responsive” approach

• Supports tablets and phones with same code• Attached to an Activity• Hosted in a View (usually FrameLayout)• Recommended to use from project start

• Even if only targeting phones at first• Makes it easier to support tablets later

Page 28: Android Crash Course Lunch and Learn

FragmentsEmailActivity

EmailListFragment

EmailActivity

EmailListFragment EmailMessageFragment

Phone UI Tablet UI

EmailMessageFragment

Page 29: Android Crash Course Lunch and Learn

Fragment ManagergetSupportFragmentManager() .beginTransaction() .replace(R.id.fragment_container, MyFragment.newInstance()) .commit();

getSupportFragmentManager() .findFragmentById(R.id.fragment_container);

Page 30: Android Crash Course Lunch and Learn

Fragment ViewsNeed to “inflate” view from XML:

@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_main, container, false); // … set up views and listeners here, i.e.: Button btn = (Button)view.findViewById(R.id.btn); btn.setText(“Hello!”); return view;}

Page 31: Android Crash Course Lunch and Learn

DemoFragments

Page 32: Android Crash Course Lunch and Learn

Menus• Action Bar

• Actions can show as icons (2)• Or only as text in the overflow (3)• Or as text in overflow if screen is

too small• Actions are menu items• res/menu/action_bar.xml

• R.menu.action_bar• Inflated like layouts into objects

• Override onCreateOptionsMenu• Override onOptionsItemSelected

to handle click http://developer.android.com/guide/topics/ui/menus.html

Page 33: Android Crash Course Lunch and Learn

DemoAction Bar

Page 34: Android Crash Course Lunch and Learn

Adapters• Repeating controls (i.e. ListView) need an Adapter• android.widget.Adapter interface• android.widget.BaseAdapter abstract class• Simplifies creating custom adapters• getCount(), getItem(position), getItemId(position), and

getView(position, convertView, parent)• OS will re-use views in adapters (convertView)• Improves performance

• android.widget.ArrayAdapter<T>• In case you have an array/list of simple types (i.e. Strings)

Page 35: Android Crash Course Lunch and Learn

DemoListView and Adapters

Page 36: Android Crash Course Lunch and Learn

Activity Lifecycle• Important to understand activity/fragment lifecycles• Common source of bugs and crashes• Activities are paused, stopped, and/or destroyed when:

• You rotate the screen (!!!)• You switch to other apps• You receive a phone call• Another app (i.e. Messenger) takes focus even if your app is visible• Your phone goes to sleep/lock• The OS needs to reclaim memory

• Depending on how and when the activity was paused/stopped/destroyed, it may be:• Created• Started/Restarted• And/or Resumed

Page 37: Android Crash Course Lunch and Learn

Activity Lifecycle

http://developer.android.com/training/basics/activity-lifecycle/starting.html

Page 38: Android Crash Course Lunch and Learn

Activity LifetimesLifetime First Call Final CallEntire Lifetime onCreate onDestroyVisible Lifetime onStart onStopForeground Lifetime onResume onPause

Page 39: Android Crash Course Lunch and Learn

Activity Lifecycle Common Patterns

Lifecycle Method Next Method Common UsageonCreate onStart Set up activity’s view, get view references

(findViewById), restore instance stateonStart onResume or

onStop(rare)

onRestart onStart (rare)onResume onPause Start any timers or CPU-consuming tasks,

refresh UI elements, play audio/videoonPause onResume or

onStopPause any timers or CPU-consuming tasks, pause audio/video

onStop onRestart or onDestroy

(rare) Clean up your activity

onDestroy nothing (rare) Clean up your activity* onSaveInstanceState

Save instance state (duh)

* onRestoreInstanceState

(rare) Restore instance state (duh)* Not part of previous diagram

Page 40: Android Crash Course Lunch and Learn

Bundles• Used for saved instance state, fragment arguments,

and intents• Like a Map<String, Object> with helper methods• void putInt(String key, int value) and int getInt(String key)• void putString(String key, String value) and String

getString(String key)• … etc.

@Overrideprotected void onSaveInstanceState(Bundle outState) { outState.putString(“Foo”, “Bar”);}

Page 41: Android Crash Course Lunch and Learn

DemoActivity Lifecycle and Instance State

Page 42: Android Crash Course Lunch and Learn

Fragment Lifecycle• “Sub activities” attached to Activities• Activity lifecycle events directly affect attached

fragments• When activity is paused or destroyed, so are all fragments

• “Back Stack” can affect fragments without leaving activity• You may need to save instance state here too• Fragments can be retained across Activity

destruction/creation• Can create “background” fragments without UIs, i.e. to play

audio• New methods: onCreateView, onAttach, onDetach,

onActivityCreated, onDestroyView

Page 43: Android Crash Course Lunch and Learn

Fragment Lifecycle

Page 44: Android Crash Course Lunch and Learn

Pattern: createInstancepublic class MyFragment extends Fragment {

public static MyFragment createInstance(int productId) {

MyFragment f = new MyFragment();

Bundle args = new Bundle();

args.putInt(EXTRA_PRODUCT_ID, productId);

f.setArguments(args);

return f;

}

}

Usage:

MyFragment f = MyFragment.createInstance(123);

getSupportFragmentManager().beginTransaction().replace(R.id.fragment, f).commit();

Page 45: Android Crash Course Lunch and Learn

Pattern: createInstancepublic class MyFragment extends Fragment { … @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Bundle args = getArguments(); if (savedInstanceState != null) { this.productId = savedInstanceState.getInt(EXTRA_PRODUCT_ID); } else if (args != null) { this.productId = args.getInt(EXTRA_PRODUCT_ID); } }}

Page 46: Android Crash Course Lunch and Learn

DemoFragment Lifecycle

Page 47: Android Crash Course Lunch and Learn

Intents• Used to start new activities

• Can be your activities• … or built in to Android (i.e. Intent.ACTION_SEND)• … or 3rd party (i.e. Facebook)

• Can include “extras” as parameters/arguments• Similar to Bundles: putExtra(String key, int value), etc.

• Flow:1. Create new Intent2. Set any extras/configuration3. Call startActivity(intent) or startActivityForResult(intent, code)4. (if awaiting result) Handle result in Activity.onActivityResult

Page 48: Android Crash Course Lunch and Learn

Built-in IntentsIntent Action (public static final String)

Example Usage

Intent.ACTION_VIEW Open URLIntent.ACTION_ATTACH_DATA Attach photo to a contactIntent.ACTION_EDIT Edit a calendar entryIntent.ACTION_PICK Pick a file from a directoryIntent.ACTION_DIAL Call a numberIntent.ACTION_SEND Share something (system share chooser)Intent.ACTION_SEARCH Perform a system searchIntent.ACTION_WEB_SEARCH Perform a web searchMediaStore.ACTION_IMAGE_CAPTURE Take a photo with the camera (default

app)MediaStore.ACTION_VIDEO_CAPTURE Record a video with the camera (default

app)

Page 49: Android Crash Course Lunch and Learn

Pattern: createIntentpublic class ProductDetailActivity extends Activity { public static final String EXTRA_PRODUCT_ID = “ProductDetail.ProductId"; public static Intent createIntent(Context context, int productId) { Intent intent = new Intent(context, MainActivity.class); intent.putExtra(EXTRA_PRODUCT_ID, productId); return intent; } …}

Usage: Intent intent = ProductDetailActivity.createIntent(123);startActivity(intent);

Page 50: Android Crash Course Lunch and Learn

Pattern: Using Intent Extraspublic class ProductDetailActivity extends Activity { … private int productId; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Intent intent = getIntent(); if (savedInstanceState != null) { this.productId = savedInstanceState.getInt(EXTRA_PRODUCT_ID); } else if (intent != null) { this.productId = intent.getIntExtra(EXTRA_PRODUCT_ID, 0); } … }}

Page 51: Android Crash Course Lunch and Learn

Handling Intent Resultsprivate static final int RC_CAMERA_CAPTURE = 100;…Intent i = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);Uri fileUri = getOutputMediaFileUri();i.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);startActivityForResult(i, RC_CAMERA_CAPTURE); …@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == RC_CAMERA_CAPTURE && resultCode == RESULT_OK) { // ... do something with data }}

Page 52: Android Crash Course Lunch and Learn

DemoIntents and Extras

Page 53: Android Crash Course Lunch and Learn

Manifest• XML file that defines:• App default package• App label and icon• Permissions needed• Activities and their labels

• Can specify which Activities available to other apps• Activity filters – must have MAIN and LAUNCHER activities• Broadcast receivers (i.e. push notifications)• (legacy) Things Gradle does for you now automatically:

• Unique app ID• SDK/API version(s)• Libraries to link against

Page 54: Android Crash Course Lunch and Learn

Minimal Manifest Example<manifest package="com.feature23.helloandroid" xmlns:android="http://schemas.android.com/apk/res/android"> <application android:icon="@mipmap/ic_launcher" android:label="@string/app_name" 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>

Page 55: Android Crash Course Lunch and Learn

Requiring Permissions<manifest …>

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

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

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

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

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

</manifest>

Page 56: Android Crash Course Lunch and Learn

Requesting Permissions• Changed in API 23 (6.0 “Marshmallow”)• Now you request specific permissions when you need

them• Call checkSelfPermission(String permission) to see if it

has already been granted• If not, call requestPermissions(String[] permissions, int

code)• Override onRequestPermissionsResult for callback

when user accepts or denies permissions

Page 57: Android Crash Course Lunch and Learn

Dangerous PermissionsPermission Group

Permissions

CALENDAR READ_CALENDAR, WRITE_CALENDARCAMERA CAMERACONTACTS READ_CONTACTS, WRITE_CONTACTS, GET_ACCOUNTSLOCATION ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATIONMICROPHONE RECORD_AUDIOPHONE READ_PHONE_STATE, CALL_PHONE, READ_CALL_LOG,

WRITE_CALL_LOG, ADD_VOICEMAIL, USE_SIP, PROCESS_OUTGOING_CALLS

SENSORS BODY_SENSORSSMS SEND_SMS, RECEIVE_SMS, READ_SMS, RECEIVE_WAP_PUSH,

RECEIVE_MMSSTORAGE READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE

Page 58: Android Crash Course Lunch and Learn

Gradle• Build system introduced with Android Studio• DSL based on Groovy, runs on JVM• Good IDE integration• Uses Maven dependency management• NuGet-like: pulls down dependencies from internet• No need to fumble with .jar files!• … but you can still include .jar files in the build if you want.

• Two build.gradle files:• One at project level, specifies repositories• One at app level, where most magic happens

Page 59: Android Crash Course Lunch and Learn

Gradle for AndroidDirective Example DescriptioncompileSdkVersion compileSdkVersion 23 Which API level this is compiled

againstbuildToolsVersion buildToolsVersion “21.1.2” Android Build Tools installed

versionapplicationId applicationId

“com.feature23.hello”The unique app ID, used by the OS

minSdkVersion minSdkVersion 19 App won’t run on devices below this

targetSdkVersion targetSdkVersion 23 Which API level this app is tested against

versionCode versionCode 2 Integer version code, must increment each release, no decimal places

versionName versionName “1.01” User-friendly version numbercompile compile

'com.google.code.gson:gson:2.4'

Add a Maven dependency

compile files('libs/coollection-0.2.0.jar')

Add a jar dependency

Page 60: Android Crash Course Lunch and Learn

Recommended Libraries• Gson: Google’s JSON Serializer• Maven: com.google.gson

• Retrofit: type-safe HTTP client• Maven: com.squareup.retrofit2

• Coollection: LINQ-like methods on arrays• Source/Jar: https://github.com/wagnerandrade/coollection

Page 61: Android Crash Course Lunch and Learn

DemoManifest and Gradle

Page 62: Android Crash Course Lunch and Learn

Pop Quiz1. From which class do all UI elements descend?2. If you wanted a TextView to grow in height as its text gets

longer, what value will you use for android:layout_height?3. Which class would you instantiate to start a new Activity?4. Which lifecycle method is called last when your app launches?5. Name the 4 abstract methods of the BaseAdapter class.6. In which resource folder do you define Action Bar items?7. In your build.gradle, to use the features in API level 23, which

would you set to 23: targetSdkVersion, minSdkVersion, or compileSdkVersion?