關於獲取android訊號強度和電池狀態變化圖示修改的方法

WitKeyLei發表於2012-10-24

最近因專案需要自己編寫手機訊號和電池狀態變化圖示,所以開始研究,這裡的程式碼主要參考android2.2和android4.0原始碼,有興趣的朋友可以去看一下。

*/frameworks/base/services/java/com/android/server/BatteryService.java  //電池

 

com.android.server.status.Parcelable //訊號強度

/sim訊號強度變化/

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.os.Bundle;
import android.provider.Settings;

public class SingnalStatus {
 public static final int RADIO_TECHNOLOGY_EVDO_0 = 7;
 public static final int RADIO_TECHNOLOGY_EVDO_A = 8;
 public static final String ACTION_SERVICE_STATE_CHANGED = "android.intent.action.SERVICE_STATE";
 private static  int[] sSignalImages = new int[] {
  R.drawable.stat_sys_signal_0,
  R.drawable.stat_sys_signal_1,
  R.drawable.stat_sys_signal_2,
  R.drawable.stat_sys_signal_3,
  R.drawable.stat_sys_signal_4,
  R.drawable.stat_sys_signal_5
 };
// private static  int[] sSignalImages = new int[] {
//   R.drawable.stat_sys_signal_0,
//   R.drawable.stat_sys_signal_1,
//   R.drawable.stat_sys_signal_2,
//   R.drawable.stat_sys_signal_3,
//   R.drawable.stat_sys_signal_4
//  };
 
 /*漫遊*/
 private static  int[] sSignalImages_r = new int[] {
//  R.drawable.stat_sys_r_signal_0,
//  R.drawable.stat_sys_r_signal_1,
//  R.drawable.stat_sys_r_signal_2,
//  R.drawable.stat_sys_r_signal_3,
//  R.drawable.stat_sys_r_signal_4
 };
 private ServiceState mServiceState;
 private TelephonyManager mPhone;
 private int mRadioTechnology;
 private boolean mIsEmergencyOnly;
 private Context mContext;
 private ServiceStateBroadcast mBroadcast;
 public boolean isLister;
 private SingnalStatusChangeLister mLister;
 public interface SingnalStatusChangeLister{
  public void callBack(int iconId);
 }
 public void setOnStatusChangeLister(SingnalStatusChangeLister lister){
   
   mLister = lister;
  }
 public SingnalStatus(Context context) {
  mContext = context;
  mPhone = (TelephonyManager) context
    .getSystemService(Context.TELEPHONY_SERVICE);
  mBroadcast = new ServiceStateBroadcast();
  onRegisterReceiver();
 }

 int mPhoneState = TelephonyManager.CALL_STATE_IDLE;
 SignalStrength mSignalStrength;
 int iconId ;
 private final void updateSignalStrength() {
  int iconLevel = -1;
  int[] iconList;

  // Display signal strength while in "emergency calls only" mode
  if (!hasService() && !isEmergencyOnly()) {
   // Slog.d(TAG, "updateSignalStrength: no service");
   if (Settings.System.getInt(mContext.getContentResolver(),
     Settings.System.AIRPLANE_MODE_ON, 0) == 1) {
    /*飛航模式*/
    //iconId =R.drawable.stat_sys_signal_flightmode;
   } else {
    /*未知*/
    iconId =R.drawable.stat_sys_signal_null;
   }
   updateIcon(iconId);
   // mService.updateIcon(mPhoneIcon, mPhoneData, null);
   return;
  }

  if (!isCdma()) {
   int asu = mSignalStrength.getGsmSignalStrength();

   // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
   // asu = 0 (-113dB or less) is very weak
   // signal, its better to show 0 bars to the user in such cases.
   // asu = 99 is a special case, where the signal strength is unknown.
   if (asu <= 2 || asu == 99)
    iconLevel = 0;
   else if (asu >= 12)
    iconLevel = 5;
   else if (asu >= 10)
    iconLevel = 4;
   else if (asu >= 8)
    iconLevel = 3;
   else if (asu >= 5)
    iconLevel = 2;
   else
    iconLevel = 1;

   // Though mPhone is a Manager, this call is not an IPC
//   if (mPhone.isNetworkRoaming()) {
//    iconList = sSignalImages_r;
//   } else {
    iconList = sSignalImages;
   //}
  } else {
   //iconList = this.sSignalImages;
   iconList = sSignalImages;

   // If 3G(EV) and 1x network are available than 3G should be
   // displayed, displayed RSSI should be from the EV side.
   // If a voice call is made then RSSI should switch to 1x.
   if ((mPhoneState == TelephonyManager.CALL_STATE_IDLE) && isEvdo()) {
    iconLevel = getEvdoLevel();
//    if (false) {
     log( "use Evdo level=" + iconLevel +
      " to replace Cdma Level=" + getCdmaLevel());
//    }
   } else {
    iconLevel = getCdmaLevel();
   }
   
  }
  iconId = iconList[iconLevel];
  updateIcon(iconId);
  // mService.updateIcon(mPhoneIcon, mPhoneData, null);
 }

