960 likes | 1.15k Views
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.
E N D
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 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: • Extending the Binder class • Using a Messenger • Using AIDL
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 • In your service, create an instance of Binder thatreturns the current Service instance, which has public methods the client can call • Return this instance of Binder from the onBind() callback method • 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 • GPS • most accurate • 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 you • latitude • longitude • distance between two locations (comparing to another Location object) • accuracy of the Location in meters • direction of travel in degrees • 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
Location - Geocoder and Address 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) • returns a List of Address objects, i.e. List<Address> • street name • city • state • country • zip code
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 Location final 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 Location final 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 Location final 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 Location final 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 Location final 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 Location final 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 Location final 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 Location final 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 Location final 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 Location final 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 when • Activity loses focus • 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 • ACCESS_COARSE_LOCATION • (Wifi location) • 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
Sensor 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
SensorManager • 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 paused • failing to do so can drain the battery in just a few hours • the system will not disable sensors automatically when the screen turns off.
SensorEvent • 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); } ... } Because we want to know when there's a SensorEvent, when values of the Sensor change
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); } ... } Similar to how we got the Location service
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); } ... } Let's get a 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); } ... } The Proximity Sensor specifically
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); } ... } The rest of the code for this class on the next slide
SensorEvent 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(); } } onCreate() is here somewhere, on the previous page
SensorEvent 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(); } } Note that this is onResume()
SensorEvent 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(); } } We only want to listen when the Activity is visible in this case, so we do this in onResume()
SensorEvent 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(); } } We pass a Context ...
SensorEvent 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(); } } a Sensor ...