技术标签: java apache android Android
Android 中的每个应用程序都可以对自己感兴趣的广播进行注册,这样该程序就只会接收到自己所关心的广播内容,这些广播可能是来自系统的,也可能是来自于其他应用程序的。
广播有两种类型——有序广播和标准广播:
Android内置了很多系统级别的广播,我们可以在应用程序中通过监听这些广播来得到各种系统的状态信息。比如手机开机、电池电量发生变化、时间或者时区发生改变等等。如果想要接收到这些广播就需要使用广播接收器。
注册广播的方式一般也有两种,在 代码中注册(动态注册) 或者 在 AndroidManifest.xml
中注册(静态注册)。
我们实现一个能准确地告诉用户当前有没有网络的功能,在实现代码前,由于 Android 为了保护用户设备的隐私和安全,规定了程序需要进行一些对用户来说比较敏感的操作,必须在配置文件中声明权限才可以,该功能监听了网络的变化,所以必须在 AndroidManifest.xml
配置权限才能访问系统网络状态:
public class BroadcastActivity extends AppCompatActivity {
private IntentFilter intentFilter; // 意图过滤器,旨在匹配可以响应对应操作的组件
private NetworkChangeReceiver networkChangeReceiver; // 自定义的广播接收器类
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
intentFilter = new IntentFilter();
// android.net.conn.CONNECTIVITY_CHANGE是网络状态变化时系统的广播
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
networkChangeReceiver = new NetworkChangeReceiver();
// 注册,将接收器与IntentFilter相匹配
registerReceiver(networkChangeReceiver, intentFilter);
}
// 动态注册一定要在结束时取消注册
protected void onDestroy(){
super.onDestroy();
// 实现取消注册
unregisterReceiver(networkChangeReceiver);
}
// 自定义的广播接收器类
class NetworkChangeReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
// 通过getSystemService得到管理网络连接的connectivityManager实例
ConnectivityManager connectivityManager = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
// 通过isAvailable方法判断是否有网络
if(networkInfo != null && networkInfo.isAvailable()){
Toast.makeText(context, "network is available", Toast.LENGTH_SHORT).show();
} else{
Toast.makeText(context, "network is unavailable", Toast.LENGTH_SHORT).show();
}
}
}
}
动态注册的广播可以自由控制注册、注销,很灵活,缺点是必须在程序启动之后才能接受到广播,因为注册的逻辑是写在 onCreate()
里面的,使用静态注册可以让程序在未启动的情况下接受到广播。
静态注册需要在 AndroidManifest.xml
进行注册,使用 receiver
标签,并告诉这个 receiver
注册哪一个 action
,下面是一个开机启动接受广播的案例:
public class BootCompleteReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
// an Intent broadcast.
Toast.makeText(context, "Boot Complete", Toast.LENGTH_SHORT).show();
}
}
PS:不要在 onReceive()
方法中添加过多逻辑或耗时操作,因为广播接收器中不允许开启线程,因此当 onReceive()
运行较长时间却未结束时,程序就会报错。
发送广播使用 Intent 进行发送,首先需要准备一个接收器用于接受发送的广播:
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// 收到自定义广播时会弹出提示
Toast.makeText(context, "received in MyBroadcastReceiver", Toast.LENGTH_LONG).show();
}
}
在 AndroidManifest.xml
中注册广播的值:
实现点击 BroadcastActivity
活动中的 send broadcast
按钮来发送广播:
布局文件 broad_layout.xml
:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/button_broadcast1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="send broadcast"/>
</LinearLayout>
活动代码 BroadcastActivity.java
:
public class BroadcastActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.broad_layout);
Button button = findViewById(R.id.button_broadcast1);
button.setOnClickListener((View v)->{
// 将要发送的广播植入Intent
Intent intent = new Intent("com.example.activitytest.Activity.MY_BROADCAST");
// 参数1:包名;参数2:接收器的路径
ComponentName componentName = new ComponentName("com.example.activitytest",
"com.example.activitytest.Activity.MyBroadcastReceiver");
// 通过调用Intent中的setComponent方法,我们可以打开另外一个应用中的Activity或者服务。
intent.setComponent(componentName);
// 调用Context的sendBroadcast方法发送广播
sendBroadcast(intent);
});
}
}
PS: ComponentName
构造函数的第一个参数指的包名是 AndroidManifest.xml
文件下 package
属性对应的包名:
而非 BroadcastActivity.java
文件所在的包名:
详见该博客
运行结果:
新建一个项目,创建广播接收器 MyReceiver.java
:
public class MyReceiver extends BroadcastReceiver {
private static final String TAG = "MyReceiver";
@Override
public void onReceive(Context context, Intent intent) {
Log.e(TAG, "onReceive: gone");
Toast.makeText(context, "received gone", Toast.LENGTH_LONG).show();
}
}
AndroidManifest.xml
:
在原来项目的 BroadcastActivity.java
文件中发送第二条广播:
运行结果:
更多关于广播的问题详见本文——解决 Android 8.0 以上静态广播无法注册
很多人对之前的代码可能会有疑问,我指定广播发送给哪个包的哪个接收器,这还算“广播”吗?因此,对于安卓高版本而言,还有另一种发送广播的方法:
修改 BroadcastActivity.java
中的代码:
即可实现真正意义上的广播。在此基础上,我们发送有序广播,定义接收器的优先级:
并在接收器 MyBroadcastReceiver.java
中截断广播,不允许广播继续传递:
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// 收到自定义广播时会弹出提示
Toast.makeText(context, "received in MyBroadcastReceiver", Toast.LENGTH_SHORT).show();
// 截断
abortBroadcast();
}
}
不必对另一个接收器 MyReceiver 进行更改,此时就已达到了只有 MyBroadcastReceiver 能收到广播,而 MyReceiver 不能收到广播的目的。
前面我们发送和接受的广播都是系统的全局广播,发出的广播可以被其他任何应用程序接收到。这样容易引起安全问题,为了解决安全性问题,Android 支持发送本地广播,其有以下特点:
本地广播并不复杂,主要就是使用了一个 LocalBroadcastManager 来对广播进行管理,并且提供了发送广播和注册广播接收器的方法:
public class BroadcastActivity extends AppCompatActivity {
private static final String TAG = "BroadcastActivity";
private IntentFilter intentFilter; // 意图过滤器
private LocalReceiver localReceiver; // 自定义接收器类
private LocalBroadcastManager localBroadcastManager; // support包提供的本地广播工具
@SuppressLint("WrongConstant")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.broad_layout);
localBroadcastManager = LocalBroadcastManager.getInstance(this); // 获取实例
Button button = findViewById(R.id.button_broadcast1);
button.setOnClickListener((View v)->{
Log.e(TAG, "onCreate: start");
// 将要发送的广播植入Intent
Intent intent = new Intent("com.example.activitytest.Activity.LOCAL_BROADCAST");
if(Build.VERSION.SDK_INT >= 28){
// 突破隐式广播限制
intent.addFlags(0x01000000);
}
localBroadcastManager.sendBroadcast(intent); // 发送本地广播
});
// 动态注册的步骤
intentFilter = new IntentFilter();
// 添加自定义广播
intentFilter.addAction("com.example.activitytest.Activity.LOCAL_BROADCAST");
// 实例化接收器
localReceiver = new LocalReceiver();
// 注册接收器
localBroadcastManager.registerReceiver(localReceiver, intentFilter);
}
// 动态注册一定要在结束时取消注册
@Override
protected void onDestroy() {
super.onDestroy();
localBroadcastManager.unregisterReceiver(localReceiver);
}
class LocalReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "本地广播", Toast.LENGTH_LONG).show();
}
}
}
Mac 版本下ssh-keygen -t rsa -C"[email protected]”生成.ssh文件,文件夹下有id_rsa,id_rsa.pub两个文件,所要用的key 值就在id_rsa.pub文件中,复制粘贴到githup即可,如果找不到ssh文件,命令行open~/.ssh cd ~/.ssh 测试是否与远程库建立了连接 ssh -T [email protected]_githup
采用Zip Utils解压文件的基本操作示例及函数详解。1.HZIP OpenZip(const TCHAR *fn, const char *password); 参数fn文件路径,相对和绝对路径应该都可以,支持unicode格式 password是解压的密码,可以为空,只需传入参数0即可。但是遗憾的是,密码只支持ascii格式,没办法,只好自己封装了两个函数用于单字节和宽字节之间互相转换_openzip
在JavaScript中,您可以使用JSON.stringify将数组或值转换为JSON格式的字符串。 var output = {}output[0] = "a";output[1] = "b";output[2] = "c";console.log( JSON.stringify(output) ); 输出量 { "0":"a", "1":"b", "2":"c"..._js将数组转为json字符串
01-13 12:06:51.562: W/PackageParser(4364): Unable to read AndroidManifest.xml of /mnt/sdcard/example.apk01-13 12:06:51.562: W/PackageParser(4364): java.io.FileNotFoundException: AndroidManifest.xml01-..._android服务下载安装
题目描述田忌赛马问题,田忌和王都有n匹马。n场比赛(每匹马都只能上场一次)。每场比赛输的要给赢的人200块钱,问最后田忌最多能获得多少钱。输入n,接着是n匹田忌马速度,接着是n匹王的马速度,遇0结束。样例输入392 83 7195 87 74220 2020 20220 1922 180输出20000思路:
一、前言 最近要做一下json文件下载的功能,就是点击一个按钮,然后执行下载操作。本来这种下载应该是很简单的,不过博主在实际操作的时候,还是遇到了不少问题,记录一下。二、ajax不能下载文件1、为什么不能下载 如标题所示,本来是通过ajax请求链接下载..._通常不会下载json
大家好,我是时间财富网智能客服时间君,上述问题将由我为大家进行解答。把d盘的东西移到e盘直接用鼠标右键剪切复制就可以了,在d盘剪切,到e盘复制即可。如果担心文件丢失,也可以先复制,复制成功以后再删除d盘的文件。盘符是DOS、WINDOWS系统对于磁盘存储设备的标识符。一般使用26个英文字符加上一个冒号:来标识。由于历史的原因,早期的PC机一般装有两个软盘驱动器,所以,“A:”和“B:”这两个盘符就..._怎么把d盘的东西移到e盘
基于matlab音乐混响效果实现基于 MATLAB 的语音混响效果的设计与实现班级:10 通信二班姓名:彭海军学号:14102301154摘要 (中文)数字信号处理(Digital Signal Processing)技术,从 20 世纪 60 年代以来,随着计算机科学和信息科学发展,数字处理技术应运而生 得..._卷积混响 matlab
在傅里叶分析时域信号,需要区分直流与交流分量,区分时域的离散信号与连续信号,区分时域的周期信号与非周期信号。其实他们是辨证统一的,它们通过时间T的无穷大和无穷小的概念实现了统一。时间时间长度是一种客观的存在,时间的长度也是一种观察者的感受。100年有时候太长,100年有时候也太短。无限大:空间的无穷大,大到宇宙万物。时间的无穷大,大到几百亿年。无穷小空间的无穷小,小到分子、原子、粒子。时间的无穷小,小到一眨眼,以及过去几百万个时间单位,几十亿的时间单..
退出word文档的批注编辑的方法如下(以windows10系统的word2018版为例,需要word处于批注编辑模式):1、打开word文档,点击界面上方的“审阅”按钮。2、随后即可看到批注正在处于编辑状态,随后点击“显示批注”按钮。3、在word文档主界面中点击任意一个空白的位置。4、随后即可发现批注编辑模式已经被退出了,可以在word文档上正常打字了。..._word如何不显示批注
1.当一个字段只有一个值的时候使用if判断某字段是否为空格式例如 "${utoken}" != "\${utoken}"图中的意思就是当utoken不为空时,则执行该if条件下的用例2.当一个字段有多个值的时候使用ForEach控制器,应用场景如图:此时,如果返回结果中没有id,则forEach不会运行,达到了跳过的目的。..._jmeter判断获取接口没有这个值跳过执行
直入主题最近在m.kugou.com 抓到了酷狗api功能包括:1.获取歌手头像,2.获取下载链接,3.获取歌词4.。。。(0)回复1楼2015-11-07 20:06举报 |个人企业举报垃圾信息举报热门推荐千锋php培训 课程全新升级 g