1.用法(在Mainfest中静态注册):
通过一个简单的例子来说明:
这是主Activity:
package com.larry.msglighter; import android.app.Activity; import android.content.Intent; import android.os.Bundle; public class MsgLighter extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_msg_lighter); Intent intent = new Intent(); intent.getAction(); } }
这是Receiver:
package com.larry.msglighter; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.widget.Toast; public class MyBroadcastReceiver extends BroadcastReceiver { // action 名称 String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED" ; public void onReceive(Context context, Intent intent) { if (intent.getAction().equals( SMS_RECEIVED )) { // 相关处理 : 地域变换、电量不足、来电来信; System.out.println("JB"); Toast.makeText(context, "来短信了", Toast.LENGTH_LONG).show(); } } }
这是Mainifest里要注册的receiver:
<receiver android:name = ".MyBroadcastReceiver" > <intent-filter android:priority = "1000" > <action android:name = "android.provider.Telephony.SMS_RECEIVED" /> </intent-filter > </receiver >
以及权限:
<uses-permission android:name = "android.permission.RECEIVE_SMS"/> <uses-permission android:name = "android.permission.SEND_SMS" />
这个简单的例子实现了当短信来了的时候toast一个“短信来了”,当然可以把toast事件改成别的想要的事件。
值得注意的是:
public class MsgLighter extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_msg_lighter); Intent intent = new Intent(); intent.getAction(); } }
这里intent的用法,这里用了一个getAction();参数为空,然后在receiver里面用下面的代码来判断这个action到底是什么。有时候也出现了setAction(),但我还不清楚这样做有什么意义。。。既然是自己能交代Action,那何必还要让系统来判断。。
if (intent.getAction().equals( SMS_RECEIVED )) { // 相关处理 : 地域变换、电量不足、来电来信; System.out.println("JB"); Toast.makeText(context, "来短信了", Toast.LENGTH_LONG).show(); }
先到这。
2.关于:
今天发现BroadcastReceiver是不会因为APP的进程被杀死而停止侦听的。。也就是说杀死了进程也能在系统有广播的时候自动程序。。好神奇。
先到这。
3.DEC2,2013补充
今天测试发现如果已经在Manifest文件中注册了BroadcastReceiver,再在onReceiver()方法中使用
if (intent.getAction().equals( SMS_RECEIVED ))
判断是否有短信似乎是多此一举的。
后来发现,如果这个广播注册了多个action,这个语句是可以用来区分的。这样就不用写好多个BroadcastReceiver了。
http://zhidao.baidu.com/question/1894114941584455300.html
4.July 25th,2014补充(代码中注册Receiver)
过去了这么久,发现之前对BroadcastReceiver的理解也仅限于静态注册的一点点知识,现在又学了一点,记录下来,不过还有很多东西没懂,比如有序广播无序广播什么的。
又看了一遍Mars的视频,他说在UI更新等情况下最好是动态注册,因为只有在展示给用户的时候注册才有意义。
其实动态注册还有个好处,就是优先级比静态注册优先级高,也就是会先拦截到广播。比如你做一个短信应用,却发现短信先被360拦截了,如何抢在360前面呢?
来个示例,工程里有三个文件:
如果是2.3之前的版本,是不需要MainActivity的(这个想必都知道,4.0以后只有Receiver的应用,是没有权利接收广播的,程序必须运行一次才行)。这个Activity里啥也没有。
然后是BroadcastReceiver,结构是这样的:
package com.seclab.zygote; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.util.Log; public class MyBrocast extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub Log.v("MyBrocast.onReceive", "received!"); if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) { Log.d("REceiver","this is a receiver"); Intent service = new Intent(context, MyService.class); context.startService(service); } } }
看见它的onReceive()方法里先是Log了一下,然后用一个判断intent的语句判断是否开机启动,是的话就启动Service。
然后是Service,代码中注册Receiver,也就是每次开机就注册:
package com.seclab.zygote; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.nio.charset.Charset; import android.app.Service; import android.content.Intent; import android.content.IntentFilter; import android.os.IBinder; import android.util.Log; import android.widget.Toast; public class MyService extends Service{ private MyBrocast myService = null ; @Override public IBinder onBind(Intent arg0) { // TODO Auto-generated method stub return null; } @Override public int onStartCommand(Intent intent, int flags, int startId) { // TODO Auto-generated method stub IntentFilter localIntentFilter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED"); localIntentFilter.setPriority(2147483647);//设置最高优先级 myService = new MyBrocast(); MyBrocast localMessageReceiver = myService; Log.v("MyBrocast.onReceive", "onCreate"); registerReceiver(localMessageReceiver, localIntentFilter); //验证这个onStartCommand是否在开机启动之后被调用。如果没有,为什么不直接把注册放到启动开机启动里(放弃Service) FileOutputStream fos = null ; try { fos = new FileOutputStream("/sdcard/hey.txt"); OutputStream os = fos; OutputStreamWriter osw = new OutputStreamWriter(os ,Charset.forName("GBK")); osw.write("hey"); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return super.onStartCommand(intent, flags, startId); } }
在Service里面我加了一个验证Service是否成功启动的代码,就是在sd卡上创建一个txt文件。
另外,在Manifest.xml中,也同时用了静态注册,并且设置了最高优先级。
这样的话,我发一条短信,Logcat里可以同时收到两条「received!」的log信息。一条是静态注册的Receiver接收到的的,一条是动态注册的Receiver接收到的。
另外,看到一篇BLOG上说的收到重视的启动顺序是:
1.首先,会解析手机中的/system/framework这个目录,原生系统中,这下面就一个apk - framework-res.apk
当然各个厂商也会加入自己的内容,比如我的这个目录下就有com.htc.resources.apk
2.然后受到重视的文件夹按顺序分别为:
/system/app
/vendor/app
/data/app
/drm/app-private
下面我将把这个应用push到/system/framework里,试一下能不能抢得过360。