Android开发手记(15) 拨打电话和收发短信
1、Intent简介
Android组价之间的通信,由Intent来协助完成。Intent负责对应用中一次操作的动作、动作涉及数据、附加数据进行描述,Android则根据此Intent的描述,负责找到对应的组件,将 Intent传递给调用的组件,并完成组件的调用。
Intent可以启动一个Activity,也可以启动一个Service,还可以发起一个广播Broadcasts。分别通过startActivity();startService();startBroadcasts();来执行操作。
在使用Android的电话功能的时候,我们需要调用Intent的相关功能来实现拨打电话和收发短信。
2、URI
URI是统一资源标识符(Uniform Resource Identifier)的缩写。是一个用于标识某一互联网资源名称的字符串。 该种标识允许用户对任何(包括本地和互联网)的资源通过特定的协议进行交互操作。URI由包括确定语法和相关协议的方案所定义。在Android中URI的意义非常重大,他是所有资源的标示符(ID),通过URI可找到一个对应的具体实体,如文件(file),数据库的表项(content)等,可以说贯穿整个Framework。
URI一般的格式为:[scheme:]schemeSpecificPart[#fragment] ([...]表示可选)
3、拨打电话
直接拨打电话需要添加android.permission.CALL_PHONE权限,在AndroidManifest.xml中添加如下代码:
<uses-permission android:name="android.permission.CALL_PHONE"/>
完整代码为:
1 <?xml version="1.0" encoding="utf-8"?> 2 <manifest xmlns:android="http://schemas.android.com/apk/res/android" 3 package="com.example.doodle.button" > 4 5 <application 6 android:allowBackup="true" 7 android:icon="@mipmap/ic_launcher" 8 android:label="@string/app_name" 9 android:theme="@style/AppTheme" > 10 <activity 11 android:name=".MainActivity" 12 android:label="@string/app_name" > 13 <intent-filter> 14 <action android:name="android.intent.action.MAIN" /> 15 16 <category android:name="android.intent.category.LAUNCHER" /> 17 </intent-filter> 18 </activity> 19 </application> 20 21 <uses-permission android:name="android.permission.CALL_PHONE"/> 22 23 </manifest>
然后,我们实例化一个Uri,其内容为要拨打电话的命令。电话号码通过TextView获得。然后我们实例化一个Intent,设置Intent的行为为“直接拨打电话”,Intent的数据为“拨打XXX电话命令”。
1 Uri uri = Uri.parse("tel:" + tvPhone.getText()); 2 Intent intent = new Intent(); 3 intent.setAction(Intent.ACTION_CALL); 4 intent.setData(uri);
然后为拨打电话按钮添加此单击事件即可
1 btnDriect.setOnClickListener(new View.OnClickListener() { 2 @Override 3 public void onClick(View view) { 4 Uri uri = Uri.parse("tel:" + tvPhone.getText()); 5 Intent intent = new Intent(); 6 intent.setAction(Intent.ACTION_CALL); 7 intent.setData(uri); 8 startActivity(intent); 9 } 10 });
同理,我们可以通过Intent来启动系统自带的拨号器。启动系统自带的拨号器是不需要android.permission.CALL_PHONE权限的。
1 btnSystem.setOnClickListener(new View.OnClickListener() { 2 @Override 3 public void onClick(View view) { 4 Uri uri = Uri.parse("tel:" + tvPhone.getText()); 5 Intent intent = new Intent(Intent.ACTION_DIAL, uri); 6 startActivity(intent); 7 } 8 });
4、发送短信
同拨打电话一样,发送短信同样需要相应的权限。
<uses-permission android:name="android.permission.SEND_SMS"/>
不同的是,我们在发送短信的时候是通过SmsManager来完成发送的。首先我们要实例化一个SmsManager。通过SmsManager.sendTextMessage()方法可以进行短信发送。其原型为:
1 sendTextMessage(String destAddr, String scAddr, String text, PendingIntent sentIntent, PendingIntent deliveryIntent); 2 // destAddress 发送短信的地址(也就是号码) 3 // scAddress 短信服务中心,如果为null,就是用当前默认的短信服务中心 4 // text 短信内容 5 // sentIntent 如果不为null,当短信发送成功或者失败时,这个PendingIntent会被广播出去成功的结果代码是Activity.RESULT_OK 6 // deliveryIntent 如果不为null,当这个短信发送到接收者那里,这个PendtingIntent会被广播,状态报告生成的pdu(指对等层次之间传递的数据单位)会拓展到数据("pdu")
这里我们需要实例化一个PendingIntent来协助SMSManger的工作。
SmsManager smsManager = SmsManager.getDefault(); PendingIntent pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, new Intent(), 0); smsManager.sendTextMessage(strAddr, null, strCont, pendingIntent, null);
1 btnSend.setOnClickListener(new View.OnClickListener() { 2 @Override 3 public void onClick(View view) { 4 String strAddr = etPhone.getText().toString(); 5 String strCont = etContent.getText().toString(); 6 7 if (strAddr.equals("")) { 8 Toast.makeText(MainActivity.this, "收件人不能为空", Toast.LENGTH_SHORT).show(); 9 } 10 if (strCont.equals("")) { 11 Toast.makeText(MainActivity.this, "短信内容不能为空", Toast.LENGTH_SHORT).show(); 12 } 13 14 SmsManager smsManager = SmsManager.getDefault(); 15 PendingIntent pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, new Intent(), 0); 16 smsManager.sendTextMessage(strAddr, null, strCont, pendingIntent, null); 17 Toast.makeText(MainActivity.this, "短信发送成功",Toast.LENGTH_LONG).show(); 18 } 19 });
完整代码为:
1 import android.app.PendingIntent; 2 import android.content.Intent; 3 import android.support.v7.app.AppCompatActivity; 4 import android.os.Bundle; 5 import android.telephony.SmsManager; 6 import android.view.View; 7 import android.widget.Button; 8 import android.widget.EditText; 9 import android.widget.Toast; 10 11 public class MainActivity extends AppCompatActivity { 12 13 private EditText etPhone; 14 private EditText etContent; 15 private Button btnSend; 16 17 @Override 18 protected void onCreate(Bundle savedInstanceState) { 19 super.onCreate(savedInstanceState); 20 setContentView(R.layout.activity_main); 21 22 etPhone = (EditText) findViewById(R.id.etPhone); 23 etContent = (EditText) findViewById(R.id.etContent); 24 btnSend = (Button) findViewById(R.id.btnSend); 25 26 btnSend.setOnClickListener(new View.OnClickListener() { 27 @Override 28 public void onClick(View view) { 29 String strAddr = etPhone.getText().toString(); 30 String strCont = etContent.getText().toString(); 31 32 if (strAddr.equals("")) { 33 Toast.makeText(MainActivity.this, "收件人不能为空", Toast.LENGTH_SHORT).show(); 34 } 35 if (strCont.equals("")) { 36 Toast.makeText(MainActivity.this, "短信内容不能为空", Toast.LENGTH_SHORT).show(); 37 } 38 39 SmsManager smsManager = SmsManager.getDefault(); 40 PendingIntent pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, new Intent(), 0); 41 smsManager.sendTextMessage(strAddr, null, strCont, pendingIntent, null); 42 Toast.makeText(MainActivity.this, "短信发送成功",Toast.LENGTH_LONG).show(); 43 } 44 }); 45 } 46 }
5、接收短信
同拨打电话一样,发送短信同样需要相应的权限。接收短信需要
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
接收短信的原理是,首先新建一个BroadcastReceiver来监听短信信息,然后根据监听到的广播信息中的短信进行捕捉,然后呈现出来。
首先,新建一个Receiver类,然后重载其onReceive方法。
1 public class Receiver extends BroadcastReceiver { 2 3 @Override 4 public void onReceive(Context context, Intent intent) { 5 if (intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")) { 6 7 8 } 9 } 10 }
然后,我们新建一个Budle来接收信息,我们知道,短信信息的关键字为"pdus",所以通过一个Object[]来接收此信息,然后再将其转化为SmsMessage即可。
由于接收到的短信由于长度原因,可能被分割成若干条信息,所以,我们通过一个for循环来处理此短信。
1 if (intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")) { 2 StringBuilder str = new StringBuilder(); 3 Bundle bundle = intent.getExtras(); 4 if (bundle != null) { 5 Object[] pdus = (Object[]) bundle.get("pdus"); 6 SmsMessage[] msg = new SmsMessage[pdus.length]; 7 for (int i = 0; i < pdus.length; i++) { 8 msg[i] = SmsMessage.createFromPdu((byte[]) pdus[i]); 9 } 10 for (SmsMessage m : msg) { 11 str.append("发件人:"); 12 str.append(m.getDisplayOriginatingAddress()); 13 str.append("\n内容:"); 14 str.append(m.getDisplayMessageBody()); 15 } 16 Toast.makeText(context, "收到消息:\n" + str, Toast.LENGTH_LONG); 17 } 18 }
最后在AndroidManifest.xml中处理一下新建的Receiver类即可。
完整代码:
AndroidMainfest.xml
1 <?xml version="1.0" encoding="utf-8"?> 2 <manifest xmlns:android="http://schemas.android.com/apk/res/android" 3 package="com.example.doodle.button" > 4 5 <application 6 android:allowBackup="true" 7 android:icon="@mipmap/ic_launcher" 8 android:label="@string/app_name" 9 android:theme="@style/AppTheme" > 10 <activity 11 android:name=".MainActivity" 12 android:label="@string/app_name" > 13 <intent-filter> 14 <action android:name="android.intent.action.MAIN" /> 15 <category android:name="android.intent.category.LAUNCHER" /> 16 </intent-filter> 17 </activity> 18 19 <receiver android:name=".Receiver" android:enabled="true"> 20 <intent-filter> 21 <action android:name="android.provider.Telephony.SMS_RECEIVED"/> 22 </intent-filter> 23 </receiver> 24 25 </application> 26 27 <uses-permission android:name="android.permission.SEND_SMS"/> 28 <uses-permission android:name="android.permission.RECEIVE_SMS"/> 29 30 </manifest>
MainActivity.java
1 import android.support.v7.app.AppCompatActivity; 2 import android.os.Bundle; 3 4 public class MainActivity extends AppCompatActivity { 5 6 @Override 7 protected void onCreate(Bundle savedInstanceState) { 8 super.onCreate(savedInstanceState); 9 setContentView(R.layout.activity_main); 10 11 } 12 }
Receiver.java
1 import android.content.BroadcastReceiver; 2 import android.content.Context; 3 import android.content.Intent; 4 import android.os.Bundle; 5 import android.telephony.SmsMessage; 6 import android.widget.Toast; 7 8 public class Receiver extends BroadcastReceiver { 9 10 @Override 11 public void onReceive(Context context, Intent intent) { 12 if (intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")) { 13 StringBuilder str = new StringBuilder(); 14 Bundle bundle = intent.getExtras(); 15 if (bundle != null) { 16 Object[] pdus = (Object[]) bundle.get("pdus"); 17 SmsMessage[] msg = new SmsMessage[pdus.length]; 18 for (int i = 0; i < pdus.length; i++) { 19 msg[i] = SmsMessage.createFromPdu((byte[]) pdus[i]); 20 } 21 for (SmsMessage m : msg) { 22 str.append("发件人:"); 23 str.append(m.getDisplayOriginatingAddress()); 24 str.append("\n内容:"); 25 str.append(m.getDisplayMessageBody()); 26 } 27 Toast.makeText(context, "收到消息:\n" + str, Toast.LENGTH_LONG); 28 } 29 } 30 } 31 }