You are on page 1of 53

Just a quick stat:

95% of all developers say


the 6th session of an academy
is always the best!
1. Install and configure the Google Play services SDK
The 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


MapFragment

Market (Info Window) title

Marker (Info Window) snippet

Marker
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" />
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));
}
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.
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.
Location
// Acquire a reference to the system Location Manager
LocationManager locationManager = (LocationManager)
this.getSystemService(Context.LOCATION_SERVICE);

// Define a listener that responds to location updates


LocationListener 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 updates
locationManager.requestLocationUpdates(LocationManager.NETWORK_PRO
VIDER, 0, 0, locationListener);
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


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"/>
Architecture 101
Most of the apps you can find online…
(or at WIT a couple of years ago)…
8. Keep in memory
Activity Application
1. startTask(params) 7. Callback to activity

AsyncTask
2. start (params) 6. Operation complete callback

Processor
3. start (params) 5. REST method complete callback

REST Method
4. GET/POST
The ones which need database…

8. Keep in memory
Activity Application
1. startTask(params) 7. Callback to activity 9. Store to database/file

AsyncTask Storage Helper


2. start (params) 6. Operation complete callback

Processor
3. start (params) 5. REST method complete callback

REST Method
4. GET/POST
So…? Anything wrong?
So what?
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?
Reality:

If an Activity pauses or stops


nothing should run until ir Solution(s):
restarts
• Just cancel the AsyncTask
Problems:
• Validate when going to the UI thread and
If an AsyncTask is running and ignore it if the Activity is paused
the app goes to background…
what will you do? • Continue as normal… what could go wrong?
Reality:

If an Activity pauses or stops


nothing should run until ir Solution(s):
restarts
• Just cancel the AsyncTask
Problems:
• Validate when going to the UI thread and
If an AsyncTask is running and ignore it if the Activity is paused
the app goes to background…
what will you do? • Continue as normal… what could go wrong?
Reality:

If an Activity pauses or stops


nothing should run until ir Solution(s):
restarts
• Just cancel the AsyncTask
Problems:
• Validate when going to the UI thread and
If an AsyncTask is running and ignore it if the Activity is paused
the app goes to background…
what will you do? • Continue as normal… what could go wrong?
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.
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.
Empty your IDE.

Create a block.
Carefully shaped. LIKE LEGO.
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.


HOW TO CODE LIKE LEGO, MY FRIEND?
HOW TO CODE LIKE LEGO, MY FRIEND?
HOW TO CODE LIKE LEGO, MY FRIEND?
HOW TO CODE LIKE LEGO, MY FRIEND?
Database
Advantages of having a database?

- You should persist early & often

- Mark data
Database
…if app is killed and resumed it
knows its last current state.

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

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

Database
Fragments
Fragments

