39.android广播-监听sd卡/监听电量的改变(不能在清单文件中注册)

广播监听sd卡,sd卡有三种状态MEDIA_MOUNTED===sd卡可用,MEDIA_REMOVED===sd卡拔出,MEDIA_UNMOUNTED===sd卡不可用,这里面不需要权限

清单文件(只需要和下面三种任意一个匹配就可以收到广播,data必须存在,为了匹配而存在):

        <receiver android:name="com.ldw.sdlistener.sdReceiver">
            <intent-filter>
                <action android:name="android.intent.action.MEDIA_MOUNTED"/>
                <action android:name="android.intent.action.MEDIA_REMOVED"/>
                <action android:name="android.intent.action.MEDIA_UNMOUNTED"/>
                <data android:scheme="file"/>
            </intent-filter>
        </receiver>

检测sd卡状态代码

package com.ldw.sdlistener;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;

public class sdReceiver extends BroadcastReceiver {

	@Override
	public void onReceive(Context context, Intent intent) {
		// TODO Auto-generated method stub
		//判断收到的是什么样的广播
		String action = intent.getAction();
		if("android.intent.action.MEDIA_MOUNTED".equals(action)){
			Toast.makeText(context, "sd卡可用", Toast.LENGTH_SHORT).show();
		}
		else if("android.intent.action.MEDIA_REMOVED".equals(action)){
			Toast.makeText(context, "sd卡拔出", Toast.LENGTH_SHORT).show();
		}
		else if("android.intent.action.MEDIA_UNMOUNTED".equals(object)){
			Toast.makeText(context, "sd卡不可用", Toast.LENGTH_SHORT).show();
		}
	}

}

MainActivity.java

package com.ldw.sdlistener;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;

public class MainActivity extends Activity {

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


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
    
}

一开始我是在Activity中注册广播,可以正常监听电量状态,但随着Activity生命周期变化,不能持续监听电量。就想到用service来持续监听,尝试了多次静态注册,发现竟然接收不到电量变化的广播。!!!!????
有五个不能静态注册的广播
不能静态注册的广播:

  •   android.intent.action.SCREEN_ON
  •   android.intent.action.SCREEN_OFF
  •   android.intent.action.BATTERY_CHANGED
  •   android.intent.action.CONFIGURATION_CHANGED
  •   android.intent.action.TIME_TICK

原因(有以下几种说法,提供给大家参考):

1.提高系统效率:这两个事件是android的基本事件,如果大多数程序监听,会大大的拖慢整个系统,所以android不鼓励我们在后台监听这两个事件。
2.因为有序广播的优先级问题。以上这些广播中,静态注册时,系统的优先级大于应用,并且系统阻止了广播的向下传播。又因在Android 的广播机制中,动态注册的优先级是要高于静态注册优先级的。故用动态注册代替静态注册。
3.系统安全问题。

解决方式(以android.intent.action.BATTERY_CHANGED为例):

动态注册不能放到activity中,因为动态注册必须要在activity消亡的时候调用unregisterReceiver,会随着activity的解锁消失而不能再接收广播。一般的办法是在activity起来后马上start一个service,这个service里动态注册一个broadcastreceiver,service必须常驻在系统内,所以要接收开机消息android.intent.action.BOOT_COMPLETED。

持续监听电量变化实例:

1,在Broadcast中启动service代码,开机自动启动:

private String boot_action ="android.intent.action.BOOT_COMPLETED";  
@Override
public void onReceive(Context context, Intent intent) { 
      if(boot_action.equals(action)){
         Log.i(TAG, "android.intent.action.BOOT_COMPLETED");
         Intent in0 = new Intent(context, BatteryService.class);
         context.startService(in0);
             
     }  
}

Manifest.xml中注册开机启动广播

<receiver android:name="BootBroadcastReceiver" >
             <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
             </intent-filter>
</receiver>

2,在service中动态注册广播,处理电量,service停止后自动启动

import java.text.SimpleDateFormat;

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.BatteryManager;
import android.os.IBinder;
import android.util.Log;

public class BatteryService extends Service {

    private static final String TAG = "BatteryReceiver"; 
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
    
    @Override  
    public void onCreate() {  
        super.onCreate(); 
        Log.i(TAG, "onCreate--------------");
        IntentFilter batteryfilter = new IntentFilter();
        batteryfilter.addAction(Intent.ACTION_BATTERY_CHANGED);
        registerReceiver(batteryReceiver, batteryfilter);
    }
    
