mobile programming lecture 9

95
Mobile Programming Lecture 9 Bound Service, Location, Sensors, IntentFilter

Upload: felix

Post on 23-Feb-2016

65 views

Category:

Documents


0 download

DESCRIPTION

Mobile Programming Lecture 9. Bound Service, Location, Sensors, IntentFilter. Agenda. Bound Services Location Sensor Starting an Activity for a Result Understanding Implicit Intents. Bound Service. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Mobile Programming Lecture 9

Mobile ProgrammingLecture 9

Bound Service, Location, Sensors, IntentFilter

Page 2: Mobile Programming Lecture 9

Agenda

• Bound Services

• Location

• Sensor

• Starting an Activity for a Result

• Understanding Implicit Intents

Page 3: Mobile Programming Lecture 9

Bound ServiceWhen you create a Bound Service, you must provide an

IBinder that provides the programming interface that clients can use to interact with the Service

There are 3 ways that you can provide this interface:1. Extending the Binder class2. Using a Messenger3. Using AIDL

Page 4: Mobile Programming Lecture 9

Bound Service

Page 5: Mobile Programming Lecture 9

Bound Service - 1 extending Binder

• this is the preferred technique when your service is merely a background worker for your own application

• the only reason you would not create your interface this way is because your service is used by other applications or across separate processes

Page 6: Mobile Programming Lecture 9

Bound Service - 1 extending BinderHere's how to set it up

1. In your service, create an instance of Binder that returns the current Service instance, which has public methods the client can call

2. Return this instance of Binder from the onBind() callback method

3. In the client, receive the Binder from the onServiceConnected() callback method and make calls to the bound service using the methods provided

Page 7: Mobile Programming Lecture 9

Bound Service - 1 extending Binder

see BoundServiceBinderExample.tar

ServiceConnection class monitors the connection between the client and the Service

When a Service is bound, the binder returned is returned to the onServiceConnected() method of ServiceConnection

Page 8: Mobile Programming Lecture 9

Bound Service - 2 using Messenger• if you need your interface to work across different processes, you

can create an interface for the service with a Messenger

• the service defines a Handler that responds to different types of Message objects

• Additionally, the client can define a Messenger of its own so the service can send messages back.

• this is the simplest way to perform interprocess communication (IPC).

Page 9: Mobile Programming Lecture 9

Bound Service - 2 using Messenger

Notice that the handleMessage() method in the Handler is where the service receives the incoming Message and decides what to do, based on the what member.

Page 10: Mobile Programming Lecture 9

Bound Service - 2 using Messenger

see BoundServiceMessengerExample.tar

Page 11: Mobile Programming Lecture 9

Bound Service - 3 using the AIDL

• Using AIDL is confusing

• AIDL isn't used that often

• We won't cover this

Page 12: Mobile Programming Lecture 9

Location Providers

To obtain user location, you can use

• GPSo most accurateo but

consumes battery power fast takes a while to determine location

• Network Location Provider

Page 13: Mobile Programming Lecture 9

Location - LocationManagerRequesting Location Updates

To get the user location, you need to use the LocationManager, which is a system service

• This returns a Location object, which can tell youo latitudeo longitudeo distance between two locations (comparing to another Location object)o accuracy of the Location in meterso direction of travel in degreeso speed of travel in meters per second

The Location, however, does not give you any human readable address such as street name, state, or country

Page 14: Mobile Programming Lecture 9

Requesting Location Updates

• You can use the Location object to obtain a human-readable address by using a Geocoder

• Geocoder can give you a list of addresses (since it may not always be sure because of accuracy issues)o returns a List of Address objects, i.e. List<Address>

street name city state country zip code

Location - Geocoder and Address

Page 15: Mobile Programming Lecture 9

Location - Last Known Location

Requesting Location Updates

Since GPS and Wifi location are not quite instantaeous, you can get the last known location until one of them becomes available

Page 16: Mobile Programming Lecture 9

Location - Last Known Locationfinal LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

getButton = (Button) findViewById(R.id.button1);

tv = (TextView) findViewById(R.id.textView1);

getButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

Location lastLoc = lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

Geocoder geo = new Geocoder(getApplicationContext());

List<Address> addresses;

addresses = geo.getFromLocation(lastLoc.getLatitude(),

lastLoc.getLongitude(), 1);

if(addresses != null)

tv.setText(addresses.get(0).getAddressLine(0));

}

});

Page 17: Mobile Programming Lecture 9

Location - Last Known Locationfinal LocationManager lm = (LocationManager)

getSystemService(Context.LOCATION_SERVICE);getButton = (Button) findViewById(R.id.button1);

