Android pro tips trilogy

Post on 12-Apr-2017

36 Views

Category:

Software

1 Downloads

Preview:

Click to see full reader

Transcript

Wifi: pUp3EkaP

> 2000 members Largest Android Active Community

Jonathan Yarkoni

Android Developer & Advocate

Ironsource

Android Academy Staff

Yonatan Levin

Android Google Developer

Expert

Britt Barak

Android LeadFigure8

Yossi Segev

Android DeveloperColu

Shahar Avigezer

Android DeveloperHello Heart

Community Mentors

What Do We Do?

● Android Fundamentals - NOW

● Android UI / UX - 29/1 !

● Community Hackathon - 9/3 !!!

● Android Performance

● Mentors Program● Active community

+RanNachmany@shed2k

From good to awesome

01Install

01Install

02Launch

Start!

01Install

02Launch

03Look & Feel

Start!

01Install

02Launch

03Look & Feel

04Use

Start!

Step 1: InstallFirst touch point.

Minimize Permissions• Request only core functionality blockers.

Minimize Permissions• Request only core functionality blockers.• You don't need permission to launch another App that has

the permission

Minimize Permissions• Request only core functionality blockers.• You don't need permission to launch another App that has

the permission

Need a contact?

Use the force, Luke

Asking for contact

Intent intent = new Intent(Intent.ACTION_GET_CONTENT);intent.setType(Phone.CONTENT_ITEM_TYPE);startActivityForResult(intent, MY_REQUEST_CODE);

void onActivityResult(int requestCode, int resultCode, Intent data) {

if (data != null) { Uri uri = data.getData(); if (uri != null) { Cursor c = getContentResolver().query(uri, new String[] {Contacts.DISPLAY_NAME,

Phone.NUMBER}, null,null, null) }

}}

Asking for contact

Need a UUID?

Option 1: TelephonyManager.getDeviceIdRequires READ_PHONE_STATE.

Option 2: Settings.Secure.ANDROID_IDReset at wipeFollows the device, not the user.

Use the force, Luke

Generate UUIDUse backup API

Step 2: First Launch“ok, let’s see what this app is all about”

My BigBRAND

LOADING ...

A bunch of data to insert?

SQLTransactions speeds things up

db.beginTransaction();

try{ for(int i=0; i<selectedIds.length; i++){ values.put(COLUMN_ID,selectedIds[i]); values.put(COLUMN_STARRED,starred); db.insert(TABLE_STARRED,null,values); db.yieldIfContendedSafely(); } db.setTransactionSuccessful();}finally { db.endTransaction();}

Bulk DB update

Not fast enough?

Server Side● Create a db file using SQLite and

fill it.● Name your primary key columns

“_id”● Create a table:

“android_metadata”● Insert a single row containing the

locale (ex: "en_US")

Import ready to use DB

Mobile Side● Grab the zipped DB from assets

or network.● Unzip it to your getDatabaseDir()● Use as usual

Import ready to use DB

SQLite version

Step 3: Look & Feel“Where is the share button?”

HOTMAIL

OUTLOOK.COM

HOTMAIL OUTLOOK.COM

Follow the guidelines

LOOK AND FEEL

LOOK AND FEEL

LOOK AND FEEL

LOOK AND FEEL

LOOK AND FEEL

LOOK AND FEEL

Follow the guidelines

Please

Step 4: Daily Use“I really like it, but...”

Always up to dateUsers don't like to wait. • Location updated.• Data downloaded from web.

Always up to dateUsers don't like to wait. • Location updated.• Data downloaded from web.

Find the location fast.• Loop through all providers->getLastKnownLoc.

• If there is one or more location which is recent enough – return the most accurate one

• If not – Return the latest one.• In case of #2 – look for “fastest” provider:

• Coarse Accuracy && low power consumption. • Register for location update.

Use passive location• >Gingerbread. • Passive location – Receive location update when other app is using

location provider. • Requires ACCESS_FINE_LOCATION permission.• Location.getProvider().

Fused Location• Define your priorities • Let Google play services do the heavy lifting.

// Create an instance of GoogleAPIClient.if (mGoogleApiClient == null) { mGoogleApiClient = new GoogleApiClient.Builder(this) .addConnectionCallbacks(this) .addOnConnectionFailedListener(this) .addApi(LocationServices.API) .build();}

Using fused location

