当前位置:阳光沙滩 >Android > 查看文章
阿里云优惠码

目录

监听SD卡的状态

接收开机完成的广播

IP拨号

监听软件的下载和安装

短信窃听器

无序广播

有序广播

有序广播2

只能通过代码注册的广播

1.安卓基础-广播接收者

什么是广播接收者呢?

广播,我们应该都听过广播吧,而这个广播接收者,可以理解为这个收音机。

 

在安卓系统里,系统会定时发地布一些广播,比如说这个电量,这个有电话拨入,有信息进入,开机完成等等。这些都会以广播的形式发出来,然后其他应用就会接收广播,做出相应的动作。

 

1.1.监听SD卡的状态

我们就先写一个例子来说明一下这个广播,用过微信的朋友都应该知道有这么一个界面吧,当然这是一个早期的界面。不过,嘻嘻!我没有用过微信。

%e5%9b%be%e7%89%871

看到那个土司了吗?储存卡已拨出,微信头像、图片、语音、视频、相册及朋友圈功能将暂时不可用。

 

 

好吧,我们下面写一下这个代码吧!

 

布局,简单就不写了哈,嘻嘻!默认的也可以嘛!主要是代码去接收这个系统储存卡已经拔开的广播。

 

步骤:

  • 定义一个类,去继承BroadcastReciver
  • 复写onRecevice方法,当接收到广播的时候就会调用此方法
public class SDStuauReciver extends BroadcastReceiver {

	@Override
	public void onReceive(Context context, Intent intent) {
		//当我们接收到广播的时候就执行这里头的代码,这里弹出一个土司。
		Toast.makeText(context, "储存卡已拨出,微信头像、图片、语音、视频、相册及朋友圈功能将暂时不可用。", 0).show();
	}
}

 

  • 注册广播接收者
  • 添加意图过滤器

配置文件 AndroidMainFest.xml里头的application里配置一下即可

 <receiver android:name="com.sunofbeaches.blogdemo.SDStuauReciver">
            <intent-filter>
                <action android:name="android.intent.action.MEDIA_UNMOUNTED"/>
                <data android:scheme="file"/>
            </intent-filter>
        </receiver>

 

好啦,万事俱备,只欠运行了!

 

当我们把程序部署到虚拟机上跑起来时,我们去设置(settings)—-储存卡(Storage)—-Unmount SD card

不过呢,这个在高版本里没有哦,嘻嘻!所以呢,用4.0以下的版本吧,这里测试用的是2.3.3版本的。

%e5%9b%be%e7%89%8722

然后点击,就会:

%e5%9b%be%e7%89%8732

好啦,到这里这个例子就写完了哦,代码很少吧,哈哈!通过这个例子呢,我们知道了这个步骤,以后大家去接收这个广播的时候按这个步骤去写就可以了。当然,并不是死的哦,灵活使用就可以啦!

1.2. 接收开机完成的广播

 

再来一个例子吧,我们接收开机完成的广播。貌似以前呢,有这样的玩意思,开机勒索。如果装上了这样的软件,只能通过付钱才能解开呗。

描述大概这样子的嘛:软件接收到你的开机完成的广播以后呢就开启界面,然后给出提示要你打钱到某某账号,不多,嘻嘻。你点击返回键不行,点击Home键也不行。

 

当然,作为一个有经验的开发人员,这事还是可以搞定的嘛!下面我就是模拟一下这个开机完成后提示这个信息。

 

代码实现:

 

  • 定义一个类去继承BroadcastReciver
  • 把要执行的代码编写在onRecevice方法里
public class BootCompleteRecevice extends BroadcastReceiver {