tv = (TextView) findViewById(R.id.textView1);

getButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

Location lastLoc = lm.getLastKnownLocation(

LocationManager.NETWORK_PROVIDER);

Geocoder geo = new Geocoder(getApplicationContext());

List<Address> addresses;

addresses = geo.getFromLocation(lastLoc.getLatitude(),

lastLoc.getLongitude(), 1);

if(addresses != null)

tv.setText(addresses.get(0).getAddressLine(0));

}

});

Similar to getting the system service for the DownloadManager

Page 18: Mobile Programming Lecture 9

Location - Last Known Locationfinal LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

getButton = (Button) findViewById(R.id.button1);

tv = (TextView) findViewById(R.id.textView1);

getButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

Location lastLoc = lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

Geocoder geo = new Geocoder(getApplicationContext());

List<Address> addresses;

addresses = geo.getFromLocation(lastLoc.getLatitude(),

lastLoc.getLongitude(), 1);

if(addresses != null)

tv.setText(addresses.get(0).getAddressLine(0));

}

});

What was the last known location?

Page 19: Mobile Programming Lecture 9

Location - Last Known Locationfinal LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

getButton = (Button) findViewById(R.id.button1);

tv = (TextView) findViewById(R.id.textView1);

getButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

Location lastLoc = lm.getLastKnownLocation(

LocationManager.NETWORK_PROVIDER);

Geocoder geo = new Geocoder(getApplicationContext());List<Address> addresses;

addresses = geo.getFromLocation(lastLoc.getLatitude(),

lastLoc.getLongitude(), 1);

if(addresses != null)

tv.setText(addresses.get(0).getAddressLine(0));

}

});

We need to use Geocoder to transform longitude and latitude to an address

Page 20: Mobile Programming Lecture 9

Location - Last Known Locationfinal LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

getButton = (Button) findViewById(R.id.button1);

tv = (TextView) findViewById(R.id.textView1);

getButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

Location lastLoc = lm.getLastKnownLocation(

LocationManager.NETWORK_PROVIDER);

Geocoder geo = new Geocoder(getApplicationContext());

List<Address> addresses;addresses = geo.getFromLocation(lastLoc.getLatitude(),

lastLoc.getLongitude(), 1);

if(addresses != null)

tv.setText(addresses.get(0).getAddressLine(0));

}

});

We will store address here

Page 21: Mobile Programming Lecture 9

Location - Last Known Locationfinal LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

getButton = (Button) findViewById(R.id.button1);

tv = (TextView) findViewById(R.id.textView1);

getButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

Location lastLoc = lm.getLastKnownLocation(

LocationManager.NETWORK_PROVIDER);

Geocoder geo = new Geocoder(getApplicationContext());

List<Address> addresses;

addresses = geo.getFromLocation(lastLoc.getLatitude(), lastLoc.getLongitude(), 1);

if(addresses != null)

tv.setText(addresses.get(0).getAddressLine(0));

}

});

Let's get a List of Addresses (although there may be only 1 sometimes)

Page 22: Mobile Programming Lecture 9

Location - Last Known Locationfinal LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

getButton = (Button) findViewById(R.id.button1);

tv = (TextView) findViewById(R.id.textView1);

getButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

Location lastLoc = lm.getLastKnownLocation(

LocationManager.NETWORK_PROVIDER);

Geocoder geo = new Geocoder(getApplicationContext());

List<Address> addresses;

addresses = geo.getFromLocation(lastLoc.getLatitude(), lastLoc.getLongitude(), 1);

if(addresses != null)

tv.setText(addresses.get(0).getAddressLine(0));

}

});

Pass the latitude ...

Page 23: Mobile Programming Lecture 9

Location - Last Known Locationfinal LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

getButton = (Button) findViewById(R.id.button1);

tv = (TextView) findViewById(R.id.textView1);

getButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

Location lastLoc = lm.getLastKnownLocation(

LocationManager.NETWORK_PROVIDER);

Geocoder geo = new Geocoder(getApplicationContext());

List<Address> addresses;

addresses = geo.getFromLocation(lastLoc.getLatitude(),

lastLoc.getLongitude(), 1);

if(addresses != null)

tv.setText(addresses.get(0).getAddressLine(0));

}

});

the longitude ...

Page 24: Mobile Programming Lecture 9

Location - Last Known Locationfinal LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

getButton = (Button) findViewById(R.id.button1);

tv = (TextView) findViewById(R.id.textView1);

getButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

Location lastLoc = lm.getLastKnownLocation(

LocationManager.NETWORK_PROVIDER);

Geocoder geo = new Geocoder(getApplicationContext());

