广播接收器与短信
一、BrodcastReceiver
1.1、BrodcastReceiver简介
BrodcastReceiver是“广播接收者”的意思,是用来接收来自系统和应用中的广播。
在Android系统中,广播体现在方方面面,例如当开机完成后系统会产生一条广播,接收到这条广播就能实现开机启动服务的功能;当网络状态发生改变时,系统会产生一条广播,接收到这条广播就能及时作出提示和保存数据等操作留点电池电量改变时,系统会产生一条广播,接收到这条广播就能在电量低时告知用户及时保存进度等等。
1.2、广播接收器的类型
1.2.1、Normal broadcasts:默认广播
发送一个默认广播使用Context.sendBroadcast()方法,普通广播对于多个接受者来说是完全异步的,通常每个接收者都无需等待即可接收到广播,接收者之间不会有影响,对于这种广播,接收者无法终止广播,既无法阻止其他接收者的接收动作。
1.2.2、Ordered broadcasts:有序广播
发送一个有序广播使用Context.sendOrderedBroadcast()方法,有序广播比较特殊,他每次只发送到优先级较高的接收者那里,然后由优先级较高的接收者再传播到优先级较低的接收者哪里,优先级高的接收者有能力终止这个广播。
1.2.3、Sticky Broadcasts:粘性广播
当处理完之后的Intent,依然存在,直到你把它去掉。
1.3、广播接收器的常见步骤
构建Intent,使用sendBroadcasts方法发出广播
定义一个广播接收器,该广播接收器继承BroadcastReceiver,并且覆盖onReceive()方法来响应事件
注册该广播接收器,我们可以在代码中注册,也可以在AndroidManifest.xml配置文件中注册
Normal Broadcasts:
//发送一个普通的广播 btnNormal.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent("com.action.MY_BROADCAST"); intent.putExtra("info", "传了一个广播"); sendBroadcast(intent); } });
/** * 自定义的广播接收器 */ public class MyReceiver extends BroadcastReceiver { //接收· @Override public void onReceive(Context context, Intent intent) { String s = intent.getStringExtra("info"); Toast.makeText(context, s, Toast.LENGTH_SHORT).show(); } }
广播注册方式:静态注册
<receiver
android:name=".MyReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.action.MY_BROADCAST"></action>
</intent-filter>
</receiver>
1.4、注册广播接收器的两种方式
静态注册:在AndroidManifest.xml文件中配置
动态注册:需要在代码中动态的指定广播地址并注册,通常我们是在Activity或Service注册一个广播,在这个方法发来的广播,收到的广播的先后和注明优先级最高的他么的先后是随机,如果都没有优先级,代码注册收到的最先。
如:
MyReceiver myReceiver = new MyReceiver(); IntentFilter filter = new IntentFilter(); filter.addAction("android.intent.action.MY_BROADCAST"); registerReceiver(myReceiver,filter); //解除绑定 unregisterReceiver(myReceiver);
1.5、有序广播
发送有序广播:sendOrderedBroadcasts()
在注册广播中的<intent-filter>中使用android:pririty属性,这个属性的范围在-1000到1000,数值越大,优先级越高
在广播接收器中使用setResultExtras方法将一个Bundle随想设置为结果集对象,传递到下一个接收者那里,这样优先级低的接收者可以用getResultExtras获取到最新的经过处理的信息集合。
使用sendOrderedBroadcasts方法发送有序广播时,需要一个权限参数,如果为null则表示不要求接收者声明指定的权限,如果不为null,则表示接收者若要接收此广播,需要声明指定权限,这样做是从安全角度考虑的,例如系统的短信就是有序广播的形式,一个应用可能是具有拦截垃圾短信的功能,当短信来时他可以先接收到短信广播,必要时终止广播传递,这样的软件就必须声明接受短信的权限。
终止广播传递:abortBroadcast()
同级别接收是先后随机的,再到级别低的收到广播,如果先接收到的把广播截断了,同级别以外的接收者是无法收到该广播的。
在这个放法发来的广播中(代码注册方式中),收到广播的先后次序为:注明优先级的、代码注册的、没有优先级的;如果都没有优先级,代码注册的先收到。
//发送一个有序广播 btnOrdered.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent("com.action.MY_BROADCAST2"); //参数:intent,接收权限, sendOrderedBroadcast(intent,null); } });
<receiver
android:name=".MyReceiver3"
android:enabled="true"
android:exported="true">
<intent-filter android:priority="100">
<action android:name="com.action.MY_BROADCAST2" />
</intent-filter>
</receiver>
<receiver
android:name=".MyReceiver4"
android:enabled="true"
android:exported="true">
<intent-filter android:priority="200">
<action android:name="com.action.MY_BROADCAST2" />
</intent-filter>
</receiver>
public class MyReceiver3 extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//获取上一个传过来的值
Bundle data = getResultExtras(false);
String s = data.getString("data");
Toast.makeText(context, "接受一个有序广播" + s, Toast.LENGTH_SHORT).show();
}
}
public class MyReceiver4 extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "有序广播2", Toast.LENGTH_SHORT).show();
//向下一个接收者传值
Bundle data = new Bundle();
data.putString("data", "sssssw");
this.setResultExtras(data);
//终端有序广播
// abortBroadcast();
}
}
1.6、粘性广播
发送粘性广播:sendStickyBroadcasts(intent);
发送这个广播需要权限:
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
去掉使用这个方法:removeStickyBroadcasts(intent)
sendStickyOrderedBroadcasts():这个方法具有有序广播的特性也有粘性广播的特性
在这个方法发送的广播中,代码注册方式中,收到广播的先后次序为:注明优先级的、代码注册的、没有优先级的、如果没有优先级,代码注册为最先。
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
//发送一个粘性广播
btnSticky.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent("com.action.MY_BROADCAST3");
sendStickyBroadcast(intent);
}
});
//打开接收粘性广播的Activity
btnOpenSticky.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this, Main2Activity.class);
startActivity(intent);
}
});
public class Main2Activity extends AppCompatActivity {
private MyReceiver5 receiver5 = new MyReceiver5();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
}
@Override
protected void onResume() {
super.onResume();
IntentFilter intentFilter = new IntentFilter("com.action.MY_BROADCAST3");
registerReceiver(receiver5, intentFilter);
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(receiver5);
}
}
public class MyReceiver5 extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "接受一个粘性广播", Toast.LENGTH_SHORT).show();
}
}
1.7、接收系统广播
1.7.1、开机启动服务
我们经常会有这样的应用场合,比如消息推送服务,需要实现开机启动功能,要实现这个功能,我们就可以订阅系统“启动完成”这条广播,接收到这条广播后我们就可以启动自己的服务了。
<intent-filter> <!--注册开始广播地址--> <action android:name="android.intent.action.BOOT_COMPLETED" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter>
这个开机广播地址,从安全角度,系统要求必须恒明开机启动广播的权限
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
1.7.2、网络状态变化
比如用户浏览网络信息是,网络突然断开,我们要及时地提醒用户网络已断开。要实现这个功能,我们可以接受网络状态改变这样一条广播,当有连接状态变为你开状态时,系统会发送一条广播,在通过网络的状态做出相应的操作。
<intent-filter> <action android:name="android.intent.action.CONFIGURATION_CHANGED" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter>
访问网络状态权限:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<receiver
android:name=".MyReceiver6"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.CONFIGURATION_CHANGED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
public class MyReceiver6 extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = cm.getActiveNetworkInfo();
if (info != null) {
String name = info.getType() + "";
Toast.makeText(context, name, Toast.LENGTH_SHORT).show();
}
}
}
1.7.3、电量变化
android:exported="true"> <intent-filter> <action android:name="android.intent.action.BATTERY_CHANGED" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter>
@Override
protected void onResume() {
super.onResume();
//立即获取电量
IntentFilter intentFilter1 = new IntentFilter();
intentFilter1.addAction("android.intent.action.BATTERY_CHANGED");
Intent battery = getApplicationContext().registerReceiver(null,intentFilter1);
//当前电量
int cuur = battery.getIntExtra(BatteryManager.EXTRA_LEVEL,0);
//总电量
int total = battery.getIntExtra(BatteryManager.EXTRA_SCALE,1);
int percent = cuur*100/total;
Toast.makeText(MainActivity.this,"当前电量为"+percent+"%",Toast.LENGTH_SHORT).show();
}
//在该方法中解除广播注册
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(receiver2);
}
1.8、发送短信
信息的发送,对mms应用程序来讲主要就是在信息数据库中创建并维护一条信息记录,真正的发送过程交友底层(Frameworks层)函数来处理。
虽然在Android系统中已经存在发送短信的应用,但是如果我们在开发其它应用时需要继承发送短信功能,则很方便。
核心代码:
//获得默认的消息管理器
SmsManager manager = SmsManager.getDefault();
//拆分长短信
ArrayList<String> list = manager.divideMessage(String txt);
//发送短信
manager.sendTextMessage(String phone,null,String content,null,null);
发送短信的权限
<uses-permission android:name="android.permission.SEND_SMS" />
btnSendMsg.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//获得默认的消息管理器
SmsManager manager = SmsManager.getDefault();
//拆分长短信
ArrayList<String> list = manager.divideMessage("发送了一条短信");
for (int i = 0; i < list.size(); i++) {
//发送短信
//参数:电话号码,信息中心号码,信息内容
manager.sendTextMessage("18766489688",null,list.get(i),null,null);
}
}
});
1.9、接收短信
略