http://blessdyb.iteye.com/blog/628338
目前需要开发一个开机自启动的GTD应用程序来提醒用户的一些重要日程安排,对于这类应用,Android提供了一个BroadcastReceiver组件来对于应用程序的运行环境进行监听,并对于各种事件进行对应的处理。使用BroadcastReceiver十分简单,我们只需要在AndroidManifest.xml或者我们的代码中进行相应的注册(这也是Android开发的两种方式)。这样之后在广播事件到来时,我们就能通过重写BroadcastReceiver的onReceive()方法来执行相应的操作。
下面简单来演示如何开发开机自启动应用。
1.建立一个名为Boot的Android应用。
2.简单实现BootActivity的应用界面,在此实现了一个TextView的实例来开机后显示一句话内容。
TextView textView=new TextView(this);
textView.setText("这是一个开机自启动应用程序");
setContentView(textView);
3.创建一个BootBroadcastReveiver的类,实现了抽象类BroadcastReceiver。以下是整个代码。
package com.blessdyb.boot;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class BootBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)){
Intent bootActivityIntent=new Intent(context,BootActivity.class);
bootActivityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(bootActivityIntent);
}
}
}
4.在AndroidMenifest.xml中配置Receiver。如下图我们在Android Menifest Application中进行配置。
其结果即为如下XML配置(application子目录):
<receiver android:name=".BootBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"></action>
</intent-filter>
</receiver>
5.当然,我们需要对我们的应用进行权限许可,只有通过这种形式才能真正地让我们的应用程序实现开机自启动。我们需要在AndroidMenifext.xml中进行如下配置。
配置完成后,会在XML文件中以如下形式显示(menifext子目录)
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/ >
之后,我们就可以对自己的应用程序进行签名,打包手就可以在手机上进行真机测试了。
转载出处:http://www.androidlab.cn/viewthread.php?tid=421&extra=page%3D1
2.构造一个 IntentReceiver类, 重构其抽象方法 onReceiveIntent(Context context, Intent intent),在其中启动你想要启动的Service。
3.在 AndroidManifest.xml中,首先加入 <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"></uses-permission>来获得BOOT_COMPLETED的使用许可,然后注册前面重构的IntentReceiver类,在其 <intent-filter>中加入 <action android:name="android.intent.action.BOOT_COMPLETED" />,以使其能捕捉到这个Action。
一个例子
xml:

<uses-permissionandroid:name="android.permission.RECEIVE_BOOT_COMPLETED"></uses-permission>
<receiverandroid:name=".OlympicsReceiver"android:label="@string/app_name">
<intent-filter>
<actionandroid:name="android.intent.action.BOOT_COMPLETED"/>
<categoryandroid:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</receiver>

publicclassOlympicsReceiverextendsIntentReceiver
{
/*要接收的intent源*/
staticfinalStringACTION="android.intent.action.BOOT_COMPLETED";
publicvoidonReceiveIntent(Contextcontext,Intentintent)
{
if(intent.getAction().equals(ACTION))
{
context.startService(newIntent(context,
OlympicsService.class),null);//启动倒计时服务
Toast.makeText(context,"OlympicsReminderservicehasstarted!",Toast.LENGTH_LONG).show();
}
}
}