The Activity is responsible for one or The fragments can always call getActivity() to
multiple fragments. obtain the current activity which is it’s parent
(if there is one).
The activity by default can only get the
fragments by the FragmentManager 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
Remember: Use a fragment to make interface that all implement?)
smaller “LEGO blocks” that are easier to
maintain an can be reused.
Fragments
public abstract class AbstractActivity implements public abstract class AbstractFragment extends Fragment implements
ControllerInterface { FragmentInterface {
public interface ControllerInterface {
Private List<FragmentInterface> mMyFragments = new public void registerFrag(FragmentInterface delegate);
ArrayList<FragmentInterface>();
public void unregisterFrag(FragmentInterface delegate);
@Override }
public void registerFrag(FragmentInterface delegate)
{ public void onActivityCreated(Bundle savedInstanceState) {
mMyFragments.add(delegate); super.onActivityCreated(savedInstanceState);
} final ControllerInterface controller =
(ControllerInterface) getActivity();
@Override controller.registerFrag(this);
public void unregisterFrag(FragmentInterface delegate) }
{
mMyFragments.remove(delegate); public void onDestroy() {
} super.onDestroy();
final ControllerInterface controller =
(ControllerInterface) getActivity();
controller.unregisterFrag(this);
}
BL Manager
BL Manager

The Activity has the logic to control the The BL Manager is the core of the Application.
Views but does not have the Business It contains the logic specific of the application
logic. you are developing.

Basically the Activity should pass the For bigger apps there should be multiple
user-interaction to the BL Manager and managers.
receive from it the output or data to
handle the views. It is normally a Singleton which lives in the
ApplicationSingleton…
It should run on the UI Thread when …yeah I don’t like singletons too.. but let me
changing the Views. explain.

It should run on Background thread - It receives feedback from the Activities


when doing everything else, including and triggers what should be triggers
invoking the BL Manager (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

@Override Use EventBus


protected void onCreate(Bundle //This is already running on background
savedInstanceState) { thread

super.onCreate(savedInstanceState); public void onEventAsync(Login event) {

// register for events //Call Service and do stuff…


EventBus bus = EventBus.getDefault(); }
bus.register(this);

Login login = new


Login(username,password);

bus.post(login);
Or whatever you
} like!
BL Manager
BL Manager

The BL is responsible for telling the To make a scalable application a good


Service what to do. implementation of a Service, is a Service with
an ThreadPool inside.
The Service is a “semi-dumb” slave
which receives orders and executes That way you manage to:
them. - control how many requests are being
done
The BL Manager should use the - which are being executed at any given
startService to initialize the Service and time
then bind to it. - cancel them or remove them before
being executed
- Separate the specific code on Tasks
BL Manager
public void onEventAsync(StartService event) { public static boolean isServiceRunning = false;
if (! Service.isServiceRunning) {
context.startService(intent); @Override
} public void onCreate() {
context.bindService(intent, mServiceConnection,
Context.BIND_AUTO_CREATE); /**
} * DO NOT DO ANYTHING HERE THIS IS RUN BY THE
UI THREAD.
private ServiceConnection mServiceConnection = new
ServiceConnection() { isServiceRunning = true;

@Override super.onCreate();
public void onServiceConnected(ComponentName }
className, IBinder service) {
if(service != null) { private void doAwesomeStuff(){
mServiceBinder = (ServiceBinder) service; // do stuff
mServiceBounded = true; }
mServiceBinder.registerManager(this);
} public class ServiceBinder extends Binder implements
} ServiceInterface {

@Override @Override
public void onServiceDisconnected(ComponentName public void doAwesomeStuff() {
className) { Service.this. doAwesomeStuff();
mServiceBounded = false;
} }
}; }
public class TutorialProvider extends ContentProvider { @Override
public static final String CONTENT_DATABASE_TABLE = public Cursor query(Uri uri, String[] projection, String

“content_table”; selection, String[] selectionArgs, String sortOrder) {


public static final String IDS_DATABASE_TABLE = String selectedTable;
“ids_table”; final int uriType = URI_MATCHER.match(uri);
private static final String AUTHORITY = switch (uriType) {
"com.wit.tutorial.providers.tutorialprovider"; case DATABASE_INFORMATION_CONTENT:
public static final Uri CONTENT_URI = Uri.parse("content://" + selectedTable = DATABASE_INFORMATION_CONTENT
AUTHORITY); break;
private static final UriMatcher URI_MATCHER = new case DATABASE_INFO_IDS:
UriMatcher(UriMatcher.NO_MATCH); selectedTable = DATABASE_INFORMATION_IDS
static { break;
URI_MATCHER.addURI(Status.AUTHORITY, “information/content”, if (selectedTable != null) return null;
DATABASE_INFORMATION_CONTENT); // build SQL query
URI_MATCHER.addURI(Status.AUTHORITY, “information/ids”, SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
DATABASE_INFO_IDS); queryBuilder.setTables(selectedTable);
@Override String sqlQuery = queryBuilder.buildQuery(projection,

public boolean onCreate() { selection, null, null, null, sortOrder, null);


mDB = ((YourApplication) getContext()).getDatabase();
return true; // run query
} try {
return database.rawQuery(sqlQuery, selectionArgs);

You might also like