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

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

Transcript of Mobile Programming Lecture 9 Bound Service, Location, Sensors, IntentFilter.

Mobile ProgrammingLecture 9

Bound Service, Location, Sensors, IntentFilter

Agenda

• Bound Services

• Location

• Sensor

• Starting an Activity for a Result

• Understanding Implicit Intents

Bound Service

When 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 class

2. Using a Messenger

3. Using AIDL

Bound Service

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

Bound Service - 1 extending Binder

Here'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

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

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).

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.

Bound Service - 2 using Messenger

see BoundServiceMessengerExample.tar

Bound Service - 3 using the AIDL

• Using AIDL is confusing

• AIDL isn't used that often

• We won't cover this

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

Location - LocationManager

Requesting 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

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

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

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));

}

});

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

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?

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

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

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)

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 ...

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 ...

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

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

Location - Last Known Location

See LastKnownLocationExample.tar

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

Location - Location Updates

final 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);

}

};

Location - Location Updates

final 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

Location - Location Updates

final 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

Location - Location Updates

final 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

Location - Location Updates

final 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 ...

Location - Location Updates

final 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

Location - Location Updates

See LocationManagerExample.tar

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)

Location - Mock Location

You 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

Accellerometer (Motion Sensor)

Gyroscope (Motion Sensor)

Light (Environment Sensor)

Proximity: how close the face of a device is to an object

Pressure

and more

See SensorListExample.tar

Sensor

• 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

• 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

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

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

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

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

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

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

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

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()

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()

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 ...

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 ...

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

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

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

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

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

• ProximitySensorExample.tar

• LightSensorExample.tar

The code change between these two examples is very small

SensorEvent

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

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

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

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

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

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)

Starting Activities & Getting Results

private int MY_CODE = 29;

@Override

public 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);

}

Starting Activities & Getting Results

private int MY_CODE = 29;

@Override

public 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

Starting Activities & Getting Results

private int MY_CODE = 29;

@Override

public 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.

Starting Activities & Getting Results

private int MY_CODE = 29;

@Override

public 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

Starting Activities & Getting Results

private int MY_CODE = 29;

@Override

public 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

Starting Activities & Getting Results

private int MY_CODE = 29;

@Override

public 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.

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.

Starting Activities & Getting Results

public class B extends Activity {

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.second);

}

public void finishMe(View v)

{

setResult(Activity.RESULT_OK, null);

finish();

}

}

Starting Activities & Getting Results

public class B extends Activity {

@Override

public 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

Starting Activities & Getting Results

public class B extends Activity {

@Override

public 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"

Starting Activities & Getting Results

public class B extends Activity {

@Override

public 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.

Starting Activities & Getting Results

public class B extends Activity {

@Override

public 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.

Starting Activities & Getting Results

See StartActivityForResultExample.tar

Starting Activities & Getting Results

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

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

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"

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

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!

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

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

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

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

Understanding Implicit Intents

Implicit 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.

Understanding Implicit Intents

Implicit Intents

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

Understanding Implicit Intents

There 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.

Understanding Implicit Intents

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

Understanding Implicit Intents

• Open LogCat

• Click the + button to add a new filter

• Enter the followingo 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

Understanding Implicit Intents

Can we create our own Home Screen app?

• Create a new project

• Open AndroidManifest.xmlo 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>

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"

Understanding Implicit Intents

See HomeScreenExample.tar

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);

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!

References

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

• Android Developers

• The Mobile Lab at Florida State University