	@Override
	public void onReceive(Context context, Intent intent) {
		
		//打印一个日志告诉我们说开机完成
		Log.d("d", "开机完成!");

		//如果接收到广播就启动主界面
		Intent in = new Intent(context,MainActivity.class);
		
		//需要使用到这个上下文去启动这个界面,这个上下文没有任务栈,所以要指定一个flag标签
		//表明这个界面会放到新的任务栈里。
		in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
		context.startActivity(in);
	}
}

 

  • 注册广播接收者和意图过滤器
 <receiver android:name="com.sunofbeaches.blogdemo.BootCompleteRecevice">
            <intent-filter >
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
            </intent-filter>
        </receiver>
  • 在0版本以后需要这个权限才能获取到开机完成的广播。
 <!-- 在安卓4.0以后要加这个获取到权限 -->
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

另外就搞一个界面吧,嘻嘻嘻,这个是主界面哦。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="您好!你的手机已经被锁定,请向***账号打10元人民币获取解锁码!" />

</LinearLayout>

开机完成之后,解锁:

%e5%9b%be%e7%89%8742

然后我们设置一下,返回键不能用,嘻嘻!

我们只要在这个主程序里头复写这个onBackPress方法即可。里面什么也不写,也就是点击返回的时候什么也不做咯!

@Override
	public void onBackPressed() {
	}

这样的话,当这个界面显示的时候,点击这个返回键是不能返回的。

点击Home键还能回到主界面是吧,那到底怎么实现这个点击home键也不能回去呢!

请继续看后面的文章,要不,,嘻嘻!你就实现去坑人了!

1.3.IP拨号

关于这个ip拨号,我们要接收到的是拨打电话的广播。

描述:首先是设置这个Ip号码。然后是有拨打电话的时候,如果发现是长途的电话,我们就自动在号码前面加上这个Ip号。

 

对了,大家知道什么是ip拨号吗?好吧,我还是画一个图说一下吧,嘻嘻。

%e5%9b%be%e7%89%8752

(图片都是我画的,使用说明一下是来自阳光沙滩:www.sunofbeaches.com  谢谢大家啦!)

 

好吧,图解释完了,我们就来这个正题吧。

先写一个界面,大概是一个输入框,一个按钮。然后让用户输入Ip号,然后把这个ip号保存起来,当用户拨打电话的时候,如果发现有0开头的号码,右以判断是长途,加了区号嘛,嘻嘻。了不知道是不是这样的,大家就装作是吧,这个核心不是在这里,是在接收广播。然后呢。如果是长途,就默认在这个前面加上这个ip号。拨打出去即可。

 

好啦,我吃过饭了,继续写吧,嘻嘻!

 

主界面:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity" >

    <EditText
        android:id="@+id/et_ipnumber"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="请输入Ip号码" />

    <Button
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:onClick="save"
        android:text="保存" />

</LinearLayout>

%e5%9b%be%e7%89%8761

然后编写这个保存的按钮的事件处理代码:

public class MainActivity extends Activity {
	SharedPreferences sp;
	EditText et_ipnumber = null;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		// 获取到输入框
		et_ipnumber = (EditText) findViewById(R.id.et_ipnumber);
		sp= this.getSharedPreferences("config", 0);
		et_ipnumber.setText(sp.getString("ipnumber", ""));
	}

	public void save(View v) {
		// 获取输入的数据
		String number = et_ipnumber.getText().toString().trim();

		// 安全检查
		if (TextUtils.isEmpty(number)) {
			// 如没有填写就点击保存的话就提示一下嘛
			Toast.makeText(this, "ip号码不能为空哦,么么哒!", 0).show();
			return;
		}
		// 如果有内容的话,就保存起来,这里我用这个sharePerference来存储简单的数据
		// 二话不说,先获取到先嘛
		// 获取编辑顺
		Editor edit = sp.edit();
		edit.putString("ipnumber", number);

		edit.commit();
		// 就这样,数据就保存了嘛,哈哈哈!
		Toast.makeText(this, "数据保存成功!", 0).show();
	}
}

 

