Android Study
Background Processing
Doze
Doze
Alarms to not fire in Doze mode.
Foreground Services
Background Location
Saving Data
Alarm Manager
FusedLocationProvider
Uses Google Play API. Must add this to your gradle.build.
Must ask for ACCESS_BACKGROUND_LOCATION permission.
In Manifest:
<uses-permission android:name=“android.permission.ACCESS_COARSE_LOCATION”/>
private FusedLocationProviderClient fusedLocationClient;
// ..
@Override
protected void onCreate(Bundle savedInstanceState) {
// ...
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
}
Getting the last location:
fusedLocationClient.getLastLocation()
.addOnSuccessListener(this, new OnSuccessListener<Location>() {
@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
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.
Batch Network Updates Intro Video
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
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
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
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
Protocol Buffers
Nano-proto Buffers
Flat Buffers
Use Network Monitor Tool in Android Studio to view asset usage issues
Service Performance Patterns
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
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
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!
Smaller Serialized Data
Caching UI Data
CPU Frequency Scaling
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
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:
Price of 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<String, Bitmap>(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<String, Bitmap>(availBytes/8);
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
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
Overdraw
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
App Launch Time
Smaller APKs
Smaller resources
In build.gradle in
BuildTypes{
Release {
minifyEnabled: True
shrinkResources: True
proguardFiles getDefaultProguardFile('proguard-android.txt', 'proguard-tools.pro')
}
}
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
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 {
}