2013/2/11
一,发送SMS
--介绍如何在应用里面发送信息。
1.1发送信息
首先要在AndroidManifest中添加一个许可:
<uses-permissionandroid:name=”android.permission.SEND_SMS”/>
这样当应用被安装的时候,就会提示此应用可能会发送SMS信息。
在应用中发送信息,可以用SmsManager类:
private voidsendSMS(String phoneNumber, String message)
{
SmsManager sms = SmsManager.getDefault();
sms.sendTextMessage(phoneNumber, null, message, null, null);
}
这里首先用SmsManager的getDefault()方法来获得一个SmsManager对象,之后就可以用其sendTextMessage方法来发送信息了。
这个方法有五个参数:
➤ destinationAddress— Phone number of the recipient
➤ scAddress— Service center address; use nullfor default SMSC
➤ text— Content of the SMS message
➤ sentIntent— Pending intent to invoke when the message is sent (discussed in more detail in the
next section)
➤ deliveryIntent— Pending intent to invoke when the message has been delivered (discussed in
more detail in the next section)
➤ scAddress— Service center address; use nullfor default SMSC
➤ text— Content of the SMS message
➤ sentIntent— Pending intent to invoke when the message is sent (discussed in more detail in the
next section)
➤ deliveryIntent— Pending intent to invoke when the message has been delivered (discussed in
more detail in the next section)
1.2 发送信息后获得回应
--发送信息后,可能会马上成功,可能会要延迟,这里示范发送信息后返回结果。
首先,用PendingIntent对象来代表延迟和发送成功:
sentPI= PendingIntent.getBroadcast(this, 0,
newIntent(SENT), 0);
deliveredPI= PendingIntent.getBroadcast(this, 0,
newIntent(DELIVERED), 0);
这里第一个表示已发送,第二个表示发送成功。然后向活动注册两个监听器,用于监听上面两个事件(sent和delivered)的发生:
registerReceiver(smsDeliveredReceiver, new IntentFilter(DELIVERED));
registerReceiver(smsSentReceiver, new IntentFilter(SENT));
里面的smsDeliveredReceiver和smsSentReceiver是用于响应对应的事件(一个是DElivered事件,另一个是sent事件)的监听器。具体实现可由实际情况而定。
最后将两个PendingIntent作为最后两个参数传入sendTextMessage:
SmsManager sms = SmsManager.getDefault();
sms.sendTextMessage(phoneNumber, null, message, sentPI, deliveredPI);
这样,无论信息发送成功与否,都会通过PendingIntent通知用户。
1.3用intent来发送信息
除了可以用SmsManager来发送信息外,还可以用内置的发送信息方法来发送信息:Intent i = new
Intent(android.content.Intent.ACTION_VIEW);
i.putExtra(“address”, “5556; 5558; 5560”);
i.putExtra(“sms_body”, “Hello my friends!”);
i.setType(“vnd.android-dir/mms-sms”);
startActivity(i);
用一个intent对象 加上设置类型为
vnd.android-dir/mms-sms
设置好address和sms_body,就可以调用内置的发送信息功能。
二,接受信息
--可以在应用中用BroadcastReceiver对象来接收SMS,这样可以让你的应用在接受到特定信息的时候触发特定的功能。
2.1接收信息,用broadcastreceiver。
首先要在AndroidManifest中添加许可:
<uses-permissionandroid:name=”android.permission.RECEIVE_SMS”/>
和指定broadcastreceiver的名字:
<receiver android:name=”.SMSReceiver”>
<intent-filter>
<actionandroid:name=
“android.provider.Telephony.SMS_RECEIVED” />
</intent-filter>
</receiver>
为了监听是否有短信收到,可以用 BroadcastReceiver类,这个类可以接受被的应用以sentBoardcast方法发送的intent对象。也就是说,当别的应用以调用sentBoardcast发送intent的时候,这个类就可以接受到。当接受到某个intent对象的时候,这个类的onReceive方法就会被调用。于是你可以重写这个方法来实现你需要的功能:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.util.Log;
import android.widget.Toast;
public class SMSReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{ Bundle bundle = intent.getExtras();
SmsMessage[] msgs = null;
String str = “SMS from “;
if(bundle != null)
SMS Messaging
{ Object[] pdus = (Object[]) bundle.get(“pdus”);
msgs = new SmsMessage[pdus.length];
for(inti=0; i<msgs.length; i++){
msgs[i] = SmsMessage.createFromPdu((byte[])pdus[i]);
if(i==0) { str += msgs[i].getOriginatingAddress();
str += “: “;
}
str += msgs[i].getMessageBody().toString();
}
Toast.makeText(context, str, Toast.LENGTH_SHORT).show();
Log.d(“SMSReceiver”, str);
}
}
}
这个类继承了BoardcastReceiver类。当sms到来的时候,里面的onReceive方法就会被调用,而且信息的相关内容包含在接受到的intent对象里面。Intent里面包含一个bundle对象,这个就是信息的实体了。
每一个信息对象都是存储在一个PDU 格式的object数组里面,当信息大于160个字符的时候,信息就会被存储在数组里面的多个对象中。用SmsManager类的静态方法
createFromPdu,传入从bundle中获取的object数组(object [])就可以获得包含信息内容的一个SmsManager对象(大于160个字的话多余一个,于是这里用了SmsManager数组)。
createFromPdu,传入从bundle中获取的object数组(object [])就可以获得包含信息内容的一个SmsManager对象(大于160个字的话多余一个,于是这里用了SmsManager数组)。
用getOriginatingAddress方法可以获得发送人的地址。而用getMessageBody方法则可以获得信息的内容。
这个时候,当一条信息发送过来,系统内置的信息工具和你定义的应用都会对信息进行响应。你也可以阻止系统内置的信息工具接受信息。只需要在内置的信息管理工具接受之前把这个信息的intent接受并处理掉即可:
<receiverandroid:name=”.SMSReceiver”>
<intent-filter android:priority=”100”>
<actionandroid:name=
“android.provider.Telephony.SMS_RECEIVED” />
</intent-filter>
</receiver>
这里添加了一个priority属性:属性值越高,就越先处理到信息。然后当你的应用处理完这个信息之后,添加一句this.abortBroadcast(); 就可以防止这个信息继续被其他程序接受。
2.2用BoardcastReceiver来更新活动
--上面中我们把接收到的信息用toast类来显示出来,你可能需要将信息内容显示在一个控件(如:Textview)里面。以下例子展示了怎么做。
我们把SMSreceiver如下设置:
package net.learn2develop.SMS;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.util.Log;
import android.widget.Toast;
public class SMSReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
//---get the SMS message passed in---
Bundle bundle = intent.getExtras();
SmsMessage[] msgs = null;
String str = "SMS from ";
if (bundle != null)
{
//---retrieve the SMS message received---
Object[] pdus = (Object[]) bundle.get("pdus");
msgs = new SmsMessage[pdus.length];
for (int i=0; i<msgs.length; i++){
msgs[i] = SmsMessage.createFromPdu((byte[])pdus[i]);
if (i==0) {
//---get the sender address/phone number---
str += msgs[i].getOriginatingAddress();
str += ": ";
}
//---get the message body---
str += msgs[i].getMessageBody().toString();
}
//---display the new SMS message---
Toast.makeText(context, str, Toast.LENGTH_SHORT).show();
Log.d("SMSReceiver", str);
//---stop the SMS message from being broadcasted---
this.abortBroadcast();
//---launch the SMSActivity---
//---send a broadcast intent to update the SMS received in the activity---
Intent broadcastIntent = new Intent();
broadcastIntent.setAction("SMS_RECEIVED_ACTION");
broadcastIntent.putExtra("sms", str);
context.sendBroadcast(broadcastIntent);
}
}
}
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.util.Log;
import android.widget.Toast;
public class SMSReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
//---get the SMS message passed in---
Bundle bundle = intent.getExtras();
SmsMessage[] msgs = null;
String str = "SMS from ";
if (bundle != null)
{
//---retrieve the SMS message received---
Object[] pdus = (Object[]) bundle.get("pdus");
msgs = new SmsMessage[pdus.length];
for (int i=0; i<msgs.length; i++){
msgs[i] = SmsMessage.createFromPdu((byte[])pdus[i]);
if (i==0) {
//---get the sender address/phone number---
str += msgs[i].getOriginatingAddress();
str += ": ";
}
//---get the message body---
str += msgs[i].getMessageBody().toString();
}
//---display the new SMS message---
Toast.makeText(context, str, Toast.LENGTH_SHORT).show();
Log.d("SMSReceiver", str);
//---stop the SMS message from being broadcasted---
this.abortBroadcast();
//---launch the SMSActivity---
//---send a broadcast intent to update the SMS received in the activity---
Intent broadcastIntent = new Intent();
broadcastIntent.setAction("SMS_RECEIVED_ACTION");
broadcastIntent.putExtra("sms", str);
context.sendBroadcast(broadcastIntent);
}
}
}
注意,上面提到,当接受到短信之后,继承了BoardcastReceiver的SMSreceiver的onReceive方法就会被调用。当处理了短信信息之后,onReceive会另外send出另外一个broadcastintent:
Intent broadcastIntent = new Intent();
broadcastIntent.setAction(“SMS_RECEIVED_ACTION”);
broadcastIntent.putExtra(“sms”, str);
context.sendBroadcast(broadcastIntent);
这里设置了setAction和加入了一个额外内容(putExtra方法)。这就让设置了接受这个intent的其他应用可以接受到(这里是同一个应用)。
然后我们设置一个broadcastReceiver来接受这个intent信号:
privateBroadcastReceiver intentReceiver= new BroadcastReceiver() {
@Override
public voidonReceive(Context context, Intent intent) {
//---display the SMS received in the TextView--- TextView SMSes = (TextView) findViewById(R.id.textView1);
SMSes.setText(intent.getExtras().getString(“sms”));
}
};
这个broadcastreceiver接受了我们在第一步中发出的intent(里面有信息的内容),然后将内容设置到Textview上面去。
为了让这个broadcastreceiver不至于接受所有的intent(上面提到,当一个信息接受到的时候,broadcastreceiver也会接受到一个带有信息内容的intent,而现在的这个intent是我们另外发出的)。所有要设置一个intentfilter,从而是这个broadcastreceiver监听特定的Intent:
intentFilter= new IntentFilter();
intentFilter.addAction(“SMS_RECEIVED_ACTION”);
最后,我们将这一对的broadcastreceiver和intentfilter都注册到主活动中:
registerReceiver(intentReceiver, intentFilter);
这样当一个信息被接受的时候,我们的活动就会broadcast出另外一个intent,让它自己接收到。最后设置到Textview中。
2.3接受信息的同时将活动带到前台。
--只需要在SMSreceiver(继承于broadcastreceiver)的onReceive中,发送另外一个Intent之前加上:
Intent mainActivityIntent = new Intent(context, SMSActivity.class);
mainActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(mainActivityIntent);
这段代码就会在接收到信息之后,将活动(原来在后台)从新带到前台。注意在活动之外调用活动,你需要setFlags为Intent.FLAG_ACTIVITY_NEW_TASK.
然后再在AndroidManifest中设置:
<activity
android:label=”@string/app_name”
android:name=”.SMSActivity”
android:launchMode=”singleTask” >
如果不设置launchMode为singleTask,那么接受到多个信息的时候就会打开多次活动。
三,发送邮件
当然也可以在应用中编程式的发送邮件:
启动邮件的Activity,也是用intent对象,只需要设置好各种信息即可:
Intent emailIntent = newIntent(Intent.ACTION_SEND);
emailIntent.setData(Uri.parse(“mailto:”));
String [] to = emailAddresses;
String [] cc = carbonCopies;
emailIntent.putExtra(Intent.EXTRA_EMAIL, to);
emailIntent.putExtra(Intent.EXTRA_CC, cc);
emailIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
emailIntent.putExtra(Intent.EXTRA_TEXT, message);
emailIntent.setType(“message/rfc822”);
startActivity(Intent.createChooser(emailIntent, “Email”));
emailIntent.setData(Uri.parse(“mailto:”));
String [] to = emailAddresses;
String [] cc = carbonCopies;
emailIntent.putExtra(Intent.EXTRA_EMAIL, to);
emailIntent.putExtra(Intent.EXTRA_CC, cc);
emailIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
emailIntent.putExtra(Intent.EXTRA_TEXT, message);
emailIntent.setType(“message/rfc822”);
startActivity(Intent.createChooser(emailIntent, “Email”));
2013/2/21