android - maps & architecture

53

Upload: pedro-vicente

Post on 17-Jul-2015

348 views

Category:

Technology


2 download

TRANSCRIPT

Page 1: Android - Maps & Architecture
Page 2: Android - Maps & Architecture
Page 3: Android - Maps & Architecture

Just a quick stat:

95% of all developers say the 6th session of an academy

is always the best!

Page 4: Android - Maps & Architecture

Let’s talk Maps!

Page 5: Android - Maps & Architecture

Google Maps API v2

Page 6: Android - Maps & Architecture

1. Install and configure the Google Play services SDKThe Google Maps Android API v2 is distributed as part of the Google Play services SDK. You can download the Google Play services SDK via the Android SDK Manager.

2. Add the Google Play services version to your app's manifest<meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />

3. Get an Android certificate and the Google Maps API key

The key is free, you can use it with any of your applications that call the Maps API, and it supports an unlimited number of users. You obtain a Maps API key from the Google APIs Console by providing your application's signing certificate and its package name. Add the key to your application by adding an element to your application's AndroidManifest.xml file.

Step by step: https://developers.google.com/maps/documentation/android/start#getting_the_google_maps_android_api_v2

Page 7: Android - Maps & Architecture

Marker

MapFragment

Market (Info Window) title

Marker (Info Window) snippet

Page 8: Android - Maps & Architecture

Hello Map

<?xml version="1.0" encoding="utf-8"?><fragment xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/map" android:name="com.google.android.gms.maps.MapFragment" android:layout_width="match_parent" android:layout_height="match_parent" />

Page 9: Android - Maps & Architecture

Hello Map import com.google.android.gms.maps.*; import com.google.android.gms.maps.model.*; import android.app.Activity; import android.os.Bundle;

public class MapPane extends Activity {

@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.map_activity);

// Get a handle to the Map Fragment GoogleMap map = ((MapFragment) getFragmentManager() .findFragmentById(R.id.map)).getMap();

LatLng sydney = new LatLng(-33.867, 151.206);

map.setMyLocationEnabled(true); map.moveCamera(CameraUpdateFactory.newLatLngZoom(sydney, 13));

// Other supported types include: MAP_TYPE_NORMAL, // MAP_TYPE_TERRAIN, MAP_TYPE_HYBRID and MAP_TYPE_NONE map.setMapType(GoogleMap.MAP_TYPE_SATELLITE);

map.addMarker(new MarkerOptions() .title("Sydney") .snippet("The most populous city in Australia.") .position(sydney)); } }

Page 10: Android - Maps & Architecture

Location

What provides me location?- GPS- WiFi- Network- …

How? Abstracted by LocationManager which allows you:

1. Query for the list of all LocationProviders for the last known user location.

2. Register/unregister for periodic updates of the user's current location from a location provider (specified either by criteria or name).

3. Register/unregister for a given Intent to be fired if the device comes within a given proximity (specified by radius in meters) of a given lat/long.

Page 11: Android - Maps & Architecture

Location - Permissions

You can register multiple permissions on the Manifest:1. ACCESS_COARSE_LOCATION (WiFi or Mobile Network)2. ACCESS_FINE_LOCATION (GPS)

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

Note: You always need the INTERNET permission to be able to reach the Google Maps servers and render the map on your app.

Page 12: Android - Maps & Architecture

Location// Acquire a reference to the system Location ManagerLocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);

// Define a listener that responds to location updatesLocationListener locationListener = new LocationListener() {    public void onLocationChanged(Location location) {      // Called when a new location is found by the network location provider.      makeUseOfNewLocation(location);    }

    public void onStatusChanged(String provider, int status, Bundle extras) {}

    public void onProviderEnabled(String provider) {}

    public void onProviderDisabled(String provider) {}  };

// Register the listener with the Location Manager to receive location updateslocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);

Page 13: Android - Maps & Architecture

Be smart, use location wisely.

Here's the typical flow of procedures for obtaining the user location:

1.Start application.

2.Sometime later, start listening for updates from desired location providers.

3.Maintain a "current best estimate" of location by filtering out new, but less accurate fixes.

4.Stop listening for location updates.

5.Take advantage of the last best location estimate.

More info: https://developer.android.com/guide/topics/location/strategies.html

Page 14: Android - Maps & Architecture

Beware

The Google Maps Android API uses OpenGL ES version 2 to render the map. If OpenGL ES version 2 is not installed, your map will not appear. 

To prevent Google Play Store from displaying your app on devices that don't support OpenGL ES version 2, add this to the AndroidManifest.xml:

<uses-feature        android:glEsVersion="0x00020000"        android:required="true"/>

Page 15: Android - Maps & Architecture

Architecture 101

Page 16: Android - Maps & Architecture

Let’s focus on RESTful Apps

Page 17: Android - Maps & Architecture

Activity Application

AsyncTask

1. startTask(params)

REST Method

2. start (params)

Processor3. start (params)

4. GET/POST

8. Keep in memory

Most of the apps you can find online…(or at WIT a couple of years ago)…

5. REST method complete callback

6. Operation complete callback