@Overridepublic void onConnected(Bundle connectionHint) { //get last known location mLastLocation = LocationServices.FusedLocationApi.getLastLocation( mGoogleApiClient); if (mLastLocation != null) { //do something }

//register for location updates LocationRequest request = LocationRequest.create(); request.setInterval(minTime); request.setPriority(lowPowerMoreImportantThanAccuracy ? LocationRequest.PRIORITY.BALANCED_POWER_ACCURACY : LocationRequest.PRIORITY_HIGH_ACCURACY ); LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, request, this);}

Using fused location

@Overridepublic void onLocationChanged(Location location) { mCurrentLocation = location; mLastUpdateTime = DateFormat.getTimeInstance().format(new Date()); updateUI();}

Using fused location

Data updates

The challenges:• When to update?• Where the data is coming from?• What to update?• How to update?

When to update my App?• Right before the user launches it

• Assuming I have battery.• Assuming I have BW.

Where the data is coming from?• My Server• 3rd Party Servers

Where the data is coming from?• My Server• 3rd Party Servers

What to Update? • What's Hot• Interesting stuff• Other

BG Update

What's Hot

BG Update

Interesting Stuff Other

BG Update

What's Hot

BG Update

Interesting Stuff Other

FCM Embedded

BG Update

What's Hot

BG Update

Interesting Stuff Other

FCM Embedded

FCM + Back-off

BG Update

What's Hot

BG Update

Interesting Stuff Other

FCM Embedded

FCM + Back-off

Daily / Bundled

Being Invisible• I don't need to think how the app works.• I never notice the app's work.• I am never being bothered by the app.

Work OfflineQueue and Send transactions.• Use persistence layer.• Tape From Square.

Work Semi-Offline• Be resilient to poor networks.

• Prioritize your transactions.• Be able to cancel transaction on the fly, or clear the Queue.• Adjust your app’s behavior and timeouts accordingly.

• Use Volley (or any other cool transport layer)

Be efficient – Data usage

Radio Resource• Frequency is expensive. • Cell tower can not service 100% of its clients 100% of the time. • Frequency is dynamically allocated to clients.

• Cellular cells uses various multiplexing methods (OFDM/OFDMA, FTDMA).

UMTS RRC States. (source: 3gpp)

Radio State Machine

IDLE

FACH

DCH

Power

Bandwidth

Radio State Machine

IDLE

FACH

DCH

Power

~10Sec tail time

~12-75 Sec tail time

Bandwidth

Avoid bursty traffic• Transmit data “together”.

• Piggyback if needed.• Pre-fetch data for the next 2-5 minutes.

• Don't ping just to keep TCP connection alive• RRC != TCP Connection.• TCP connection is kept even in IDLE mode

#1: Case study: Pandora• Music file streamed as single file.• Analytics data sends ~2KB every 62.5 seconds

Source: AT&T research

#1: Case study: Pandora

0.2% of data consumed 46% of energy!

Don't be HTTP rookie• Don't download what you already have.• Take care of server headers

• Max-age, expires. • Use conditional GET when cache expires

• Use “last modified” header.• Server return 304, with no body.

Adaptive App• Optimized for different User Experience.

• User has more than one device. • Be predictable.• Behave as expected

Text Input• Specify the Edit Text input to show the right keyboard type.

• use android:inputType attribute• Four classes of keyboards:

• Plain text• Decimal Number• Phone Number• Date or Time

Text Input• Plain text types:

• URIs• Email address• People's names• Postal address• Passwords

mGeofenceList.add(new Geofence.Builder() // Set the request ID of the geofence. This is a string to identify this // geofence. .setRequestId(entry.getKey())

.setCircularRegion( entry.getValue().latitude, entry.getValue().longitude, Constants.GEOFENCE_RADIUS_IN_METERS ) .setExpirationDuration(Constants.GEOFENCE_EXPIRATION_IN_MILLISECONDS) .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT) .build());

Geofencing

private GeofencingRequest getGeofencingRequest() { GeofencingRequest.Builder builder = new GeofencingRequest.Builder(); builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER); builder.addGeofences(mGeofenceList); return builder.build();}

Geofencing

private PendingIntent getGeofencePendingIntent() { // Reuse the PendingIntent if we already have it. if (mGeofencePendingIntent != null) { return mGeofencePendingIntent; } Intent intent = new Intent(this, GeofenceTransitionsIntentService.class); // We use FLAG_UPDATE_CURRENT so that we get the same pending intent back when // calling addGeofences() and removeGeofences(). return PendingIntent.getService(this, 0, intent, PendingIntent. FLAG_UPDATE_CURRENT);}

Geofencing

LocationServices.GeofencingApi.addGeofences( mGoogleApiClient, getGeofencingRequest(), getGeofencePendingIntent() ).setResultCallback(this);

Geofencing

private void initTextToSpeech() { Intent intent = new Intent(Engine.ACTION_CHECK_TTS_DATA); startActivityForResult(intent,TTS_DATA_CHECK)}

Geek Magic - Text to speech

private void onActivityResult(int request, int result, Intent data) { if (TTS_DATA_CHECK == request && Engine.CHECK_VOICE_DATA_PASS == result) { tts = new TextToSpeech(this, new on InitListener() { public void onInit(int status) { if (TextToSpeech == status) { ttsIsInit = true; } }

});}else { startActivity(new Intent(Engine.ACTION_INSTALL_TTS_DATA));}

}

Geek Magic - Text to speech

private void say(Strint text) { if (null != tts && ttsIsInit) { tts.speak(text,TextToSpeech.QUEUE_ADD, null); }}

Geek Magic - Text to speech

private void requestVoiceInput() { Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); intent.putExtra(RecognizerIntent.EXTRA_PROMPT, getString(R.String.voice_input_prompt); intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.ENGLISH); startActivityForResult(intent,VOICE_RECOGNITION);}

Geek Magic - Speech Recognition

private void requestVoiceInput() { Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); intent.putExtra(RecognizerIntent.EXTRA_PROMPT, getString(R.String.voice_input_prompt); intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.ENGLISH); startActivityForResult(intent,VOICE_RECOGNITION);}

Geek Magic - Speech Recognition

Geek Magic – Speech Recognition• More than one result is returned.• Loop through all results, taking context in mind.

<intent-filter> <action android:name="android.intent.action.VIEW"/> <category android:name="android.intent.category.DEFAULT"/> <data android:host="mysite.com" android:scheme="http"/></intent-filter>

Intercept Links

Follow the guidelines

Be FreshBe InvisibleBe EfficientBe AdaptiveBe Psychic

Make it quick

Start!

minimize permissions

Thank You!+RanNachmany@shed2k

top related