保存好这个Ip号码之后,我们在拨打电话的时候,就需要接受到拨打电话的广播,所以呢,我们要定义一个广播接收的类,去继承BroadcastReciver。除了写里面接收到广播后的执行语句之外,我们还要在配置文件里注册一下。即使前面两个例子已经很熟悉了吧,我还是会写出来D,嘻嘻!

 

编写广播接收者:

public class PhoneStatuReciver extends BroadcastReceiver {

	@Override
	public void onReceive(Context context, Intent intent) {

		//一旦接收到打电话的广播,那么获取到打电话的拨号数据
		String data = this.getResultData();
		//判断一下,这个号码是不是以这个0开头捏,是的话,我们就添加一下这个Ip号,再设置回去。
		if(data.startsWith("0")){
			//获取Ip号
			SharedPreferences sp = context.getSharedPreferences("config",0);
			
			String ipnumber = sp.getString("ipnumber", "");
			
			//号码的前面加上这个Ipnumber
			data = ipnumber+data;
			System.out.println(data+"==============");
			
			//设置回去
			this.setResultData(data);
		}
		
	}
}

设置这个接收者添加一个过滤器

 <receiver android:name="com.sunofbeaches.ipcall.PhoneStatuReciver">
            <intent-filter >
                <action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
            </intent-filter>
        </receiver>

获取权限

  <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>

然后就可以运行啦,第一次运行需要设置这个Ip号码。然后再拨打电话,当发现是长途电话的时候就会自动添加上Ip号啦

%e5%9b%be%e7%89%877

爽吧,又学会了这个Ip拨号了,嘻嘻!

 

1.4.监听软件的下载和安装

先讲个故事吧,在很久很久以前,山上有个公司,开发了一个很多人用的软件,然后这个软件随着时间的推移,用的人达到了一定的数目,随后,当别的公司也开发出更好用的软件时,抢走了大量的用户,于是乎,被山上的公司发现,山上的那公司也开发出类似的软件某信。

 

所以,从这个故事里可以知道,山上那个公司多多少少侵犯了用户的隐私,监测着用户的软件安装和卸载。

 

大公司就这样嘛,嘻嘻!有的是钱,看你发展起来了,先收购,收购不成就抄袭呗,反正打官司你打不过,他们有用户基础,除非可以技术垄断。

 

 

步骤:

  • 写一个类去继承这个BroadcastReciver,然后把接收到广播后执行的代码写在里面。
public class SoftStatuListener extends BroadcastReceiver {

	@Override
	public void onReceive(Context context, Intent intent) {

		//当然是对这个获取到的广播进行判断啦
		/*因为我们注册的时候是这个安装和卸载嘛*/
		if(intent.getAction().equals(Intent.ACTION_PACKAGE_ADDED)){
			//打出信息,说这个软件安装了
			Log.d("message", intent.getData()+"软件安装了");
		}else if(intent.getAction().equals(Intent.ACTION_PACKAGE_REMOVED)){
			Log.d("message", intent.getData()+"软件被卸载了");
		}
	}
}
  • 注册一下这个接收者和意图过滤器
<receiver android:name="com.sunofbeaches.softstatulistener.SoftStatuListener">
            <intent-filter >
                <data android:scheme="package"/>
                <action android:name="android.intent.action.PACKAGE_ADDED"/>
                <action android:name="android.intent.action.PACKAGE_REMOVED"/>
            </intent-filter>
        </receiver>

%e5%9b%be%e7%89%878

1.5. 短信窃听器

这个大家都听多了吧,知道怎么实现的吗?接下来,我们就看看怎么去实现这样一个功能哦!

丫的,这么多年,自己的短信总是被女朋友窃听,现在终于可以反窃听一回了!

 

  • 定义这个类去继承BroadcastReciver。
  • 到这里,我们就需要去查看这个信息解析的代码了。不过官方的有点多哈。
    1. 以下是官方的源代码