    @Override  
    public void onStart(Intent intent, int startId) { 
        super.onStart(intent, startId);  
    }
    
    @Override  
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i(TAG, "onStartCommand--------------");
        return Service.START_STICKY; //
    }
    
    @Override  
    public void onDestroy() {  
        Log.i(TAG, "onDestroy--------------");
        super.onDestroy(); 
        this.unregisterReceiver(batteryReceiver); 
        
    }
    // 接收电池信息更新的广播  
     private BroadcastReceiver batteryReceiver = new BroadcastReceiver(){
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.i(TAG, "BatteryReceiver--------------");
            String action = intent.getAction();
            Log.i(TAG, " 0 action:"+ action);
            Log.i(TAG, "ACTION_BATTERY_CHANGED");
            int status = intent.getIntExtra("status", 0);
            int health = intent.getIntExtra("health", 0);
            boolean present = intent.getBooleanExtra("present", false);
            int level = intent.getIntExtra("level", 0);
            int scale = intent.getIntExtra("scale", 0);
            int icon_small = intent.getIntExtra("icon-small", 0);
            int plugged = intent.getIntExtra("plugged", 0);
            int voltage = intent.getIntExtra("voltage", 0);
            int temperature = intent.getIntExtra("temperature", 0);
            String technology = intent.getStringExtra("technology");

            String statusString = "";
            switch (status) {
            case BatteryManager.BATTERY_STATUS_UNKNOWN:
                statusString = "unknown";
                break;
            case BatteryManager.BATTERY_STATUS_CHARGING:
                statusString = "charging";
                break;
            case BatteryManager.BATTERY_STATUS_DISCHARGING:
                statusString = "discharging";
                break;
            case BatteryManager.BATTERY_STATUS_NOT_CHARGING:
                statusString = "not charging";
                break;
            case BatteryManager.BATTERY_STATUS_FULL:
                statusString = "full";
                break;
            }
            String acString = "";

            switch (plugged) {
            case BatteryManager.BATTERY_PLUGGED_AC:
                acString = "plugged ac";
                break;
            case BatteryManager.BATTERY_PLUGGED_USB:
                acString = "plugged usb";
                break;
            }
             
            SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss:SSS ");
              String date = sDateFormat.format(new java.util.Date()); 
             
            Log.i(TAG, "battery: date=" + date + ",status " + statusString 
                     + ",level=" + level +",scale=" + scale 
                     + ",voltage=" + voltage +",acString=" + acString );
            
             MyLog.i("Battery.txt", "Battery",":date=" + date + ",status=" + statusString 
                    + ",level=" + level +",scale=" + scale 
                    + ",voltage=" + voltage );

        }
     };
}

那么怎样才能保证service不被杀死?

Android开发的过程中,每次调用startService(Intent)的时候,都会调用该Service对象的onStartCommand(Intent,int,int)方法,这里在onStartCommand方法的返回值做文章就可以了,这里用到的是Service.START_STICKY这个返回值:

网络上找到的解释:如果service进程被kill掉,保留service的状态为开始状态,但不保留递送的intent对象。随后系统会尝试重新创建service,由于服务状态为开始状态,所以创建服务后一定会调用onStartCommand(Intent,int,int)方法。如果在此期间没有任何启动命令被传递到service,那么参数Intent将为null。

3,将电量数据保存到文件中(这里只提取了关键的方法)

/**
     * 打开日志文件并写入日志
     * 
     * @return
     * **/
    private static void writeLogtoFile(String logTypename, String mylogtype,
            String tag, String text) {// 新建或打开日志文件
        Log.i("zjq", "mylog----------");
        File path = Environment.getExternalStorageDirectory();
        Date nowtime = new Date();
        String needWriteFiel = logfile.format(nowtime);
        String needWriteMessage = text;
        File file = new File(path, needWriteFiel + logTypename);
        try {
            FileWriter filerWriter = new FileWriter(file, true);// 后面这个参数代表是不是要接上文件中原来的数据,不进行覆盖
            BufferedWriter bufWriter = new BufferedWriter(filerWriter);
            bufWriter.write(needWriteMessage);
            bufWriter.newLine();
            bufWriter.close();
            filerWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值