BroadcastReceiver

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。

原文地址:https://www.cnblogs.com/larrylawrence/p/3421176.html