List<Address> addresses;

addresses = geo.getFromLocation(lastLoc.getLatitude(),

lastLoc.getLongitude(), 1);

if(addresses != null)

tv.setText(addresses.get(0).getAddressLine(0));

}

});

and the max number of addresses that you want to be returned

Page 25: Mobile Programming Lecture 9

Location - Last Known Locationfinal LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

getButton = (Button) findViewById(R.id.button1);

tv = (TextView) findViewById(R.id.textView1);

getButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

Location lastLoc = lm.getLastKnownLocation(

LocationManager.NETWORK_PROVIDER);

Geocoder geo = new Geocoder(getApplicationContext());

List<Address> addresses;

addresses = geo.getFromLocation(lastLoc.getLatitude(),

lastLoc.getLongitude(), 1);

if(addresses != null)

tv.setText(addresses.get(0).getAddressLine(0));}

});

Get the first line of the first address in the list

Page 26: Mobile Programming Lecture 9

Location - Last Known Location

See LastKnownLocationExample.tar

Page 27: Mobile Programming Lecture 9

Location - Location Updates

Requesting Location Updates

• To get actual location updates periodically, you should use a LocationListener

• At some point, you should stop requesting location updates, possibly wheno Activity loses focuso You no longer need the location

Page 28: Mobile Programming Lecture 9

Location - Location Updatesfinal LocationManager lm = (LocationManager) getSystemService(LOCATION_SERVICE);final LocationListener ll = new LocationListener() {

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

@Override public void onProviderEnabled(String provider) {}@Override public void onProviderDisabled(String provider) {}

@Override public void onLocationChanged(Location location) {Geocoder geo = new Geocoder(getApplicationContext());

List<Address> addresses = null;addresses = geo.getFromLocation(location.getLatitude(),

location.getLongitude(), 1);if(addresses != null)

tv.setText(addresses.get(0).getAddressLine(0));

lm.removeUpdates(this);}

};

Page 29: Mobile Programming Lecture 9

Location - Location Updatesfinal LocationManager lm = (LocationManager)

getSystemService(LOCATION_SERVICE);final LocationListener ll = new LocationListener() {

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

@Override public void onProviderDisabled(String provider) {}

@Override public void onLocationChanged(Location location) {Geocoder geo = new Geocoder(getApplicationContext());

List<Address> addresses = null;addresses = geo.getFromLocation(location.getLatitude(),

location.getLongitude(), 1);if(addresses != null)

tv.setText(addresses.get(0).getAddressLine(0));

lm.removeUpdates(this);}

};

We need to register a LocationListener if we want to get updates on the location periodically

Page 30: Mobile Programming Lecture 9

Location - Location Updatesfinal LocationManager lm = (LocationManager)

getSystemService(LOCATION_SERVICE);final LocationListener ll = new LocationListener() {

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

@Override public void onProviderDisabled(String provider) {}

@Override public void onLocationChanged(Location location) {Geocoder geo = new Geocoder(getApplicationContext());

List<Address> addresses = null;addresses = geo.getFromLocation(location.getLatitude(),

location.getLongitude(), 1);if(addresses != null)

tv.setText(addresses.get(0).getAddressLine(0));

lm.removeUpdates(this);}

};

We're forced to override these methods, although we don't use them

Page 31: Mobile Programming Lecture 9

Location - Location Updatesfinal LocationManager lm = (LocationManager)

getSystemService(LOCATION_SERVICE);final LocationListener ll = new LocationListener() {

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

@Override public void onProviderDisabled(String provider) {}

@Override public void onLocationChanged(Location location) {Geocoder geo = new Geocoder(getApplicationContext());

List<Address> addresses = null;addresses = geo.getFromLocation(location.getLatitude(),

location.getLongitude(), 1);if(addresses != null)

tv.setText(addresses.get(0).getAddressLine(0));

lm.removeUpdates(this);}

};

In this callback method is where you code your response to a location change

Page 32: Mobile Programming Lecture 9

Location - Location Updatesfinal LocationManager lm = (LocationManager)

getSystemService(LOCATION_SERVICE);final LocationListener ll = new LocationListener() {

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

@Override public void onProviderDisabled(String provider) {}

@Override public void onLocationChanged(Location location) {Geocoder geo = new Geocoder(getApplicationContext());

List<Address> addresses = null;addresses = geo.getFromLocation(location.getLatitude(),

location.getLongitude(), 1);

if(addresses != null)tv.setText(addresses.get(0).getAddressLine(0));

lm.removeUpdates(this);}

};

Nothing new here ...

Page 33: Mobile Programming Lecture 9