7. Callback to activity

Page 18: Android - Maps & Architecture

Activity

The ones which need database…

AsyncTask

1. startTask(params)

REST Method

2. start (params)

Processor3. start (params)

4. GET/POST

5. REST method complete callback

6. Operation complete callback

7. Callback to activity 9. Store to database/file

Storage Helper

Application8. Keep in memory

Page 19: Android - Maps & Architecture

So…? Anything wrong?

Page 20: Android - Maps & Architecture

So what?

Page 21: Android - Maps & Architecture

Reality:

If an Activity pauses or stops nothing should run until ir restarts

Problems:

If an AsyncTask is running and the app goes to background… what will you do?

Page 22: Android - Maps & Architecture

Reality:

If an Activity pauses or stops nothing should run until ir restarts

Problems:

If an AsyncTask is running and the app goes to background… what will you do?

Solution(s):

• Just cancel the AsyncTask

• Validate when going to the UI thread and ignore it if the Activity is paused

• Continue as normal… what could go wrong?

Page 23: Android - Maps & Architecture

Solution(s):

• Just cancel the AsyncTask

• Validate when going to the UI thread and ignore it if the Activity is paused

• Continue as normal… what could go wrong?

Reality:

If an Activity pauses or stops nothing should run until ir restarts

Problems:

If an AsyncTask is running and the app goes to background… what will you do?

Page 24: Android - Maps & Architecture

Solution(s):

• Just cancel the AsyncTask

• Validate when going to the UI thread and ignore it if the Activity is paused

• Continue as normal… what could go wrong?

Reality:

If an Activity pauses or stops nothing should run until ir restarts

Problems:

If an AsyncTask is running and the app goes to background… what will you do?

Page 25: Android - Maps & Architecture

In each of the options you will either:

- Lose the data from the operation by canceling or ignoring the AsyncTask

- Process data in background where you shouldn’t

- Lose control of how many threads may be running at any given point

- Create a deadlock by cancelling the operation and not recovering the state.

Page 26: Android - Maps & Architecture
Page 27: Android - Maps & Architecture

Besides…

Page 28: Android - Maps & Architecture

AsyncTask is designed to be a helper class around Thread and Handler and does not constitute a generic threading framework. AsyncTasks should ideally be used for short operations (a few seconds at the most.) If you need to keep threads running for long periods of time, it is highly recommended you use the various APIs provided by the java.util.concurrent package such asExecutor, ThreadPoolExecutor and FutureTask.

Page 29: Android - Maps & Architecture
Page 30: Android - Maps & Architecture

Empty your IDE.

Create a block. Carefully shaped.

You connect a LEGO piece into another. They COUPLE PERFECTLY.

You connect two LEGO pieces. They STILL COUPLE PERFECTLY.

You couple 1024 pieces of LEGO. They still fucking COUPLE PERFECTLY! LEGOs can help you BUILD or if dropped create a hell of a pain when stepped upon.

CODE LIKE LEGO, MY FRIEND.

LIKE LEGO.

Page 31: Android - Maps & Architecture

HOW TO CODE LIKE LEGO, MY FRIEND?

Page 32: Android - Maps & Architecture

HOW TO CODE LIKE LEGO, MY FRIEND?

Page 33: Android - Maps & Architecture

HOW TO CODE LIKE LEGO, MY FRIEND?

Page 34: Android - Maps & Architecture

HOW TO CODE LIKE LEGO, MY FRIEND?

Page 35: Android - Maps & Architecture
Page 36: Android - Maps & Architecture

Database

Page 37: Android - Maps & Architecture

Database

Advantages of having a database?

- You should persist early & often

- Mark data

…if app is killed and resumed it knows its last current state.

- Minimize network usage: avoid getting the same data all the time)

Database

Page 38: Android - Maps & Architecture

Database

Ladies and gentleman, the Android Service:

- Create specifically for long running tasks. If you use binders you can define interfaces

- If a service is running the OS will only kill it in last resort (so be friendly…stop it when not using it)

- Can have a ThreadPool inside (or use AsyncTasks TP), to queue requests

Page 39: Android - Maps & Architecture

Fragments

Page 40: Android - Maps & Architecture

The Activity is responsible for one or multiple fragments.

The activity by default can only get the fragments by the FragmentManager

Remember: Use a fragment to make smaller “LEGO blocks” that are easier to maintain an can be reused.

The fragments can always call getActivity() to obtain the current activity which is it’s parent (if there is one).

Everytime you should validate:- If null (an Activity can detach) - The instanceof before casting to a specif

type (maybe do a generic Activity with an interface that all implement?)

Fragments

Page 41: Android - Maps & Architecture

Fragments

