mobile programming lecture 9
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 PresentationTRANSCRIPT
Mobile ProgrammingLecture 9
Bound Service, Location, Sensors, IntentFilter
Agenda
• Bound Services
• Location
• Sensor
• Starting an Activity for a Result
• Understanding Implicit Intents
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
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 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
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 - 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
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 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);}
};
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
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
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
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 ...
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
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 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
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
• 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;
@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);
}
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
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.
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
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
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.
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 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();
}}
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
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"
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.
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.
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 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.
Understanding Implicit Intents
Implicit Intents
How do you know which Intent Action to specify for a given Uri?
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.
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 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
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>
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