|
Cyril Sermon (@admin) |
In the following example, you’ll fill in the code behind the Set up Auto Responder button added in the previous example, to let the Emergency Responder automatically respond to status update requests.
Start by creating a new autoresponder.xml layout resource that will be used to lay out the auto-matic response configuration window. Include an EditText for entering a status message to send, a Spinner to choose the auto-response expiry time, and a CheckBox to let users choose if they want to include their location in the automated responses.
<?xml version=”1.0” encoding=”utf-8”?>
<LinearLayout
xmlns:android=”http://schemas.android.com/apk/res/android”
android:orientation=”vertical”
android:layout_width=”fill_parent”
android:layout_height=”fill_parent”>
<TextView
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”
android:text=”Respond With”/>
<EditText
android:id=”@+id/responseText”
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”/>
<CheckBox
android:id=”@+id/checkboxLocation”
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”
android:text=”Transmit Location”/>
<TextView
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”
android:text=”Auto Respond For”/>
<Spinner
android:id=”@+id/spinnerRespondFor”
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”
android:drawSelectorOnTop=”true”/>
<LinearLayout
xmlns:android=”http://schemas.android.com/apk/res/android”
android:orientation=”horizontal”
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”>
<Button
android:id=”@+id/okButton”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:text=”Enable”/>
<Button
android:id=”@+id/cancelButton”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:text=”Disable”/>
</LinearLayout>
</LinearLayout>
Update the application’s string.xml resource to define a name for an application SharedPreference and strings to use for each of its keys.
<?xml version=”1.0” encoding=”utf-8”?>
<resources>
<string name=”app_name”>Emergency Responder</string>
<string name=”respondAllClearButtonText”>I am Safe and Well</string> <string name=”respondMaydayButtonText”>MAYDAY! MAYDAY! MAYDAY!</string>
<string name=”respondAllClearText”>I am safe and well. Worry not!</string> <string name=”respondMaydayText”>Tell my mother I love her.</string>
<string name=”querystring”>”are you ok?”</string>
<string name=”user_preferences”>com.paad.emergencyresponder.preferences</string> <string name=”includeLocationPref”>PREF_INCLUDE_LOC</string>
<string name=”responseTextPref”>PREF_RESPONSE_TEXT</string> <string name=”autoRespondPref”>PREF_AUTO_RESPOND</string> <string name=”respondForPref”>PREF_RESPOND_FOR</string>
</resources>
You should also take this opportunity to externalize the strings used for labels within the layout.
Then create a new arrays.xml resource, and create arrays to use for populating the Spinner.
<resources>
<string-array name=”respondForDisplayItems”> <item>- Disabled -</item>
<item>Next 5 minutes</item>
<item>Next 15 minutes</item>
<item>Next 30 minutes</item>
<item>Next hour</item>
<item>Next 2 hours</item>
<item>Next 8 hours</item>
</string-array>
<array name=”respondForValues”>
<item>0</item>
<item>5</item>
<item>15</item>
<item>30</item>
<item>60</item>
<item>120</item>
<item>480</item>
</array>
</resources>
Now create a new AutoResponder Activity, populating it with the layout you created in Step 1.
package com.paad.emergencyresponder;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.res.Resources;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.BroadcastReceiver;
import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.os.Bundle; import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Spinner;
public class AutoResponder extends Activity {
@Override
public void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(R.layout.autoresponder);
}
}
Update onCreate further to get references to each of the controls in the layout and wire up the Spinner using the arrays defined in Step 3. Create two new stub methods, savePreferences and updateUIFromPreferences, that will be updated to save the auto-responder settings
to a named SharedPreference and apply the saved SharedPreferences to the current UI, respectively.
Spinner respondForSpinner;
CheckBox locationCheckbox;
EditText responseTextBox;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.autoresponder);
5.1. Start by getting references to each View.
respondForSpinner = (Spinner)findViewById(R.id.spinnerRespondFor); locationCheckbox = (CheckBox)findViewById(R.id.checkboxLocation); responseTextBox = (EditText)findViewById(R.id.responseText);
5.2. Populate the Spinner to let users select the auto-responder expiry time.
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
this,
R.array.respondForDisplayItems,
android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); respondForSpinner.setAdapter(adapter);
5.3. Now wire up the OK and Cancel buttons to let users save or cancel setting changes.
Button okButton = (Button) findViewById(R.id.okButton); okButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
savePreferences();
setResult(RESULT_OK, null);
finish();
}
});
Button cancelButton = (Button) findViewById(R.id.cancelButton); cancelButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
respondForSpinner.setSelection(-1);
savePreferences();
setResult(RESULT_CANCELED, null);
finish();
5.4. Finally, make sure that when the Activity starts, it updates the GUI to represent the cur-rent settings.
Load the saved preferences and update the
UI updateUIFromPreferences();
5.5. Close off the onCreate method, and add the updateUIFromPreferences and savePreferences stubs.
}
private void updateUIFromPreferences() {}
private void savePreferences() {}
Next, complete the two stub methods from Step 5. Start with updateUIFromPreferences; it should read the current saved AutoResponder preferences and apply them to the UI.
private void updateUIFromPreferences() {
// Get the saves settings
String preferenceName = getString(R.string.user_preferences); SharedPreferences sp = getSharedPreferences(preferenceName, 0);
boolean autoRespond = sp.getBoolean(getString(R.string.autoRespondPref), false); String respondText = sp.getString(getString(R.string.responseTextPref), “”); boolean includeLoc = sp.getBoolean(getString(R.string.includeLocationPref),
false);
int respondForIndex = sp.getInt(getString(R.string.respondForPref), 0);
Apply the saved settings to the UI if (autoRespond)
respondForSpinner.setSelection(respondForIndex); else
respondForSpinner.setSelection(0);
locationCheckbox.setChecked(includeLoc);
responseTextBox.setText(respondText);
}
Complete the savePreferences stub to save the current UI settings to a Shared Preferences file.
private void savePreferences() {
// Get the current settings from the UI
boolean autoRespond = respondForSpinner.getSelectedItemPosition() > 0; int respondForIndex = respondForSpinner.getSelectedItemPosition(); boolean includeLoc = locationCheckbox.isChecked();
String respondText = responseTextBox.getText().toString();
// Save them to the Shared Preference file
String preferenceName = getString(R.string.user_preferences); SharedPreferences sp = getSharedPreferences(preferenceName, 0);
Editor editor = sp.edit();
editor.putBoolean(getString(R.string.autoRespondPref), autoRespond); editor.putString(getString(R.string.responseTextPref), respondText); editor.putBoolean(getString(R.string.includeLocationPref), includeLoc ); editor.putInt(getString(R.string.respondForPref), respondForIndex ); editor.commit();
Set the alarm to turn off the autoresponder setAlarm(respondForIndex);
}
private void setAlarm(int respondForIndex) {}
The setAlarm stub from Step 8 is used to create a new Alarm that fires an Intent that should result in the AutoResponder being disabled.
You’ll need to create a new Alarm object and a BroadcastReceiver that listens for it before disabling the auto-responder accordingly.
8.1. Start by creating the action String that will represent the Alarm Intent.
public static final String alarmAction = “com.paad.emergencyresponder.AUTO_RESPONSE_EXPIRED”;
8.2. Then create a new Broadcast Receiver instance that listens for an Intent that includes the action specified in Step 7. When this Intent is received, it should modify the auto-responder settings to disable the automatic response.
private BroadcastReceiver stopAutoResponderReceiver = new BroadcastReceiver() { @Override
public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(alarmAction)) {
String preferenceName = getString(R.string.user_preferences); SharedPreferences sp = getSharedPreferences(preferenceName, 0);
Editor editor = sp.edit();
editor.putBoolean(getString(R.string.autoRespondPref), false);
editor.commit();
}
}
};
8.3. Finally, complete the setAlarm method. It should cancel the existing alarm if the auto-responder is turned off; otherwise, it should update it with the latest expiry time.
PendingIntent intentToFire;
private void setAlarm(int respondForIndex) {
Create the alarm and register the alarm intent receiver. AlarmManager alarms = (AlarmManager)getSystemService(ALARM_SERVICE);
if (intentToFire == null) {
Intent intent = new Intent(alarmAction);
intentToFire = PendingIntent.getBroadcast(getApplicationContext(), 0,intent,0);
IntentFilter filter = new IntentFilter(alarmAction);
registerReceiver(stopAutoResponderReceiver, filter);
}
if (respondForIndex < 1)
If “disabled” is selected, cancel the alarm. alarms.cancel(intentToFire);
else {
Otherwise find the length of time represented by the selection and
and set the alarm to trigger after that time has passed.
Resources r = getResources();
int[] respondForValues = r.getIntArray(R.array.respondForValues); int respondFor = respondForValues [respondForIndex];
long t = System.currentTimeMillis();
t = t + respondFor*1000*60;
// Set the alarm.
alarms.set(AlarmManager.RTC_WAKEUP, t, intentToFire);
}
}
That completes the AutoResponder, but before you can use it, you’ll need to add it to your application manifest.
<?xml version=”1.0” encoding=”utf-8”?>
<manifest
xmlns:android=”http://schemas.android.com/apk/res/android” package=”com.paad.emergencyresponder”> <application
android:icon=”@drawable/icon”
android:label=”@string/app_name”>
<activity
android:name=”.EmergencyResponder”
android:label=”@string/app_name”>
<intent-filter>
<action android:name=”android.intent.action.MAIN” /> <category android:name=”android.intent.category.LAUNCHER” />
</intent-filter>
</activity>
<activity
android:name=”.AutoResponder”
android:label=”Auto Responder Setup”/>
</application>
<uses-permission android:name=”android.permission.ACCESS_GPS”/> <uses-permission android:name=”android.permission.ACCESS_LOCATION”/> <uses-permission android:name=”android.permission.RECEIVE_SMS”/> <uses-permission android:name=”android.permission.SEND_SMS”/>
</manifest>
To enable the auto-responder, return to the Emergency Responder Activity and update the startAutoResponder method stub that you created in the previous example. It should open the AutoResponder Activity you just created.
private void startAutoResponder() { startActivityForResult(new Intent(EmergencyResponder.this,
AutoResponder.class), 0);
}
If you start your project, you should now be able to bring up the Auto Responder settings win-dow to set the auto-response settings. It should appear as shown in Figure 9-5.
The final step is to update the requestReceived method in the Emergency Responder Activity to check if the auto-responder has been enabled.
If it has, the requestReceived method should automatically execute the respond method, using the message and location settings defined in the application’s SharedPreferences.
public void requestReceived(String _from) {
if (!requesters.contains(_from)) {
lock.lock();
requesters.add(_from);
aa.notifyDataSetChanged();
lock.unlock();
// Check for auto-responder
String preferenceName = getString(R.string.user_preferences); SharedPreferences prefs = getSharedPreferences(preferenceName, 0);
String autoRespondPref = getString(R.string.autoRespondPref) boolean autoRespond = prefs.getBoolean(autoRespondPref, false);
if (autoRespond) {
String responseTextPref = getString(R.string.responseTextPref); String includeLocationPref = getString(R.string.includeLocationPref);
String respondText = prefs.getString(responseTextPref, “”);
boolean includeLoc = prefs.getBoolean(includeLocationPref, false);
respond(_from, respondText, includeLoc);
}
}
}
You should now have a fully functional interactive and automated emergency responder.
You can test it in the same way as described in the previous example by using a second emulator instance to receive the response messages, and the emulator controls to send the requests for status updates.
Summar y
Technologies like SMS and instant messaging are providing an increasingly versatile platform for per-son-to-person communication.
Android lets you use these text-based communication channels to create applications that let users send messages using instant messengers and SMS texts, as well as supplying an invisible data conduit for your applications to exchange data between devices.
In this chapter, you learned how to connect to IM Sessions using the GTalk Service and how to send and receive text and data messages using these sessions. You learned about presence, how to set your own presence, and how to find the presence of the contacts on the IM roster.
You also used the SMS Manager to send and receive text and data messages from your applications.
This chapter also showed you how future SDK release may allow you to:
❑Add and remove instant messaging contacts.
❑ Block contacts and monitor the roster for changes. ❑ Manage group chats and chat rooms.
Chapter 10 explores access to the low-level mobile hardware.
Using the phone’s telephony services, you’ll initiate new calls and monitor both outgoing and incoming calls. You’ll be introduced to Android’s multimedia capabilities and use the media API to play back and record a variety of media resources.
You’ll also learn how to interact with the Sensor Manager to access the compass and accelerometer before investigating network management using the Wi-Fi and Bluetooth APIs.