public abstract class AbstractActivity implements ControllerInterface {

Private List<FragmentInterface> mMyFragments = new ArrayList<FragmentInterface>();

@Overridepublic void registerFrag(FragmentInterface delegate) { mMyFragments.add(delegate); }

@Override public void unregisterFrag(FragmentInterface delegate) { mMyFragments.remove(delegate); }

public abstract class AbstractFragment extends Fragment implements FragmentInterface {

public interface ControllerInterface { public void registerFrag(FragmentInterface delegate);

public void unregisterFrag(FragmentInterface delegate);}

public void onActivityCreated(Bundle savedInstanceState) {

super.onActivityCreated(savedInstanceState);final ControllerInterface controller =

(ControllerInterface) getActivity();controller.registerFrag(this);

}

public void onDestroy() {super.onDestroy();final ControllerInterface controller =

(ControllerInterface) getActivity();controller.unregisterFrag(this);

}

Page 42: Android - Maps & Architecture
Page 43: Android - Maps & Architecture

BL Manager

Page 44: Android - Maps & Architecture

The Activity has the logic to control the Views but does not have the Business logic.

Basically the Activity should pass the user-interaction to the BL Manager and receive from it the output or data to handle the views.

It should run on the UI Thread when changing the Views.

It should run on Background thread when doing everything else, including invoking the BL Manager

The BL Manager is the core of the Application. It contains the logic specific of the application you are developing.

For bigger apps there should be multiple managers.

It is normally a Singleton which lives in the ApplicationSingleton……yeah I don’t like singletons too.. but let me explain.

- It receives feedback from the Activities and triggers what should be triggers (Services, Broadcasts, ...).

- Also it receives data from the Services (which can be alive when the Activities are not) – Background & App killed

It NEVER runs on the UI Thread.

BL Manager

Page 45: Android - Maps & Architecture

@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // register for events EventBus bus = EventBus.getDefault(); bus.register(this);

Login login = new Login(username,password);

bus.post(login);

}

Use EventBus

Or whatever you like!

//This is already running on background thread

public void onEventAsync(Login event) {

//Call Service and do stuff… }

BL Manager

Page 46: Android - Maps & Architecture

BL Manager

Page 47: Android - Maps & Architecture

The BL is responsible for telling the Service what to do.

The Service is a “semi-dumb” slave which receives orders and executes them.

The BL Manager should use the startService to initialize the Service and then bind to it.

To make a scalable application a good implementation of a Service, is a Service with an ThreadPool inside.

That way you manage to:- control how many requests are being

done- which are being executed at any given

time- cancel them or remove them before being

executed- Separate the specific code on Tasks

BL Manager

Page 48: Android - Maps & Architecture

public void onEventAsync(StartService event) { if (! Service.isServiceRunning) { context.startService(intent); } context.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE); }

private ServiceConnection mServiceConnection = new ServiceConnection() {

@Override public void onServiceConnected(ComponentName className, IBinder service) { if(service != null) { mServiceBinder = (ServiceBinder) service; mServiceBounded = true; mServiceBinder.registerManager(this); } }

@Override public void onServiceDisconnected(ComponentName className) { mServiceBounded = false; } };

public static boolean isServiceRunning = false;

@Override public void onCreate() {

/** * DO NOT DO ANYTHING HERE THIS IS RUN BY THE UI THREAD.

isServiceRunning = true;

super.onCreate();}

private void doAwesomeStuff(){ // do stuff}

public class ServiceBinder extends Binder implements ServiceInterface {

@Override public void doAwesomeStuff() { Service.this. doAwesomeStuff();

}}

BL Manager

Page 49: Android - Maps & Architecture

public class TutorialProvider extends ContentProvider {

public static final String CONTENT_DATABASE_TABLE =

“content_table”;

public static final String IDS_DATABASE_TABLE =

“ids_table”;

private static final String AUTHORITY =

"com.wit.tutorial.providers.tutorialprovider";

public static final Uri CONTENT_URI = Uri.parse("content://" +

AUTHORITY);

private static final UriMatcher URI_MATCHER = new

UriMatcher(UriMatcher.NO_MATCH);

static {

URI_MATCHER.addURI(Status.AUTHORITY, “information/content”,

DATABASE_INFORMATION_CONTENT);

URI_MATCHER.addURI(Status.AUTHORITY, “information/ids”,

DATABASE_INFO_IDS); 

    @Override

    public boolean onCreate() {

        mDB = ((YourApplication) getContext()).getDatabase();

        return true;

    }

@Override

public Cursor query(Uri uri, String[] projection, String

selection, String[] selectionArgs, String sortOrder) {

String selectedTable;

final int uriType = URI_MATCHER.match(uri);

switch (uriType) {

case DATABASE_INFORMATION_CONTENT:

selectedTable = DATABASE_INFORMATION_CONTENT

break;

case DATABASE_INFO_IDS:

selectedTable = DATABASE_INFORMATION_IDS

break;

if (selectedTable != null) return null;

// build SQL query

SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();

queryBuilder.setTables(selectedTable);

String sqlQuery = queryBuilder.buildQuery(projection,

selection, null, null, null, sortOrder, null);

// run query

try {

return database.rawQuery(sqlQuery, selectionArgs);

} catch (SQLiteException ex1) {

return null;

} catch (IllegalArgumentException ex2) {

return null;

}

}

Page 50: Android - Maps & Architecture

After this…

Android is peaners

Page 51: Android - Maps & Architecture
Page 52: Android - Maps & Architecture
Page 53: Android - Maps & Architecture