public static final SmsMessage[] getMessagesFromIntent(
             Intent intent) {
         Object[] messages = (Object[]) intent.getSerializableExtra("pdus");
         byte[][] pduObjs = new byte[messages.length][];

         for (int i = 0; i < messages.length; i++) {
             pduObjs[i] = (byte[]) messages[i];
         }
         byte[][] pdus = new byte[pduObjs.length][];
         int pduCount = pdus.length;
         SmsMessage[] msgs = new SmsMessage[pduCount];
         for (int i = 0; i < pduCount; i++) {
             pdus[i] = pduObjs[i];
             msgs[i] = SmsMessage.createFromPdu(pdus[i]);
         }
         return msgs;
     }

我们可以根据源码自己写比较简单的。

public class MessageBroadcastRevicer extends BroadcastReceiver {

	@Override
	public void onReceive(Context context, Intent intent) {

		/*
		 * 当程序接收到来信广播的时候,就会被调用,这个时候,我们可以进行劫持
		 * 然后获取到信息的内容,进行处理,发到自己的手机或者再给这个信息收到也可以的嘛。
		 */
		// 获取信息
		Object[] message = (Object[]) intent.getSerializableExtra("pdus");
		for (int i = 0; i < message.length; i++) {
			byte[] buf = (byte[]) message[i];
			// 将数据进行格式化
			android.telephony.SmsMessage data = android.telephony.SmsMessage
					.createFromPdu(buf);
			// 获取数据内容
			String body = data.getMessageBody();
			// 获取这个发送人
			String address = data.getOriginatingAddress();

			// 然后把这个数据发到我们的手机,是吧,嘻嘻!这里直接打出啦!
			Log.d("message", "来自" + address + "的信息,内容是:" + body);

			// 终止广播
			this.abortBroadcast();// 不再传给手机上的信息接收器。
		}
	}
}
  • 注册接收者、权限、意图过滤器
<receiver android:name="com.sunofbeaches.messagelistener.MessageBroadcastRevicer">
            <intent-filter android:priority="1000">
                <!-- 查看短信接收器的代码找到的,嘻嘻! -->
                <action android:name="android.provider.Telephony.SMS_RECEIVED"/>
            </intent-filter>
        </receiver>

权限:

  <uses-permission android:name="android.permission.RECEIVE_SMS"/>

%e5%9b%be%e7%89%879

%e5%9b%be%e7%89%8710

然而,这个系统的信息接收器并收不到信息哦,哈哈!不错吧!

 

1.6.无序广播

无序广播,当然还有有序广播,嘻嘻!不过,这个有序广播下一个再说吧。在上面的五个例子里,我们都是为了获取了这个系统的广播,而这里我们就自己定义自己的广播吧,然后再获取自己的广播。

先自己发一个广播吧,哈哈,无序的哦!

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
	}

	public void send(View v){
		//设置这个Action
		Intent intent = new Intent();
		Intent action = intent.setAction("con.sunofbeaches.orderboradcast.BROADCAST");
		
		//设置内容
		action.putExtra("data", "这是来自己我自己定义的广播....");
		sendBroadcast(action);
	}
}

在界面里添加了一个按钮,界面就只这个啦。然后的话点击就会执行这里的send方法啦,这个方法是发送广播的嘛。


<Button
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="发送广播"
        android:onClick="send" />

自己定义的广播接收者

public class MyBroadcastReciver extends BroadcastReceiver {

	@Override
	public void onReceive(Context context, Intent intent) {
		//接收到广播后就打印到logcat里吧。
		String data = intent.getStringExtra("data");
		Log.d("message", data);
	}

}

注册接收者和意图过滤器

<receiver android:name="com.sunofbeaches.orderbroadcast.MyBroadcastReciver">
            <intent-filter >
                <action android:name="con.sunofbeaches.orderboradcast.BROADCAST"/>
        	    </intent-filter>
</receiver>

%e5%9b%be%e7%89%8710

