======Android Study======
====Background Processing====
[[https://developer.android.com/guide/background|Guide to Background Processing]]
====Doze====
[[https://developer.android.com/training/monitoring-device-state/doze-standby|Doze]]
Alarms to not fire in Doze mode.
====Foreground Services====
[[https://android-developers.googleblog.com/2018/12/effective-foreground-services-on-android_11.html|Effective Foreground Services]]
====Background Location====
[[https://developer.android.com/about/versions/oreo/background-location-limits|Background Location Limits]]
====Saving Data====
* Shared Preferences
* SQL
====IME KEyboard Input====
Starting from Android 1.5, the Android platform offers an Input Method Framework (IMF). https://android-developers.googleblog.com/2009/04/updating-applications-for-on-screen.html
An input method editor (IME) is a user control that enables users to enter text. To add an IME to the Android system, you create an Android application containing a class that extends InputMethodService.
[[https://developer.android.com/guide/topics/text/creating-input-method|Creating Input Method]]
====Alarm Manager====
Periodically eexecute
==== FusedLocationProvider ====
Uses Google Play API. Must add this to your gradle.build.
Must ask for ACCESS_BACKGROUND_LOCATION permission.
In Manifest:
private FusedLocationProviderClient fusedLocationClient;
// ..
@Override
protected void onCreate(Bundle savedInstanceState) {
// ...
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
}
Getting the last location:
fusedLocationClient.getLastLocation()
.addOnSuccessListener(this, new OnSuccessListener() {
@Override
public void onSuccess(Location location) {
// Got last known location. In some rare situations this can be null.
if (location != null) {
// Logic to handle location object
}
}
});
====LocationManager====
ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION in manifest
====Google Cloud Messaging (GCM) ====
Server informs the app on phone that there is new data on server. Battery efficient, the device does not have to poll.
**Note**: When using GCM, your app can pass messages in normal or high priority. Your server should typically use normal priority to deliver messages. Using this priority level prevents devices from being woken up if they are inactive and in a low-power Doze state. Use high priority messages only if absolutely required.
====Pre-Fetching====
* Download 2 to 5 minutes of data likely to be used. Such as one full song.
* 1 to 5Mb on a 3G network
* Measure usage so you know what best to download.
* Use HTTP live streaming where possible
* Record and determine usage patterns to know what to prefetch
* News all want to download a lot of articles and pictures and feed to app asynchronously to provide good user experience.
* Possibly schedule downloads when device is charging.Intent.ACTION_BATTERY_CHANGED
* Use Google Cloud Messaging (see above) to let the server notify app to fetch updates.
* Track activity of user and pre-fetch when user is not interacting with the app, but has the app open. Intent.ACTION_STRING. This is "Context Driven Prefetching"
https://developer.android.com/training/efficient-downloads/efficient-network-access.html#PrefetchData
https://www.youtube.com/watch?time_continue=175&v=Rk1u7VVmadE&feature=emb_logo
====Batch Network Requests====
* Network access is the biggest battery drain.
* After a network request the chip waits around using power for an extra 20 to 60 seconds.
* Piggy-back on other services firing up network. GCM Network Manager!
Use GCM Network Manager. It will allow you to batch requests and send/receive efficiently.
[[https://www.youtube.com/watch?time_continue=28&v=Ecz5WDZoJok&feature=emb_logo|Batch Network Updates Intro Video]]
====Android Performance Patterns Videos====
https://www.youtube.com/playlist?list=PLWz5rJ2EKKc9CBxr3BVjPTPoDPLdPIFCE
* Screen refreshed 60 =time/sec, every 16ms.
* If a process will take 16ms, do it in a thread!
Threading methods:
* AsyncTask
* HandlerThread
* ThreadPool
* IntentService
HandlerThread
* **Long running thread.**
* Looper accessed by a Handler
* Gets jobs from a queue
* Should set thread priority!
ThreadPool Class
* **ThreadPoolExecutor** manages thread Pools. Spins up threads and you toss work to them.
* Only for large numbers of jobs
* Lots of work into little buckets
* Should set thread priority!
Each tread costs 64k minimum
AsyncTasks
* queue up.
* Waits for previous one to complete.
* If canceled, onCanceled() is called. Should not create AsyncTask as an inner class. If Activity gets destroy its reference will remain in memory until the task completes!
Intent Service Class
* Moves all intent responses to another thread for you
* Acts like a service, inherits from Service
* Makes your app less likely to be killed by the system
* Not a general purpose threading solution. Really only for intents
* Can call RunonUIThread or LocalBroadcast an intent to the Activity to update UI
LoaderManager
* Avoids memory leaks when UI is destroyed but threads are active
Latency
* Need to adapt to changing network quality
* 1) Gather info about the network, 2) Make adjustments
* Use connectivityManager and get the network connection type
* Use the emulator and use "Emulator Throttling"
* Use AT&Ts Network Attenuator
Minimize Asset Size
* Make as small as possible to avoid network bloat
* Large assets drain battery
* Large assets costs money for the user
* Don't use PNGs if not necessary
* Play with JPG quality to reduce size
* Store different sizes and qualities of images on your server
* JSON and XML are horribly large
* Protocol Buffers
* Nano-proto Buffers
* Flat Buffers
//Use Network Monitor Tool in Android Studio to view asset usage issues//
Service Performance Patterns
* Services can drain system resources
* Services run on the UI Thread!
Minimize Code
* Use Proguard to remove unused code, obfuscate method names, create a smaller size
* Enable this by an entry in the gradle file. MinifyEnabled"
* "ShrinkResources" will remove unused resources from build
Cache
* Use LRUCache to cache data. It is easy!
Approximation
* Use easier to calculate values when possible.
* Example: may not need high resolution position info all the time
* "Good Enough. Let's Ship it"
Culling
* Remove code where you are wasting processing time.
* Use ClipRect when drawing custom views
* Overdraw is not so much a problem in the latest OS improvements
Data Serialization
* Don't extend your class to a Serializable class. Inefficient.
* GSON library is more efficient than Serializable, but uses JSON (bloated)
* JSON and XML are inefficient!
* Android resource files are XML but are compiled into a more efficient structure for run-time
* **Protocol Buffers** - Not good for mobile development, lots of overhead
* **Nana-Proto-Buffers** is Proto Bufs optiminized for mobile development
* **FlatBuffers** //focused on performance// - Efficient! Best to use.
* **SharedPreferences** is a key/value store, best for simple storage
* **Parcelable** - best for passing between running processes
USE FlatBuffers to pass data instead of JSON!
* **SQLite** - Store structured data
Smaller Serialized Data
* To serialize objects efficiently - **Struct-of-Arrays** is efficient - then FlatBuffer the result
Caching UI Data
* While displaying cached data while fetching new data, inform user with some type of "Syncing" message/
CPU Frequency Scaling
* The OS slows down processor to save battery
* Frame rates may go down
* Use Systrace to determine what is happening
Array Maps
* More efficient than HashMap
* Runtime access grows a bit as data size grows
* Inserts and deletions cost a bit more
* Uses less memory when small
* Best used if number of key value pairs is not large. There is an efficiency hit, so use HashMap for large sets of key/vale pairs
* Don't need to use iterator, can use index in a for loop. More efficient
* Use when you have < 1000 objects
* Use when you have Maps of Maps
Beware Autoboxing
* Ex: Using Integer as int, may cause a lot of temp object creation in for loops!
* This overhead shows up in HashMap access. So use specific types:
* Special types of HashMap for NO Autoboxing:
* HashMap
* SparseBoolMap
* SparceIntMap
* SparceLongMapMlong, obj>
* LongSparceMap
* SparseMaps always use primitive type as the key
* Use Allocation Tracker to find where a lot of inter objects are coming from one call site.
* With traceView find where a lot of allocations are happening
Price of Enums
* Enums take a lot of memory
* Enums are like Gremlins
* Try to avoid enums!
* Use @intDef((ENUM1, ENUM2, ENUM3)) to avoid memory costs
* ProGuard has an option to optimize enums
Trimmed and Shared Memory
* onTrimMemeory(trimValue) is called to inform your app to release unnecessary memory. All in-memory apps are notified. Activity, Service, Fragment all get this notification.
* onLowMemory() callback happens after all other apps are killed
* ActivityManager.isLowRamDevice(), you can query this
Do NOT Leak Views
* Don't reference views inside of Async callbacks
* Don't reference views from static obhects.
* Be careful storing views in collections or WeakHashMap s.
* Use Allocation Tracker in Android Studio
Location and Battery
* setInterval()
* Back off interval if user is not changing position much
* Updated at fastest rate of any apps. You can get flooded
* setFastestInterval(), limits how fast your app gets positions
* LocationRequest.setPrioroty()
* FusedLocationProvider
layouts
* Watch cascading repositioning
* Use Systrace
* Minimize the depth in view hierarchy
* Avoid calling layout requests when not necessary
Object Pools
* Can be the source of a lot of GC (Garbage Collection) events
* Allocate in groups - allocates have overhead
* Pre-allocate groups at start of app to make startup fast. Minimized having to go back to the heap many times at start of app.
* You are in charge of freeing from the pool. No auto GC.
* When freeing an object, clen up variables to make sure they do not reference other objects. This is a memory leak.
* USe the AllocationTracker
* Reduces memory churn
Iterators or Index?
* Every time you get an iterator it results in a memory allocation
* it.next() takes some resource to get the next.
* Adnroid platform team does not use iterators!!!
* Simple for loop is fastest! Iterators slowest.
LruCache Class
* LruCache c = new LruCache(size_in_bytes);
* Stores in a key/value relationship.
* Bounded container - has a max size you define.
* You can get the amount of memory available for your app and use some portion. Example:
ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
int availBytes = am.getMemoryClass() * 2014 * 1024;
LruCache c = new LruCache(availBytes/8);
* Tweak the size as you learn over time
* get() and put()
LINT
* Can spot and report potential errors and memory usage problems (churn)
* In Android Studio Analyze->"Inspect Code" will run Lint
* In File->Options you can select which issues to report
* Set memory allocations issues to thow an error!
*
Hidden Cost of Transparency
* Alpha blending costs
* Video 46
Avoid Allocations in onDraw()
* onDraw() runs onthe UI thread
* onDraw gets called 60 times a second
* A high rate of allocations creates a lot of memory churn, GC eats up battery
* MOVE allocations out of onDraw()
* Make the objects static outside of onDraw()
Strict Mode:
* Used to detect bad things done on the UI Thread
* In developer options select Strict Mode
* Whenever there is an issue, the border will flash red in your app
* StrictMode Class can be used to specify detection criteria and what action to take when the condition is met
* Best to StrictMode.noteSlowCall() before sychronization{}
* No allocations on UI thread! StictMode helps identify
Custom Views and Performance
* Don't call view.invalidate() if not necessary
* Always pass a rectangle to invalidate!
* Canvas.clipRect() limits call to
* Don't draw anything you dont have to
* Don't use draw methods that are not hardware accelerated. Varies by Android version.
* Don't make allocations in onDraw()!!!!
Batching Work Until Later
* Batching helps battery power
* Turning on things at irregular times wasted power to turn them on
* Power state transitions are power hungry
* AlarmManager can be in exact or inexact
* Don't call AlarmManager.setExact()!
* Use SyncAdapter in app. Sync adapters are designed specifically for syncing data between a device and the cloud; you should only use them for this type of task.
* JobScheduler in API > 21, can set a lot of conditions, like when charging and on Wifi.
* In Android N (API level 24), the SyncManager sits on top of the JobScheduler. You should only use the SyncAdapter class if you require the additional functionality that it provides.
Image Memory Usage
* PNG and JPG images use CPU memory and are transfered to GPU memory as textures.
* Defaults to 32 bit pixels
* There are differenct formats you can store then in, 565, 4444, etc.
bitmap.Options.setPreferredConfig(Bitmap.Config.RGB_565)
Smaller PNG data
* Use Web-P format.
* Web-P is supported natively
* Only helps with data transfer, still takes same size in memory
Scaling Bitmaps
* Resize images programmatically to the size they will be on screen.
* createScaledBitmap()
* Can scale image when loading with bitmapOptions
* Glide and Picasso libraries handle resizing
*
Reusing Bitmaps
* You can re-use bitmap objects
* Set the inBitmap option to a bitmap and the decode will reuse
* mBitmapOptions.inBitmap = mCurrentBitmap;
* Size must <= new bitmap size
* Avoids memory fragmentation
* Create ObjectPools, each has a size and RGB format in common.
* Use Glide library to do this
Perfomance Tuning Lifestyle
* Think about performance ahead of a time
* Gather, Insight, Action
* Use a tool to gather information.
Overdraw
* Overdraw is how many times a pixel is drawn in a single frame
* Turn on Show Overdraw in dev options to debug
* Tints showing overdraws
* Overlapping backgrounds
Understanding VSYNC
* Refresh Rate
* Frame Rate
* If refresh rate > Frame Rate, you get tearing
* Double buffering by the GPU
* VSYNC will copy from GPU to screen during VSYNC
Profile GPU Rendering Tool
* In dev mode on device
* Keep all bars < 16ms!
GPU
* DisplayList submitted to the GPU
* Turn on the GPU View in dev mode. Invalidates will show in red.
* Use Hierarchy Viewer
App Launch Time
* Don't display a splash screen
* Fix the main activity so the load time is quick
Smaller APKs
* Smaller resources
* In build.gradle in
*
BuildTypes{
Release {
minifyEnabled: True
shrinkResources: True
proguardFiles getDefaultProguardFile('proguard-android.txt', 'proguard-tools.pro')
}
}
* Toss out images you don't need for all resolutions.
* Use "Vector Drawables"
* Rotate images instead of separate images.
* Smaller code
* minifiedEnabled: true
* Optimize code like enums (which get inflated to a class)
* JARs can be large. Proguard only helps a bit. Find smaller alternatives.
* You can split APKs into different versions
*
====Tools to use====
* Systrace Trace.beginSection(), Trace.endSection()
* Network Monitor Tool - in Android Studio
* Network Attenuator from AT&T
* ARO Tool from AT&T
* Allocation Tracker
* TraceView
* Battery Historian
* DDMS in Android Studio. Best of all memory tools
* Heirarchy View
* On device tools: Profile GPU (Rendering), Show GPU (Overdraw), GPU View (Updates) `
* Heap Tool
* Memory Monitor
* Start Method Tracing Tool
* Method Profile Tool
* APK Analyzer
Vector Drawable
* One file generates all resolutions on demand
* Can be animated with an XML file
* Can take more time to load into GPU
* Pay attention to the complexity of the paths in your vector data
====NOTES:====
New Java 5 syntax:
for (Object obj : list {
}