Location - Location Updatesfinal LocationManager lm = (LocationManager)

getSystemService(LOCATION_SERVICE);final LocationListener ll = new LocationListener() {

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

@Override public void onProviderDisabled(String provider) {}@Override public void onLocationChanged(Location location) {

Geocoder geo = new Geocoder(getApplicationContext());List<Address> addresses = null;

addresses = geo.getFromLocation(location.getLatitude(), location.getLongitude(), 1);

if(addresses != null)tv.setText(addresses.get(0).getAddressLine(0));

lm.removeUpdates(this);}

};

Let's save battery life and stop listening for updates, although you may choose to stop listening for updates at some other point if you want to

Page 34: Mobile Programming Lecture 9

Location - Location Updates

See LocationManagerExample.tar

Page 35: Mobile Programming Lecture 9

Location - Permissions

• In order to receive location updates from NETWORK_PROVIDER or GPS_PROVIDER, you must request user permission by declaring one or both of the following permissions

o ACCESS_COARSE_LOCATION (Wifi location)

o ACCESS_FINE_LOCATION (GPS location)

Page 36: Mobile Programming Lecture 9

Location - Mock LocationYou can test your location-based features by mocking

location data in the Emulator

http://developer.android.com/guide/topics/location/obtaining-user-location.html#MockData

The Emulator uses the GPS provider

Found under the Emulator Control View in DDMS, under the Telephony View

Page 37: Mobile Programming Lecture 9

Accellerometer (Motion Sensor)Gyroscope (Motion Sensor)Light (Environment Sensor)Proximity: how close the face of a device is to an object

Pressureand more

See SensorListExample.tar

Sensor

Page 38: Mobile Programming Lecture 9

• SensorManager lets you access the device's sensors. Get an instance of this class by calling Context.getSystemService(SENSOR_SERVICE).

• Always make sure to disable sensors you don't need, especially when your activity is pausedo failing to do so can drain the battery in just a few

hourso the system will not disable sensors automatically

when the screen turns off.

SensorManager

Page 39: Mobile Programming Lecture 9

• The values for each sensor may change at some point

• Set up an Event Listener to take action when these change

• These values can be retrieved from a float values[] array, regardless of the type of Sensor

SensorEvent

Page 40: Mobile Programming Lecture 9

public class SensorExampleActivity extends Activity implements SensorEventListener {

SensorManager mSensorManager;

Sensor mProximity;

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);

mProximity = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);

}

...

}

SensorEvent

Page 41: Mobile Programming Lecture 9

public class SensorExampleActivity extends Activity implements SensorEventListener {

SensorManager mSensorManager;

Sensor mProximity;

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);

mProximity = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);

}

...

}

SensorEvent

Because we want to know when there's a SensorEvent, when values of the Sensor change

Page 42: Mobile Programming Lecture 9

public class SensorExampleActivity extends Activity implements SensorEventListener {

SensorManager mSensorManager;

Sensor mProximity;

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);mProximity = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);

}

...

}

SensorEvent

Similar to how we got the Location service

Page 43: Mobile Programming Lecture 9

public class SensorExampleActivity extends Activity implements SensorEventListener {

SensorManager mSensorManager;

Sensor mProximity;

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);

mProximity = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);}

...

}

SensorEvent

Let's get a Sensor

Page 44: Mobile Programming Lecture 9

public class SensorExampleActivity extends Activity implements SensorEventListener {

SensorManager mSensorManager;

Sensor mProximity;

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);

mProximity = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);

}

...

}

SensorEvent

The Proximity Sensor specifically

Page 45: Mobile Programming Lecture 9

public class SensorExampleActivity extends Activity implements SensorEventListener {

SensorManager mSensorManager;

Sensor mProximity;

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);

mProximity = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);

}

...

}

SensorEvent

The rest of the code for this class on the next slide

Page 46: Mobile Programming Lecture 9

public class SensorExampleActivity extends Activity implements SensorEventListener {

...

protected void onResume() {

super.onResume();

mSensorManager.registerListener(this, mProximity,

SensorManager.SENSOR_DELAY_NORMAL);

}

protected void onPause() {

super.onPause();

mSensorManager.unregisterListener(this);

}

public void onSensorChanged(SensorEvent event) {

Toast.makeText(this, "Proximity = " + event.values[0], Toast.LENGTH_SHORT).show();

}

}

SensorEvent

onCreate() is here somewhere, on the previous page

Page 47: Mobile Programming Lecture 9