好啦,这个无序广播到此结束了,接下来当然是有序广播啦!

1.7. 有序广播

有了前面的无序广播,然后现在我们要说说这个有序广播了!

 

有序广播和无序广播有什么不同呢?

  • 有序广播,因为是有序的,当然是按优先级高低来接收的,优先级高的先接收到,低的后接收到。这个优先级从-1000到

另外,这个先接收到的应用程序可以对广播进行修改,或者终止广播也可以。

  • 无序广播,无序,所以是所有的应用程序可以同时接收到,从而谈不上终止广播和修改广播。

 

这里是有序的广播,其实和无序的差不多,只是在部分上不同。比如说,在发送的时候不同,注册广播接收者的时候,需要设置一个这个优先级别。

 

先写发送广播的类吧!在主类里发布广播即可,界面同样,只需要一个按钮就可以啦!

 

界面:

  <Button
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="发送有序广播"
        android:onClick="send" />

%e5%9b%be%e7%89%8712

发送有序的广播:

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
	}

	public void send(View v){
		
		//定义意图对象
		Intent intent = new Intent();
		intent.setAction("com.sunofbeaches.ORDER_BROADCAST");
		//设置广播内容
		this.sendOrderedBroadcast(
				intent,//意图对象
				null,//接收权限
				null, //最终接收者,也就是一定会收到的
				null, //消息处理器
				1, //初始代码
				"有序广播消息...",//初始数据 
				null);//额外的数据
	}
}

定义一个类去继承BroadcastReciver

然后获取里面的数据

public class MyOrderBroadcastReciver extends BroadcastReceiver {

	@Override
	public void onReceive(Context context, Intent intent) {

		//获取广播数据
		String data = this.getResultData();
		
		Log.d("message", data);
		
	}
}

%e5%9b%be%e7%89%8713

我点击了很多次,嘻嘻!

 

在注册那里也看到了,多了个设置这个优先级别的priority = 1000

也就是这个优先级别设置为1000.当然,还要在这个基础上演示一下这个对广播进行修改,或者终止广播。这样的话,在这个优先级别以下的收不到了。

 

1.8.有序广播2

在这里呢,先讲一个故事,去构造你内心的场景。是这样的,我是老板嘛,我要给所有的员工发2亿的奖金。我很多企业嘛,所以呢,我只能找到各企业里的老总过来开会,给也们每人带两个亿回去,然后他们回去了,再找部门经理开会,然后部门经理再找各小组开会,最后才发放奖金。

 

生活在现实的我们,都知道,不贪污是不太可能的,所以呢,在这其中就有老总或者经理贪污,自己弄了一点钱。好啦,场景设置好了,接下来,代码体现一下吧:

老板发广播了,注意一下吧,嘻嘻嘻!

public class MainActivity extends Activity {
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
	}
	public void send(View v){
		//搞一个意图对象
		Intent intent = new Intent();
		intent.setAction("com.sunofbeaches.bonusorderbroadcast.BONUS");
		//设置数据
		this.sendOrderedBroadcast(intent, null, null, null, 1, "老板:我今年给大家发¥2亿奖金..", null);
	}
}

老总接收广播:

  • 定义一个类去继承BroadcastReciver
public class LeaderReciver extends BroadcastReceiver {

	@Override
	public void onReceive(Context context, Intent intent) {

		//这是老总接收老板的广播
		
		//获取广播
		String data = this.getResultData();
		
		Log.d("messate", data);
		
		//贪污5千万剩下1.5亿
		data = "老板:我今年给大家发¥1.5亿奖金..";
		
		//把这个数据发给部门经历
		this.setResultData(data);
	}
}

注册一下:

<receiver android:name="com.sunofbeaches.bonusorderbroadcast.LeaderReciver">
            <intent-filter android:priority="1000">
                <action android:name="com.sunofbeaches.bonusorderbroadcast.BONUS"/>
            </intent-filter>
        </receiver>
  • 部门经理接收广播:
