现在,用户可以在应用的preferences中保存输入的密码了,接下来,我们将要检查手机接收到的短信,并且对我们感兴趣的短信做出响应。这种短信的格式为:
SMSLOCATE:<password>
因此,如果某条短信以“SMSLOCATE:”开头,并且紧跟‘:’字符后面的密码的MD5和我们先前存储的匹配,我们将回复一条包含手机当前位置信息的短信。为了实现这一目的,我们需要建立一个IntentReceiver,响应类型为“android.provider.Telephony.SMS_RECEIVED”的Action。该IntentReceiver必须在AndroidManifest.xml 文件中声明,以下是AndroidManifest.xml 文件:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas./apk/res/android"
package="com.helloandroid.android.phonefinder">
<uses-permission id="android.permission.RECEIVE_SMS" />
<application android:icon="@drawable/icon">
<activity class=".PhoneFinder" android:label="@string/app_name">
<intent-filter>
<action android:value="android.intent.action.MAIN" />
<category android:value="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver class=".FinderReceiver">
<intent-filter>
<action android:value="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
</application>
</manifest>
在第4行,通过<uses-permission>标签,我们请求接收短信的权限。在第13行,我们指定我们的FinderReceiver作为一个receiver,同时声明了intent-filter,以此来过滤被广播的所有intent。你可以看到,我们只对“android.provider.Telephony.SMS_RECEIVED”这类action感兴趣。
现在,系统知道了对于这类action,该调用何种receiver。接下来我们来创建名为FinderReceiver的IntentReceiver。
public class FinderReceiver extends IntentReceiver {
@Override
public void onReceiveIntent(Context context, Intent intent) {
SharedPreferences passwdfile = context.getSharedPreferences(
PhoneFinder.PASSWORD_PREF_KEY, 0);
String correctMd5 = passwdfile.getString(PhoneFinder.PASSWORD_PREF_KEY,
null);
if (correctMd5 != null) {
SmsMessage[] messages = Telephony.Sms.Intents
.getMessagesFromIntent(intent);
for (SmsMessage msg : messages) {
if (msg.getMessageBody().contains("SMSLOCATE:")) {
String[] tokens = msg.getMessageBody().split(":");
if (tokens.length >= 2) {
String md5hash = PhoneFinder.getMd5Hash(tokens[1]);
if (md5hash.equals(correctMd5)) {
String to = msg.getOriginatingAddress();
LocationManager lm =
(LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
SmsManager sm = SmsManager.getDefault();
sm.sendTextMessage(to, null, lm.getCurrentLocation("gps").toString(),
null, null, null);
NotificationManager nm =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
nm.notifyWithText(R.layout.main,
context.getText(R.string.notify_text) + " " + msg.getDisplayOriginatingAddress(),
NotificationManager.LENGTH_LONG, null);
}
}
}
}
}
}
}
首先,我们从SharedPreferences取出密码的MD5(18-21行),如果我们取到了,我们就用它来检查我们接收到的所有的短信。 我们使用Telphony.Sms.Intents.getMessageFromInent(intent)来获取SmsMessages数组,我们将遍历该数组,查看每条短信消息体中是否包含“SMSLOCATE:”标记,如果找到符合条件的短消息,我们会获取‘:’字符后的密码,计算其MD5,和手机里存储的MD5进行比较。 如果密码匹配,系统会执行第36行处的代码块。接下来我们将回复该短信,现在我们只需要一个代表短信目的地的字符串,以及代表手机位置信息的字符串。我们创建一个LocationManager,使用其getCurrentLocation("gps").toString()方法来获取位置信息。该信息由GPS位置服务提供者提供。然后,我们使用一个SmsManager对象发送短信。短信发送完毕后,我们还会显示一个通知。 注意:有一个可能更好做法是,在密码输入对话框中加入一个可选项来控制是否显示通知。如果手机被偷,最好把通知隐藏起来,否则小偷会意识到自己被跟踪,从而把手机关掉。
测试
现在,万事俱备。在新版的android SDK中,给模拟器打电话或者发短信都很容易。这些操作都可以通过Eclipse中的模拟器控制面板视图来完成。你可以通过“"Window -> Show View -> Other”,选择android部分的“Emulator Control”项来增加这个视图。 译者注:如果你的android Eclipse插件为ADT0.3.1,请务必升级到ADT0.3.3,升级步骤见 http://code.google.com/android/intro/upgrading.html 测试的第一步是激活主Activity,设置密码。例如,我使用“123456”作为密码,接下来,你可以发送一条内容为“SMSLOCATE:123456”的短信,如下图所示:
好了,一切OK。我想,这是一个很好的例子。通过它,你会发现在android平台上开发一个有用的应用是多么的容易。我们通过2个基本的对象就完成了一件非常有用的任务。