public class SensorExampleActivity extends Activity implements SensorEventListener {

...

protected void onResume() {super.onResume();mSensorManager.registerListener(this, mProximity,

SensorManager.SENSOR_DELAY_NORMAL);}

protected void onPause() {

super.onPause();

mSensorManager.unregisterListener(this);

}

public void onSensorChanged(SensorEvent event) {

Toast.makeText(this, "Proximity = " + event.values[0], Toast.LENGTH_SHORT).show();

}

}

SensorEvent

Note that this is onResume()

Page 48: Mobile Programming Lecture 9

public class SensorExampleActivity extends Activity implements SensorEventListener {

...

protected void onResume() {

super.onResume();

mSensorManager.registerListener(this, mProximity,

SensorManager.SENSOR_DELAY_NORMAL);

}

protected void onPause() {

super.onPause();

mSensorManager.unregisterListener(this);

}

public void onSensorChanged(SensorEvent event) {

Toast.makeText(this, "Proximity = " + event.values[0], Toast.LENGTH_SHORT).show();

}

}

SensorEvent

We only want to listen when the Activity is visible in this case, so we do this in onResume()

Page 49: Mobile Programming Lecture 9

public class SensorExampleActivity extends Activity implements SensorEventListener {

...

protected void onResume() {

super.onResume();

mSensorManager.registerListener(this, mProximity,

SensorManager.SENSOR_DELAY_NORMAL);

}

protected void onPause() {

super.onPause();

mSensorManager.unregisterListener(this);

}

public void onSensorChanged(SensorEvent event) {

Toast.makeText(this, "Proximity = " + event.values[0], Toast.LENGTH_SHORT).show();

}

}

SensorEvent

We pass a Context ...

Page 50: Mobile Programming Lecture 9

public class SensorExampleActivity extends Activity implements SensorEventListener {

...

protected void onResume() {

super.onResume();

mSensorManager.registerListener(this, mProximity,

SensorManager.SENSOR_DELAY_NORMAL);

}

protected void onPause() {

super.onPause();

mSensorManager.unregisterListener(this);

}

public void onSensorChanged(SensorEvent event) {

Toast.makeText(this, "Proximity = " + event.values[0], Toast.LENGTH_SHORT).show();

}

}

SensorEvent

a Sensor ...

Page 51: Mobile Programming Lecture 9

public class SensorExampleActivity extends Activity implements SensorEventListener {

...

protected void onResume() {

super.onResume();

mSensorManager.registerListener(this, mProximity,

SensorManager.SENSOR_DELAY_NORMAL);

}

protected void onPause() {

super.onPause();

mSensorManager.unregisterListener(this);

}

public void onSensorChanged(SensorEvent event) {

Toast.makeText(this, "Proximity = " + event.values[0], Toast.LENGTH_SHORT).show();

}

}

SensorEvent

and the rate we want sensor events to be delivered

Page 52: Mobile Programming Lecture 9

public class SensorExampleActivity extends Activity implements SensorEventListener {

...

protected void onResume() {

super.onResume();

mSensorManager.registerListener(this, mProximity,

SensorManager.SENSOR_DELAY_NORMAL);

}

protected void onPause() {

super.onPause();

mSensorManager.unregisterListener(this);}

public void onSensorChanged(SensorEvent event) {

Toast.makeText(this, "Proximity = " + event.values[0], Toast.LENGTH_SHORT).show();

}

}

SensorEvent

in onPause(), we want to stop listening for updates, preserving battery life

Page 53: Mobile Programming Lecture 9

public class SensorExampleActivity extends Activity implements SensorEventListener {

...

protected void onResume() {

super.onResume();

mSensorManager.registerListener(this, mProximity,

SensorManager.SENSOR_DELAY_NORMAL);

}

protected void onPause() {

super.onPause();

mSensorManager.unregisterListener(this);

}

public void onSensorChanged(SensorEvent event) {Toast.makeText(this, "Proximity = " + event.values[0], Toast.LENGTH_SHORT).show();

}

}

SensorEvent

This is where we take action when there is a change in Sensor values

Page 54: Mobile Programming Lecture 9

public class SensorExampleActivity extends Activity implements SensorEventListener {

...

protected void onResume() {

super.onResume();

mSensorManager.registerListener(this, mProximity,

SensorManager.SENSOR_DELAY_NORMAL);

}

protected void onPause() {

super.onPause();

mSensorManager.unregisterListener(this);

}

public void onSensorChanged(SensorEvent event) {

Toast.makeText(this, "Proximity = " + event.values[0], Toast.LENGTH_SHORT).show();

}

}

SensorEvent

event.values[] array has important data about the sensor event

Page 55: Mobile Programming Lecture 9