public class DepartMentManagerReciver extends BroadcastReceiver {

	@Override
	public void onReceive(Context context, Intent intent) {

		// 接收广播的数据
		String data = this.getResultData();
		Log.d("部门经理", data);

		// 部门经理贪污了两千万,剩下1.3亿。
		data = "老板:我今年给大家发¥1.3亿奖金..";
		setResultData(data);
	}
}

注册接收者和过滤器

 <!-- 配置经理接收 ,和优先级500-->
        <receiver android:name="com.sunofbeaches.bonusorderbroadcast.DepartMentManagerReciver">
            <intent-filter android:priority="500">
                <action android:name="com.sunofbeaches.bonusorderbroadcast.BONUS"/>
            </intent-filter>
        </receiver>
  • 定义一个员工接收者
public class EmployeeReciver extends BroadcastReceiver {

	@Override
	public void onReceive(Context context, Intent intent) {

		//获取广播消息
		String data = this.getResultData();
		
		//打印出来吧
		Log.d("员工", data);
		Log.d("员工", "谢谢老板!");
	}
}

注册一下呗:

<receiver android:name="com.sunofbeaches.bonusorderbroadcast.EmployeeReciver">
            <intent-filter android:priority="500">
                <action android:name="com.sunofbeaches.bonusorderbroadcast.BONUS"/>
            </intent-filter>
        </receiver>

运行的结果如下:

%e5%9b%be%e7%89%8714

通过这个案例,我们得出结论:

我们可以自己定义广播,然后接收广播。并且,可以设置这个优先级。有序广播的特别,优先级高的先接收,然后的话,可以修改,甚至可以终止广播,这个大家可以去试试吧,另外还有一个最终接收者的,这个也是哦,大家可以设置一下,在那个发送那里sendOrderedBroadcast方法里传入相关的参数即可以了。

 

好吧,加油!

 

1.9. 只能通过代码注册的广播

在前面里,我们都在配置文件里配置这个接收者。那么在系统里呢,有些广播是不允许这个配置文件里配置的。因这些广播太频繁 ,这样的话会点很多的资源的。比如说,这个电源的广播,每两秒就广播一次,这个锁屏或者这个解锁也是,很频繁的操作就不可以在配置文件里配置了,只能用代码来配置。下面就用例子来说明一下,就是用代码配置,然后说明这个用代码设置。

  • 和前面一样,先定义一个接收者
public class ScreenReciver extends BroadcastReceiver {

	@Override
	public void onReceive(Context context, Intent intent) {
		if(intent.getAction().equals(Intent.ACTION_SCREEN_ON)){
			//打印出Logcat
			Log.d("message", "屏幕解锁了!");
		}else{
			Log.d("message", "锁屏了!真的!");
		}
	}

}

再通过代码给接收者进行注册

public class MainActivity extends Activity {

	// 定义全局屏幕状态广播接收者,就是我们创建那个类啦
	ScreenReciver sr = null;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		sr = new ScreenReciver();

		// 添加意图过滤器
		IntentFilter intfil = new IntentFilter();
		intfil.addAction(Intent.ACTION_SCREEN_OFF);
		intfil.addAction(Intent.ACTION_SCREEN_ON);
		
		//注册广播接收者
		this.registerReceiver(sr, intfil);
		
	}
	@Override
	protected void onDestroy() {

		this.unregisterReceiver(sr);
		super.onDestroy();
	}
}

结果如下:

%e5%9b%be%e7%89%8715

帅吧!哈哈….

OK啦,广播就讲到这里吧,祝大家学习愉快!有问题到我们的社区交流哦!

 

社区:http://bbs.sunofbeaches.com

 

 

 

本文链接:http://blog.sunofbeaches.com/archives/346 转载请注明出处.
如果喜欢:点此订阅本站
7K
为您推荐
各种观点