publicclassOlympicsReceiverextendsBroadcastReceiver
{
/*要接收的intent源*/
staticfinalStringACTION="android.intent.action.BOOT_COMPLETED";
publicvoidonReceive(Contextcontext,Intentintent)
{
if(intent.getAction().equals(ACTION))
{
context.startService(newIntent(context,
OlympicsService.class),null);//启动倒计时服务
Toast.makeText(context,"OlympicsReminderservicehasstarted!",Toast.LENGTH_LONG).show();
//这边可以添加开机自动启动的应用程序代码
}
}
}
http://www.iteye.com/topic/1115903
- /**
- *如何去理解BroadcastReceiver(广播)?
- *其实可以这样想,首先我们要有一个发送广播的“媒体”,在这个例子中,我们暂且用activity组件作为这个媒体,当然以后
- *会用到service,或者随机启动方式来发送广播,这看业务需求来决定。
- *在这个例子中,当点击按钮的时候,一条广播就发送了出去,同样用到了意图对象Intent。
- *和启动activity和service一样,我们需要为意图对象设置“标记”和“包裹”,它就像个基站,向世界发送信号。
- *而对于广播自身而言,他就像一个监听器,一个系统级别的监听器,当然他也有他所监听的内容,不是什么都监听的,
- *那么如何确定广播到底在监听什么呢?
- *上面提到,意图这个基站被激活后向外发送信号,这个信号是带着“标记(action)”的,比如,基站发送了一条标记为
- *setAction("wuchen.broadcastReceiver.MY_RECEIVER")的信号,
- *而在世界中监听的广播君,如果想要监听到这条信号,就需要让世界知道自己的存在,并且告诉世界自己要监听的信号的标记是什么,
- *都要记录在案。这就需要在Manifest清单文件中进行注册:
- *<receiverandroid:name=".MyBroadcastReceiver">
- <intent-filter>
- <actionandroid:name="wuchen.broadcastReceiver.MY_RECEIVER"/>
- </intent-filter>
- </receiver>
- *一但注册完成功后,每当有基站发送的信号同广播君向世界注册的标记匹配时,广播君就会启动并截获信息。
- *其实广播接听的这个过程,上面的比喻需要调整一下,更严谨的说法是广播并不是随时都保持在一个监听的状态,而是在
- *接收到Intent发出的广播和自己本身注册的信息匹配时,才会被触发,而且由于自身属于系统级别监听和程序级别监听不同的是:
- *程序级别监听在程序终止后就没有监听作用了,而系统级别监听在被激活后会有自己的进程,比如当一个程序打开,并激活了一个系
- *统级别监听,当这个程序关闭后,系统级别监听并不会随着这个激活他的程序的关闭而停止处理业务的作用,还会继续运行,
- *除非他自己本身处理完业务需求后生命周期结束。严格上讲,系统级别监听的broadcastReceiver激活后也只能最多运行10秒钟,
- *如果10秒内还没有处理完业务,Android会认为该程序无响应,并弹出ANR(applicationNoResponse)对话框。
- *对于这种”限制“,我们处理这种限制的方式,也是项目中用到的最多一种方法:启动service。
- *最可靠的方式是在广播中启动一个service,让service在后台去处理数据,这样就算广播生命周期结束,service也不会被销毁,
- *因为用startService这种方式启动的service,就算访问者(广播)销毁自己也不会销毁,
- *而且本来在广播中处理数据的耗时操作,交给了service去做,同时避免了ANR问题的出现。
- *用启动新线程的方式也不可靠,
- *广播的生命周期,就是内部onReceive方法的周期,当onReceiver方法结束,也就意味着广播的结束。虽然我们可以在onReceiver
- *内执行启动一个新线程执行耗时的业务,由于onReceiver方法周期很短暂,可能出现的情况是:子线程还没有结束
- *广播就关闭了,广播一旦关闭,虽然子线程还可以运行,但系统会认为广播处于无组件活动的状态,在内存紧张的时候优先结束该进程,这样
- *可能会导致子线程不能执行完任务。所以最好的方式是启动service。
- *
- *需要注意的是,世界中接收同一个标记信号的广播君不局限只能存在一个,也许广播君A和广播君B监听的是同一个信号
- *这是决不冲突的。但究竟是广播君A先接收到信号还是广播君B先接收到,这就涉及到了有序广播,和有序广播相对应的是普通广播。
- *普通广播:
- *普通广播可以让所有的广播君一起接收到信号(逻辑上),如果有10个广播君,那么是个都可以接收到,无法停止信号的传播。
- *有序广播:
- *有序广播传播的方式如同传递,比如有10个广播君,A传到B,B再到C,以此类推,如果传到D后,D想终止信号的传播,那么D以后
- *的广播君就接收不到信号了。虽然这10个广播君都在等待接收同一个信号,但在D这里,就有权利终止信号的传输。
- *有序广播还有一个特点,广播君可以将自己的内容传给下一位
- *唯一需要确定的是,到底是广播君A先接收到还是广播君B先接收到,这就需要在广播君们在注册时,考虑到”优先级“的问题了。
- *在配置文件的每个receiver中的intent-filter标签中添加一个属性android:priority="100",数字越高
- *优先级越大。
- *<receiverandroid:name=".MyBroadcastReceiver">
- <intent-filterandroid:priority="11">
- <actionandroid:name="wuchen.broadcastReceiver.MY_RECEIVER"/>
- </intent-filter>
- </receiver>
- <receiverandroid:name=".MyBroadcastReceiver_B">
- <intent-filterandroid:priority="10">
- <actionandroid:name="wuchen.broadcastReceiver.MY_RECEIVER"/>
- </intent-filter>
- </receiver>
- *@authorAdministrator
- *
- */
上面讲了很多关于广播的很多基础概念,那么BroadcastReceiver在实际的应用中到底会起到样的作用呢?
因为广播是一个系统级别的监听器,所以它可以将不同进程间通信的一个“纽带”。举个简单的例子,我们知道在我们启动service是如果用startService这种方式启动时,访问者和service之间是不能进行数据的“互动”的,但是有了BroadcastReceiver就一样可以进行互动,方法我大致说一下,在activity端创建一个broadcast,同样在service端也创建一个broadcast,相互监听对方的动作,这样就可以达到进程间通信的目的了。
BroadcastReceiver还可以监听系统进程,比如android的收短信,电量低,电量改变,系统启动,等……只要BroadcastReceiver监听了这些进程,就可以实现很多有趣的功能,比如,接收短信的这条广播是一条有序广播,所以我们可以监听这条信号,在传递给真真的接收程序时,我们将自定义的广播接收程序的优先级大于它,并且取消广播的传播,这样就可以实现拦截短信的功能了。
下面是短信拦截代码:
Java代码
- packagewuchen.broadcastReceiver;
- importandroid.content.BroadcastReceiver;
- importandroid.content.Context;
- importandroid.content.Intent;
- importandroid.os.Bundle;
- importandroid.telephony.SmsMessage;
- importandroid.widget.Toast;
- publicclassSmsReceiverextendsBroadcastReceiver
- {
- //当接收到短信时被触发
- @Override
- publicvoidonReceive(Contextcontext,Intentintent)
- {
- //如果是接收到短信
- if(intent.getAction().equals(
- "android.provider.Telephony.SMS_RECEIVED"))
- {
- //取消广播(这行代码将会让系统收不到短信)
- abortBroadcast();
- StringBuildersb=newStringBuilder();
- //接收由SMS传过来的数据
- Bundlebundle=intent.getExtras();
- //判断是否有数据
- if(bundle!=null)
- {
- //通过pdus可以获得接收到的所有短信消息
- Object[]pdus=(Object[])bundle.get("pdus");
- //构建短信对象array,并依据收到的对象长度来创建array的大小
- SmsMessage[]messages=newSmsMessage[pdus.length];
- for(inti=0;i<pdus.length;i++)
- {
- messages[i]=SmsMessage
- .createFromPdu((byte[])pdus[i]);
- }
- //将送来的短信合并自定义信息于StringBuilder当中
- for(SmsMessagemessage:messages)
- {
- sb.append("短信来源:");
- //获得接收短信的电话号码
- sb.append(message.getDisplayOriginatingAddress());
- sb.append("\n------短信内容------\n");
- //获得短信的内容
- sb.append(message.getDisplayMessageBody());
- }
- }
- Toast.makeText(context,sb.toString()
- ,5000).show();
- }
- }
- }
清单文件
- Xml代码
- <?xmlversion="1.0"encoding="utf-8"?>
- <manifestxmlns:android="http://schemas.android.com/apk/res/android"
- package="wuchen.broadcastReceiver"
- android:versionCode="1"
- android:versionName="1.0">
- <applicationandroid:icon="@drawable/icon"android:label="@string/app_name">
- <receiverandroid:name=".SmsReceiver">
- <intent-filterandroid:priority="800">
- <actionandroid:name="android.provider.Telephony.SMS_RECEIVED"/>
- </intent-filter>
- </receiver>
- </application>
- <!--授予程序接收短信的权限-->
- <uses-permissionandroid:name="android.permission.RECEIVE_SMS"/>
- </manifest>