 private boolean isEmergencyOnly() {
  // TODO Auto-generated method stub
  return mIsEmergencyOnly;
 }

 private PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
  @Override
  public void onSignalStrengthsChanged(SignalStrength signalStrength) {
   mSignalStrength = signalStrength;
   updateSignalStrength();
  }

  
  public void onServiceStateChanged(ServiceState state) {
   mServiceState = state;
  // EServiceState s = (EServiceState)state;
   updateSignalStrength();
   // updateCdmaRoamingIcon(state);
   // updateDataIcon();
  }

  @Override
  public void onCallStateChanged(int state, String incomingNumber) {
   updateCallState(state);
   // In cdma, if a voice call is made, RSSI should switch to 1x.
   if (isCdma()) {
    updateSignalStrength();
   }
  }

  @Override
  public void onDataConnectionStateChanged(int state, int networkType) {
   // mDataState = state;
   // updateDataNetType(networkType);
   // updateDataIcon();
  }

  @Override
  public void onDataActivity(int direction) {
   // mDataActivity = direction;
   // updateDataIcon();
  }
 };

 private boolean hasService() {
  if (mServiceState != null) {
   switch (mServiceState.getState()) {
   case ServiceState.STATE_OUT_OF_SERVICE:
   case ServiceState.STATE_POWER_OFF:
    return false;
   default:
    return true;
   }
  } else {
   return false;
  }
 }

 private final void updateCallState(int state) {
  mPhoneState = state;
//  if (false) {
//   // Slog.d(TAG, "mPhoneState=" + mPhoneState
//   // + " mLowBatteryDialog=" + mLowBatteryDialog
//   // + " mBatteryShowLowOnEndCall=" + mBatteryShowLowOnEndCall);
//  }
  //if (mPhoneState == TelephonyManager.CALL_STATE_IDLE) {
   // if (mBatteryShowLowOnEndCall) {
   // if (!mBatteryPlugged) {
   // showLowBatteryWarning();
   // }
   // mBatteryShowLowOnEndCall = false;
   // }
  //} else {
   // if (mLowBatteryDialog != null) {
   // mLowBatteryDialog.dismiss();
   // mBatteryShowLowOnEndCall = true;
   // }
  //}
 }

 private boolean isCdma() {
  return (mSignalStrength != null) && !mSignalStrength.isGsm();
 }

 private int getCdmaLevel() {
  final int cdmaDbm = mSignalStrength.getCdmaDbm();
  final int cdmaEcio = mSignalStrength.getCdmaEcio();
  int levelDbm = 0;
  int levelEcio = 0;

  if (cdmaDbm >= -75)
   levelDbm = 5;
  else if (cdmaDbm >= -80)
   levelDbm = 4;
  else if (cdmaDbm >= -85)
   levelDbm = 3;
  else if (cdmaDbm >= -95)
   levelDbm = 2;
  else if (cdmaDbm >= -100)
   levelDbm = 1;
  else
   levelDbm = 0;

  // Ec/Io are in dB*10
  if (cdmaEcio >= -90)
   levelEcio = 5;
  else if (cdmaEcio >= -100)
   levelEcio = 4;
  else if (cdmaEcio >= -110)
   levelEcio = 3;
  else if (cdmaEcio >= -130)
   levelEcio = 2;
  else if (cdmaEcio >= -150)
   levelEcio = 1;
  else
   levelEcio = 0;

  return (levelDbm < levelEcio) ? levelDbm : levelEcio;
 }

 private int getEvdoLevel() {
  int evdoDbm = mSignalStrength.getEvdoDbm();
  int evdoSnr = mSignalStrength.getEvdoSnr();
  int levelEvdoDbm = 0;
  int levelEvdoSnr = 0;

  if (evdoDbm >= -65)
   levelEvdoDbm = 5;
  if (evdoDbm >= -70)
   levelEvdoDbm = 4;
  else if (evdoDbm >= -75)
   levelEvdoDbm = 3;
  else if (evdoDbm >= -90)
   levelEvdoDbm = 2;
  else if (evdoDbm >= -105)
   levelEvdoDbm = 1;
  else
   levelEvdoDbm = 0;

  if (evdoSnr >= 7)
   levelEvdoSnr = 5;
  else if (evdoSnr >= 6)
   levelEvdoSnr = 4;
  else if (evdoSnr >= 5)
   levelEvdoSnr = 3;
  else if (evdoSnr >= 3)
   levelEvdoSnr = 2;
  else if (evdoSnr >= 1)
   levelEvdoSnr = 1;
  else
   levelEvdoSnr = 0;

  return (levelEvdoDbm < levelEvdoSnr) ? levelEvdoDbm : levelEvdoSnr;
 }

 private boolean isEvdo() {
  //return false;
   return ( (mServiceState != null)
   && ((getRadioTechnology()
   == RADIO_TECHNOLOGY_EVDO_0)
   || (getRadioTechnology()
   == RADIO_TECHNOLOGY_EVDO_A)));
 }

 private int getRadioTechnology() {
  // TODO Auto-generated method stub
  return mRadioTechnology;
 }
 
 


 class ServiceStateBroadcast extends BroadcastReceiver{

  @Override
  public void onReceive(Context context, Intent intent) {
   // TODO Auto-generated method stub
   String action = intent.getAction();
   Log.e("SingnalStatus", "action="+action);
   if(action.equals(ACTION_SERVICE_STATE_CHANGED)){
    Bundle m = intent.getExtras();
    if(m!=null){
     mIsEmergencyOnly = m.getBoolean("emergencyOnly");
     mRadioTechnology = m.getInt("radioTechnology");
     Log.e("SingnalStatus", "mIsEmergencyOnly="+mIsEmergencyOnly
       +" mRadioTechnology="+mRadioTechnology);
     updateSignalStrength();
    }
    
   }
  }
  
 }
 public void updateIcon(int iconid){
  Log.e("SingnalStatus", "updateIcon="+iconid);
  if(mLister!=null){
   mLister.callBack(iconid);
  }
 }
 public void onRegisterReceiver(){
  if(isLister){
   return;
  }
  isLister = true;
  mPhone.listen(mPhoneStateListener, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
  mPhone.listen(mPhoneStateListener,PhoneStateListener.LISTEN_CALL_STATE);
  mPhone.listen(mPhoneStateListener, PhoneStateListener.LISTEN_SERVICE_STATE);
  mContext.registerReceiver(mBroadcast, new IntentFilter(ACTION_SERVICE_STATE_CHANGED));

 }
 public  void onUnRegisterReceiver(){
  if(!isLister){
   return;
  }
  isLister = false;
  mPhone.listen(mPhoneStateListener,
    PhoneStateListener.LISTEN_NONE);
  mContext.unregisterReceiver(mBroadcast);
  
 }
 public void destory(){
  onUnRegisterReceiver();
  if(sSignalImages!=null){
   sSignalImages =null;
  }
  if(sSignalImages_r!=null){
   sSignalImages_r = null;
  }
  if(mBroadcast!=null){
   mBroadcast = null;
  }
 }

 

 

 

/電池狀態變化/

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.BatteryManager;

public class BatteryStaus {
 private Context mContext;

 
 private int mBatteryStatus;
 private int mBatteryLevel;
 private BatteryStatusChangeLister mLister;
 public interface BatteryStatusChangeLister{
  public void callBack(int level,int iconId);
 }
 public BatteryStaus(Context context){
  mContext = context;
  mContext.registerReceiver(mReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
  
 }
 public void setOnStatusChangeLister(BatteryStatusChangeLister lister){
  
  mLister = lister;
 }
    private final int getIcon(int level) {
        if (mBatteryStatus == BatteryManager.BATTERY_STATUS_CHARGING) {
            return R.drawable.stat_sys_battery_charge;
        } else if (mBatteryStatus == BatteryManager.BATTERY_STATUS_DISCHARGING) {
            return R.drawable.stat_sys_battery;
        } else if (mBatteryStatus == BatteryManager.BATTERY_STATUS_NOT_CHARGING
                || mBatteryStatus == BatteryManager.BATTERY_STATUS_FULL) {
            if (mBatteryStatus == BatteryManager.BATTERY_STATUS_UNKNOWN && mBatteryLevel >= 100) {
                return R.drawable.stat_sys_battery_charge;
            } else {
                return R.drawable.stat_sys_battery;
            }
        } else {
            return R.drawable.stat_sys_battery_unknown;
        }
    }
   
 private BroadcastReceiver mReceiver = new BroadcastReceiver() {
  public void onReceive(Context arg0, Intent intent) {
   String action = intent.getAction();
   
   if (action.compareTo(Intent.ACTION_BATTERY_CHANGED) == 0) {
    mBatteryStatus = intent.getIntExtra("status", BatteryManager.BATTERY_STATUS_NOT_CHARGING);  
    mBatteryLevel = intent.getIntExtra("level", 0);// 電量百分比
    if(mLister!=null)
      mLister.callBack(mBatteryLevel, getIcon(mBatteryLevel));

   }
  }
 };
 public void destory(){
  mContext.unregisterReceiver(mReceiver);
 }

 

相關文章