public class SensorExampleActivity extends Activity implements SensorEventListener {

...

protected void onResume() {

super.onResume();

mSensorManager.registerListener(this, mProximity,

SensorManager.SENSOR_DELAY_NORMAL);

}

protected void onPause() {

super.onPause();

mSensorManager.unregisterListener(this);

}

public void onSensorChanged(SensorEvent event) {

Toast.makeText(this, "Proximity = " + event.values[0], Toast.LENGTH_SHORT).show();

}

}

SensorEvent

Refer to this page for details for each type of Sensor

Page 56: Mobile Programming Lecture 9

• ProximitySensorExample.tar• LightSensorExample.tar

The code change between these two examples is very small

SensorEvent

Page 57: Mobile Programming Lecture 9

Using Sensors to Create a NUI

NUI = Natural User Interface

• Human Computer Interaction is moving further and further away from the mouse and keyboard.o Being replaced by gestures on the device, air

gestures, speech reco, and kinetics.

• There are typically two phases to gesture recognitiono Data Gatheringo Gesture Detection

Page 58: Mobile Programming Lecture 9

Touch

• Using Gesture Detection you can register to listen for touch events on the device.o Long Presso Double Tapo Flingo Pincho Multiple Finger gestures

Page 59: Mobile Programming Lecture 9

Telepathy

• Can think of this gesture as an air gestureo Passing your hand over the device without touching

the screen

• Might think that this would require a front facing camera to process this gesture..o This would be an option but there is an easier way

• Use the Light Sensor to recognize the gestureo and the Proximity Sensor to validate

Page 60: Mobile Programming Lecture 9

Microphone

• Using Speech is a no brainer for NUIo http://developer.android.com/reference/android/spee

ch/RecognizerIntent.html

• A more technical way of using the microphone requires signal processingo Way, way, way outside the scope of this class

Page 61: Mobile Programming Lecture 9

Making Sense of the Data

• Thresholdso check peakso filter peaks too closeo based on count

• Timeo combine with sensor data to get heart rate, for

example

• Statistics are your friendo Since sensors spit out messy and noisy datao Mean, median, mode, range, etc

Page 62: Mobile Programming Lecture 9

Starting Activities & Getting Results

If you created two Activities A and B, you can start B from A, and have B return some result to A

• instead of o startActivity(Intent)

• callo startActivityForResult(Intent, int)

Page 63: Mobile Programming Lecture 9

Starting Activities & Getting Results

private int MY_CODE = 29;

@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);

}

public void startSecondActivity(View v){Intent intent = new Intent(A.this, B.class);startActivityForResult(intent, MY_CODE);

}

Page 64: Mobile Programming Lecture 9

Starting Activities & Getting Results

private int MY_CODE = 29;

@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);

}

public void startSecondActivity(View v){Intent intent = new Intent(A.this, B.class);startActivityForResult(intent, MY_CODE);

}

This code is for Activity A

Page 65: Mobile Programming Lecture 9

Starting Activities & Getting Results

private int MY_CODE = 29;

@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);

}

public void startSecondActivity(View v){Intent intent = new Intent(A.this, B.class);startActivityForResult(intent, MY_CODE);

}

Some number that you want to use to identify your request. #29 is nothing special here.

Page 66: Mobile Programming Lecture 9

Starting Activities & Getting Results

private int MY_CODE = 29;

@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);

}

public void startSecondActivity(View v){Intent intent = new Intent(A.this, B.class);startActivityForResult(intent, MY_CODE);

}

I added a button to the XML and set the android:onClick attribute to this method

Page 67: Mobile Programming Lecture 9

Starting Activities & Getting Results

private int MY_CODE = 29;

@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);

}

public void startSecondActivity(View v){Intent intent = new Intent(A.this, B.class);startActivityForResult(intent, MY_CODE);

}

We have seen this before

Page 68: Mobile Programming Lecture 9

Starting Activities & Getting Results

private int MY_CODE = 29;

@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);

}

public void startSecondActivity(View v){Intent intent = new Intent(A.this, B.class);startActivityForResult(intent, MY_CODE);

}

Instead of startActivity(intent), we call startActivityForResult and give it the intent along with our "special" request code.

Page 69: Mobile Programming Lecture 9

Starting Activities & Getting Results

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

if(requestCode == MY_CODE){if(resultCode == RESULT_OK){

// result is OK, add code here } }}

We also need to add this method to Activity A, to react to when the result has been returned from Activity B.

Page 70: Mobile Programming Lecture 9

Starting Activities & Getting Resultspublic class B extends Activity {

@Overridepublic void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.second);

}

public void finishMe(View v){

setResult(Activity.RESULT_OK, null);finish();

}}

