Notifications and Services
Total Page:16
File Type:pdf, Size:1020Kb
Notifications and Services Landon Cox March 28, 2017 Networking so far • Volley (retrieve quiz stored at URL) • User starts app • Check with server for new quiz • Say you’re building a messaging app … • How else might you use the network? • Are the workflows different than those we’ve seen? How do we keep device data fresh? Solution 1: polling • Basic idea • App periodically sends message to server • Asks, “is there anything new for me?” • Very simple to implement • Create a timer • When timer fires, exchange messages with server • What’s the problem? Impact of polling on battery • Network power • LTE: 600 – 1700 mW • WiFi: 77 – 130 mW • Assume radio stays in high-power state for 10 sec. • Energy per LTE poll: 1500 mW x 10 seconds = 15 Joules • 5 min frequency: 480 J/day • 30 sec. frequency: 4800 J/day • Total Pixel battery: ~40k Joules • You probably have more than one app that needs to sync • If you have a lot of apps, your radios will always be in a high-power state • Choosing the right period right is difficult • Check too often and drain the battery with useless messages • Check too infrequently and user experience will suffer http://dl.acm.org/citation.cfm?id=2307658 Every outgoing query will put the radio in a high- power state. Solution 2: push notifications • Share persistent network connection across apps • Device and server maintain (TCP) connection • Radio can enter low-power state when no updates • Server pushes updates to device • Device can push updates to server • Updates should be small (< 4KB) • On-device service routes updates to apps • Example: Firebase Cloud Messaging (FCM) Share one persistent connection. High-power only when data is ready. Firebase cloud messaging (FCM) • Formerly Google Cloud Messaging (GCM) • On your device • Google Play Services (global, maintains connection to cloud) • FirebaseInstanceIDService (per app, receives instance ID) • FirebaseMessageService (per app, receives notifications) • In the cloud • Firebase (routes messages to app server, devices) • App server (stores data, manages messaging) Firebase cloud messaging (FCM) • Formerly Google Cloud Messaging (GCM) • On your device • Google Play Services (global, maintains connection to cloud) • FirebaseInstanceIDService (per app, receives instance ID) • FirebaseMessageService (per app, receives data) • In the cloud • Firebase (routes messages to app server, devices) • App server (stores data, manages messaging) Next time Services • Service • Performs tasks on main thread: onStartCommand • Defined as an app component • Because it is a component, it is externally visible • Who schedules most work on threads? • Code already running inside our app Services • Service • Performs tasks on main thread: onStartCommand • Defined as an app component • Because it is a component, it is externally visible • Why might external visibility be useful? • Allows processes to communicate with each other Services • Service • Performs tasks on main thread: onStartCommand • Defined as an app component • Because it is a component, it is externally visible • Why are services essential for FCM? • Gives Google Play Services a place to send messages • Forward new data from Firebase to app’s Service Services • Service • Performs tasks on main thread: onStartCommand • Defined as an app component • Because it is a component, it is externally visible • Need to add Service to Android Manifest AndroidManifest.xml: <application … <service android:name=“.MyService” /> /> Services • Example Service • Create a subclass of Service • Use a worker thread to process IPC requests • Handle requests serially public class MyService extends Service { protected int onStartCommand(Intent intent) { // process IPC request } What } thread does this run on? Services • Example Service • Create a subclass of Service • Use a worker thread to process IPC requests • Handle requests serially public class MyService extends Service { protected int onStartCommand(Intent intent) { // process IPC request } } What is an Intent? Quick Intents review Displaying a web URL How does Android know which components could receive this Intent? Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(" http://www.google.com/images?q=duke ")); startActivity(browserIntent); Intent filters Restricts which actions the Activity will accept (Intent Action must match) <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> Intent filters <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> Describes categories of Intent Activity accepts (Intent categories must match all) Implementing MyService • We can do this! • Tools to use • Handler • Looper • HandlerThread • Useful to peak under the FCM hood Implementing MyService public class MyService extends Service { private Looper mLooper; What private ServiceHandler mHandler; needs to happen? protected void onCreate() { // on which thread does this code run? } protected int onStartCommand(Intent intent) { // on which thread does this code run? } private class ServiceHandler extends Handler { public ServiceHandler(Looper l) { super (l); } public void handleMessage(Message m) { … } } } https://developer.android.com/reference/android/app/Service.html Implementing MyService public class MyService extends Service { private Looper mLooper; private ServiceHandler mHandler; protected void onCreate() { HandlerThread thread = new HandlerThread(…); thread.start(); // Get the Looper and use it for our Handler mServiceLooper = thread.getLooper(); mServiceHandler = new ServiceHandler(mServiceLooper); // on which thread does this code run? } … private class ServiceHandler extends Handler { public ServiceHandler(Looper l) { super (l); } public void handleMessage(Message m) { … } } } Implementing MyService public class MyService extends Service { private Looper mLooper; private ServiceHandler mHandler; protected void onCreate() { // on which thread does this code run? } protected int onStartCommand(Intent intent) { // on which thread does this code run? What } needs to happen? private class ServiceHandler extends Handler { public ServiceHandler(Looper l) { super (l); } public void handleMessage(Message m) { … } } } Implementing MyService public class MyService extends Service { private Looper mLooper; private ServiceHandler mHandler; … protected int onStartCommand(Intent intent) { Toast.makeText(…).show(); // For each start request, forward the Intent Message msg = mServiceHandler.obtainMessage(); msg.arg1 = intent; mServiceHandler.sendMessage(msg); return 0; // on which thread does this code run? } … } Implementing MyService public class MyService extends Service { private Looper mLooper; Lucky for you, you private ServiceHandler mHandler; can just subclass Firebase Services! protected void onCreate() { // on which thread does this code run? } protected int onStartCommand(Intent intent) { // on which thread does this code run? } private class ServiceHandler extends Handler { public ServiceHandler(Looper l) { super (l); } public void handleMessage(Message m) { … } } } Firebase services • FirebaseInstanceIDService • Why does each app instance need a unique ID? • Who manages mapping from users to instance IDs? • FirebaseMessageService • What should happen if your app is in the foreground? • What should happen if your app is in the background? • Note: you will likely need to update via SDK manager git clone https://github.com/firebase/quickstart-android.git .