Page 71: Mobile Programming Lecture 9

Starting Activities & Getting Resultspublic class B extends Activity {

@Overridepublic void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.second);

}

public void finishMe(View v){

setResult(Activity.RESULT_OK, null);finish();

}}

This code is for Activity B

Page 72: Mobile Programming Lecture 9

Starting Activities & Getting Resultspublic class B extends Activity {

@Overridepublic void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.second);

}

public void finishMe(View v){

setResult(Activity.RESULT_OK, null);finish();

}}

Assuming there's a Button with android:onClick="finishMe"

Page 73: Mobile Programming Lecture 9

Starting Activities & Getting Resultspublic class B extends Activity {

@Overridepublic void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.second);

}

public void finishMe(View v){

setResult(Activity.RESULT_OK, null);finish();

}}

Set the result of this Activity to OK. The second argument is an Intent, but we'll go in to this another time.

Page 74: Mobile Programming Lecture 9

Starting Activities & Getting Resultspublic class B extends Activity {

@Overridepublic void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.second);

}

public void finishMe(View v){

setResult(Activity.RESULT_OK, null);finish();

}}

Finish this Activity B, which will lead to onDestroy() being called, and Activity A becoming active. onActivityResult() in A will then be called.

Page 75: Mobile Programming Lecture 9

Starting Activities & Getting Results

See StartActivityForResultExample.tar

Page 76: Mobile Programming Lecture 9

Starting Activities & Getting Results

As another example, let's call upon an existing Android Activity for a result

Page 77: Mobile Programming Lecture 9

Starting Activities & Getting Results

static final int PICK_REQUEST = 1337;

@Override public void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);

}

public void pickContact(View v) {Intent intent = new Intent(Intent.ACTION_PICK, Phone.CONTENT_URI);startActivityForResult(intent, PICK_REQUEST);

}

protected void onActivityResult(int requestCode, int resultCode, Intent data) {if (requestCode == PICK_REQUEST) {

if (resultCode == RESULT_OK) {/* result is OK! */

}}

}

Here's our request code again

Page 78: Mobile Programming Lecture 9

Starting Activities & Getting Results

static final int PICK_REQUEST = 1337;

@Override public void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);

}

public void pickContact(View v) {Intent intent = new Intent(Intent.ACTION_PICK, Phone.CONTENT_URI);startActivityForResult(intent, PICK_REQUEST);

}

protected void onActivityResult(int requestCode, int resultCode, Intent data) {if (requestCode == PICK_REQUEST) {

if (resultCode == RESULT_OK) {/* result is OK! */

}}

}

Tied to a Button with android:onClick="pickContact"

Page 79: Mobile Programming Lecture 9

Starting Activities & Getting Results

static final int PICK_REQUEST = 1337;

@Override public void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);

}

public void pickContact(View v) {Intent intent = new Intent(Intent.ACTION_PICK, Phone.CONTENT_URI);startActivityForResult(intent, PICK_REQUEST);

}

protected void onActivityResult(int requestCode, int resultCode, Intent data) {if (requestCode == PICK_REQUEST) {

if (resultCode == RESULT_OK) {/* result is OK! */

}}

}

We use a different constructor for the Intent this time

Page 80: Mobile Programming Lecture 9

Starting Activities & Getting Results

static final int PICK_REQUEST = 1337;

@Override public void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);

}

public void pickContact(View v) {Intent intent = new Intent(Intent.ACTION_PICK, Phone.CONTENT_URI);startActivityForResult(intent, PICK_REQUEST);

}

protected void onActivityResult(int requestCode, int resultCode, Intent data) {if (requestCode == PICK_REQUEST) {

if (resultCode == RESULT_OK) {/* result is OK! */

}}

}

These two arguments must mean something together, they don't always do!

Page 81: Mobile Programming Lecture 9

Starting Activities & Getting Results

static final int PICK_REQUEST = 1337;

@Override public void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);

}

public void pickContact(View v) {Intent intent = new Intent(Intent.ACTION_PICK, Phone.CONTENT_URI);startActivityForResult(intent, PICK_REQUEST);

}

protected void onActivityResult(int requestCode, int resultCode, Intent data) {if (requestCode == PICK_REQUEST) {

if (resultCode == RESULT_OK) {/* result is OK! */

}}

}

There should be an Activity that recognizes this Intent

Page 82: Mobile Programming Lecture 9

Starting Activities & Getting Results

static final int PICK_REQUEST = 1337;

@Override public void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);

}

public void pickContact(View v) {Intent intent = new Intent(Intent.ACTION_PICK, Phone.CONTENT_URI);startActivityForResult(intent, PICK_REQUEST);

}

protected void onActivityResult(int requestCode, int resultCode, Intent data) {if (requestCode == PICK_REQUEST) {

if (resultCode == RESULT_OK) {/* result is OK! */

}}

}

If none exists, you will probably get Force Close

Page 83: Mobile Programming Lecture 9

Starting Activities & Getting Results

static final int PICK_REQUEST = 1337;

@Override public void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);

}

public void pickContact(View v) {Intent intent = new Intent(Intent.ACTION_PICK, Phone.CONTENT_URI);startActivityForResult(intent, PICK_REQUEST);

}

protected void onActivityResult(int requestCode, int resultCode, Intent data) {if (requestCode == PICK_REQUEST) {

if (resultCode == RESULT_OK) {/* result is OK! */

}}

}

Nothing new here

Page 84: Mobile Programming Lecture 9

Starting Activities & Getting Results

static final int PICK_REQUEST = 1337;

@Override public void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);

}

public void pickContact(View v) {Intent intent = new Intent(Intent.ACTION_PICK, Phone.CONTENT_URI);startActivityForResult(intent, PICK_REQUEST);

}

protected void onActivityResult(int requestCode, int resultCode, Intent data) {if (requestCode == PICK_REQUEST) {

if (resultCode == RESULT_OK) {/* result is OK! */

}}

}

That starts Activity B. When Activity B has returned, the result will be returned to this callback function

Page 85: Mobile Programming Lecture 9

Understanding Implicit IntentsImplicit Intents

• �specify the action that should be performed and optionally the URI which should be used in conjunction with the action

Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(“http://www.google.com”));

o The Android system searches for all the components that are registered to handle this specific action

o If the system only finds one component, then it will launch that automatically

o If the system finds more than one component, it will pop up a dialog that will give the user the option of selecting the one they prefer

o If none is found, you may get an Exception.

Page 86: Mobile Programming Lecture 9

Understanding Implicit Intents

Implicit Intents

How do you know which Intent Action to specify for a given Uri?

Page 87: Mobile Programming Lecture 9

Understanding Implicit IntentsThere are three rules, all of which must be true for a given activity to be eligible

for a given intent

1. The activity must support the specified action2. The activity must support the stated MIME type (if supplied)3. The activity must support all of the categories named in the intent

The upshot is that you want to make your intents specific enough to find the right receiver(s), and no more specific than that.

Page 88: Mobile Programming Lecture 9

Understanding Implicit Intents

Let's take a look at what happens when when the Home key is pressed ...

Page 89: Mobile Programming Lecture 9

Understanding Implicit Intents• Open LogCat• Click the + button to add a new filter• Enter the following

o Filter Name: ActivityManagero Log Tag: ActivityManager

• Now press the Home key on your deviceo For the Tag Column, look for ActivityManagero For the Text Column, look for anything beginning with "Starting:

Intent ..." The last one should be the Intent that was used to launch the

home screeno Mouseover that row, and you should see values for the following

act, which is the action - android.intent.action.MAIN cat, which is the category - android.intent.category.HOME in this case, there is no data, but sometimes there is

o Note the action and category

Page 90: Mobile Programming Lecture 9

Understanding Implicit IntentsCan we create our own Home Screen app?

• Create a new project• Open AndroidManifest.xml

o add a new intent-filter to your Activityo the action should match the one you found in LogCato so should the categoryo in addition, add the DEFAULT category

<intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.HOME" /><category android:name="android.intent.category.DEFAULT" />

</intent-filter>

Page 91: Mobile Programming Lecture 9

Understanding Implicit Intents

Now press the Home key ...

For a nicer effect, make your Activity full-screen by adding this to the <activity> tag in the manifest file

android:theme="@android:style/Theme.NoTitleBar.Fullscreen"

Page 92: Mobile Programming Lecture 9

Understanding Implicit Intents

See HomeScreenExample.tar

Page 93: Mobile Programming Lecture 9

Understanding Implicit Intents

It's not too difficult to figure out the Java code for the same Intent:

<intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.HOME" /><category android:name="android.intent.category.DEFAULT" />

</intent-filter>

or

IntentFilter myFilter = new IntentFilter(Intent.ACTION_MAIN);myFilter.addCategory(Intent.CATEGORY_HOME);

Page 94: Mobile Programming Lecture 9

Understanding Implicit Intents

If you make your Intent Filters

• too vague• too specific

it won't match what you expect it to. Try to make your Intent Filters precise!

Page 95: Mobile Programming Lecture 9

References

• The Busy Coder's Guide to Android Development - Mark Murphy

• Android Developers

• The Mobile Lab at Florida State University