当前位置:  编程技术>移动开发
本页文章导读:
    ▪转载 ADROID 2.1 架构解析 十 声音        转载 ADROID 2.1 架构解析 10 声音 10 声音 10.1 音频管理 文件: frameworks/base/media/java/android/media/AudioManager.java 10.1.1 音量控制 /** @hide Default volume index values for audio streams */ public static final in.........
    ▪ listView中item一部分可用        listView中item部分可用 事实再一次证明有时候 自己还真的好浮躁,以前只是简单的看过这个程序 只是没有细研,今天用到item 部分可用部分不可用 当返回去查阅时 真汗颜 ,好多东西要不归于.........
    ▪ ADROID 2.1 架构解析 五 电池       ADROID 2.1 架构解析 5 电池 5 电池电池涉及的功能有:BatteryStatus、BatteryHealth、BatteryPresent、BatteryLevel、PlugType、BatteryVoltage、BatteryTemperature、BatteryTechnology等,它是种从下而上的表现方式,即.........

[1]转载 ADROID 2.1 架构解析 十 声音
    来源: 互联网  发布时间: 2014-02-18
转载 ADROID 2.1 架构解析 10 声音
10 声音
10.1 音频管理
文件: frameworks/base/media/java/android/media/AudioManager.java

10.1.1 音量控制
/**  @hide Default volume index values for audio streams */ 

    public static final int[] DEFAULT_STREAM_VOLUME = new int[] { 

        4,  // STREAM_VOICE_CALL 

         7,  // STREAM_SYSTEM 

        5,  // STREAM_RING 

        11, // STREAM_MUSIC 

        6,  // STREAM_ALARM 

        5,  // STREAM_NOTIFICATION 

        7,  // STREAM_BLUETOOTH_SCO 

        7,  // STREAM_SYSTEM_ENFORCED 

        11, // STREAM_DTMF 

        11  // STREAM_TTS 

}; 


以上结构定义了默认音量。

public void adjustStreamVolume(int streamType, int direction, int flags) { 

        IAudioService service = getService(); 

        try { 

            service.adjustStreamVolume(streamType, direction, flags); 

        } catch (RemoteException e) { 

            Log.e(TAG, "Dead object in adjustStreamVolume", e); 

        } 

} 

public void setStreamVolume(int streamType, int index, int flags) { 

        IAudioService service = getService(); 

        try { 

            service.setStreamVolume(streamType, index, flags); 

        } catch (RemoteException e) { 

            Log.e(TAG, "Dead object in setStreamVolume", e); 

        } 

    } 



将音量控制参数转给音频服务去处理。

10.1.2 播放控制
@Deprecated public void setParameter(String key, String value) { 

        setParameters(key+"="+value); 

    } 

  

    /** 

     * Sets a variable number of parameter values to audio hardware. 

     * 

     * @param keyValuePairs list of parameters key value pairs in the form: 

     *    key1=value1;key2=value2;... 

     * 

     */ 

    public void setParameters(String keyValuePairs) { 

        AudioSystem.setParameters(keyValuePairs); 

} 

cupcake 的播放控制采用的是 setrouting() 方式进行, eclaire 的播放控制改用 setParameter 方式,用参数设置的方式进行。

以上代码的功能是:将参数传给音频系统去进行处理。

10.2 音频服务
文件: frameworks/base/media/java/android/media/AudioService.java

10.2.1 音效
 
private static final String SOUND_EFFECTS_PATH = "/media/audio/ui/"; 

    private static final String[] SOUND_EFFECT_FILES = new String[] { 

        "Effect_Tick.ogg", 

        "KeypressStandard.ogg", 

        "KeypressSpacebar.ogg", 

        "KeypressDelete.ogg", 

        "KeypressReturn.ogg" 

}; 

public boolean loadSoundEffects() { 

        ... 

String filePath = Environment.getRootDirectory() + SOUND_EFFECTS_PATH + SOUND_EFFECT_FILES[SOUND_EFFECT_FILES_MAP[effect][0]]; 

              ... 

        return true; 

} 


音效文件放在: /system/media/audio/ui/ 目录下。

10.2.2 音量
public void setStreamVolume(int streamType, int index, int flags) { 

        ensureValidStreamType(streamType); 

        index = rescaleIndex(index * 10, streamType, STREAM_VOLUME_ALIAS[streamType]); 

        setStreamVolumeInt(STREAM_VOLUME_ALIAS[streamType], index, false, true); 

  

        // UI, etc. 

        mVolumePanel.postVolumeChanged(streamType, flags); 

        // Broadcast Intent 

        sendVolumeUpdate(streamType); 

} 

private void setStreamVolumeInt(int streamType, int index, boolean force, boolean lastAudible) { 

        VolumeStreamState streamState = mStreamStates[streamType]; 

        if (streamState.setIndex(index, lastAudible) || force) { 

            // Post message to set system volume (it in turn will post a message 

            // to persist). Do not change volume if stream is muted. 

            if (streamState.muteCount() == 0) { 

                 sendMsg(mAudioHandler, MSG_SET_SYSTEM_VOLUME, streamType, SENDMSG_NOOP, 0, 0, 

                        streamState, 0); 

            } 

        } 

} 

private class AudioHandler extends Handler { 

private void setStreamVolumeIndex(int stream, int index) { 

         AudioSystem.setStreamVolumeIndex(s tream, (index + 5)/10); 

} 

  

        private void setSystemVolume(VolumeStreamState streamState) { 

  

            // Adjust volume 

            setStreamVolumeIndex (streamState.mStreamType, streamState.mIndex); 

... 

         } 

public void handleMessage(Message msg) { 

            int baseMsgWhat = getMsgBase(msg.what); 

  

            switch (baseMsgWhat) { 

  

                case MSG_SET_SYSTEM_VOLUME: 

                    setSystemVolume((VolumeStreamState) msg.obj); 

                     break; 

... 


音量设置通过消息发给消息处理,然后再转向音频系统进行处理:

AudioSystem.setStreamVolumeIndex

10.3 音频系统
文件: frameworks/base/media/java/android/media/AudioSystem.java

10.3.1 音频类型
/* The audio stream for phone calls */ 

    public static final int STREAM_VOICE_CALL = 0; 

     /* The audio stream for system sounds */ 

    public static final int STREAM_SYSTEM = 1; 

    /* The audio stream for the phone ring and message alerts */ 

    public static final int STREAM_RING = 2; 

    /* The audio stream for music playback */ 

    public static final int STREAM_MUSIC = 3; 

    /* The audio stream for alarms */ 

    public static final int STREAM_ALARM = 4; 

    /* The audio stream for notifications */ 

    public static final int STREAM_NOTIFICATION = 5; 

    /* @hide The audio stream for phone calls when connected on bluetooth */ 

    public static final int STREAM_BLUETOOTH_SCO = 6; 

    /* @hide The audio stream for enforced system sounds in certain countries (e.g camera in Japan) */ 

    public static final int STREAM_SYSTEM_ENFORCED = 7; 

    /* @hide The audio stream for DTMF tones */ 

     public static final int STREAM_DTMF = 8; 

    /* @hide The audio stream for text to speech (TTS) */ 

public static final int STREAM_TTS = 9; 

10.3.2 输入输出设备
// output devices 

    public static final int DEVICE_OUT_EARPIECE = 0x1; 

    public static final int DEVICE_OUT_SPEAKER = 0x2; 

    public static final int DEVICE_OUT_WIRED_HEADSET = 0x4; 

    public static final int DEVICE_OUT_WIRED_HEADPHONE = 0x8; 

    public static final int DEVICE_OUT_BLUETOOTH_SCO = 0x10; 

     public static final int DEVICE_OUT_BLUETOOTH_SCO_HEADSET = 0x20; 

    public static final int DEVICE_OUT_BLUETOOTH_SCO_CARKIT = 0x40; 

    public static final int DEVICE_OUT_BLUETOOTH_A2DP = 0x80; 

    public static final int DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100; 

    public static final int DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = 0x200; 

    public static final int DEVICE_OUT_AUX_DIGITAL = 0x400; 

    public static final int DEVICE_OUT_DEFAULT = 0x8000; 

    // input devices 

    public static final int DEVICE_IN_COMMUNICATION = 0x10000; 

    public static final int DEVICE_IN_AMBIENT = 0x20000; 

    public static final int DEVICE_IN_BUILTIN_MIC1 = 0x40000; 

    public static final int DEVICE_IN_BUILTIN_MIC2 = 0x80000; 

    public static final int DEVICE_IN_MIC_ARRAY = 0x100000; 

    public static final int DEVICE_IN_BLUETOOTH_SCO_HEADSET = 0x200000; 

    public static final int DEVICE_IN_WIRED_HEADSET = 0x400000; 

    public static final int DEVICE_IN_AUX_DIGITAL = 0x800000; 

public static final int DEVICE_IN_DEFAULT = 0x80000000; 

10.3.3 转向底层处理
public static native int setParameters(String keyValuePairs); 

public static native int setStreamVolumeIndex(int stream, int index); 


对于参数设置和音量设置都转向 C/C++ 文件进行处理。

10.4 音频系统底层处理
文件: frameworks/base/media/libmedia/AudioSystem.cpp

10.4.1 音量设置
const sp<IAudioPolicyService>& AudioSystem::get_audio_policy_service() 

{ 

    ... 

        sp<IServiceManager> sm = defaultServiceManager(); 

              ... 

        binder = sm->getService(String16("media.audio_policy")); 

           ... 

} 

status_t AudioSystem::setStreamVolumeIndex(stream_type stream, int index) 

{ 

    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service(); 

    if (aps == 0) return PERMISSION_DENIED; 

     return aps->setStreamVolumeIndex(stream, index); 

} 

将参数传给音频策略进行处理。

10.4.1 参数设置
const sp<IAudioFlinger>& AudioSystem::get_audio_flinger() 

{ 

    ... 

        sp<IServiceManager> sm = defaultServiceManager(); 

       .. 

            binder = sm->getService(String16("media.audio_flinger")); 

        ... 

} 

status_t AudioSystem::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs) { 

    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger(); 

    if (af == 0) return PERMISSION_DENIED; 

    return af->setParameters(ioHandle, keyValuePairs); 

} 


将参数传给音频投掷进行处理。

主参数:
const char *AudioParameter::keyRouting = "routing"; 

const char *AudioParameter::keySamplingRate = "sampling_rate"; 

const char *AudioParameter::keyFormat = "format"; 

const char *AudioParameter::keyChannels = "channels"; 

const char *AudioParameter::keyFrameCount = "frame_count"; 

10.5 音频策略
文件: frameworks/base/libs/audioflinger/AudioPolicyService.cpp
void AudioPolicyService::instantiate() { 

    defaultServiceManager()->addService( 

            String16("media.audio_policy"), new AudioPolicyService()); 

} 


注册名为 media.audio_policy 的服务。
AudioPolicyService::AudioPolicyService() 

    : BnAudioPolicyService() , mpPolicyManager(NULL) 

{ 

    ... 

        mpPolicyManager = createAudioPolicyManager(this); 

    ... 

} 


调用音频策略管理器。
status_t AudioPolicyService::setStreamVolumeIndex(AudioSystem::stream_type stream, int index) 

{ 

    ... 

  

    return mpPolicyManager->setStreamVolumeIndex(stream, index); 

} 


将音量控制参数传给音频策略管理器。

10.6 音频投掷
文件: frameworks/base/libs/audioflinger/AudioFlinger.cpp
void AudioFlinger::instantiate() { 

    defaultServiceManager()->addService( 

            String16("media.audio_flinger"), new AudioFlinger()); 

} 


注册名为 media.audio_flinger 的服务
AudioFlinger::AudioFlinger() 

    : BnAudioFlinger(), 

        mAudioHardware(0), mMasterVolume(1.0f), mMasterMute(false), mNextThreadId(0) 

{ 

    ... 

mAudioHardware = AudioHardwareInterface::create(); 

... 

} 

status_t AudioFlinger::setParameters(int ioHandle, const String8& keyValuePairs) 

{ 

    ... 

        result = mAudioHardware->setParameters(keyValuePairs); 

    ... 

} 


将参数转向硬件接口去进行处理。

10.6.1 硬件接口
文件: frameworks/base/libs/audioflinger/AudioHardwareInterface.cpp
AudioHardwareInterface* AudioHardwareInterface::create() 

{ 

   ... 

   hw = createAudioHardware(); 

   ... 

} 

调用音频设备。

10.7 音频策略管理器
文件: hardware/msm7k/libaudio/AudioPolicyManager.cpp
extern "C" AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface) 

{ 

    return new AudioPolicyManager(clientInterface); 

} 

status_t AudioPolicyManager::setStreamVolumeIndex(AudioSystem::stream_type stream, int index) 

{ 

  

   ... 

    for (size_t i = 0; i < mOutputs.size(); i++) { 

         status_t volStatus = checkAndSetVolume(stream, index, mOutputs.keyAt(i), mOutputs.valueAt(i)->device()); 

        if (volStatus != NO_ERROR) { 

            status = volStatus; 

        } 

    } 

    return status; 

} 

设置音量。

10.8 音频设备
文件: hardware/msm7k/libaudio/AudioHardware.cpp
extern "C" AudioHardwareInterface* createAudioHardware (void) { 

    return new AudioHardware(); 

} 

status_t AudioHardware::setParameters(const String8& keyValuePairs) 

{ 

    AudioParameter param = AudioParameter(keyValuePairs); 

    String8 value; 

    String8 key; 

... 

    key = String8(BT_NAME_KEY); 

    if (param.get(key, value) == NO_ERROR) { 

       ... 

    } 

    return NO_ERROR; 

} 


处理 setParameters 参数。

    
[2] listView中item一部分可用
    来源: 互联网  发布时间: 2014-02-18
listView中item部分可用

事实再一次证明有时候 自己还真的好浮躁,以前只是简单的看过这个程序 只是没有细研,今天用到item 部分可用部分不可用 当返回去查阅时 真汗颜 ,好多东西要不归于遗忘 要不归于不重视  什么时候能看过用过 全部记住就好了 那就不用写这个了

public class List5 extends ListActivity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setListAdapter(new MyListAdapter(this));
    }

    private class MyListAdapter extends BaseAdapter {
        public MyListAdapter(Context context) {
            mContext = context;
        }

        public int getCount() {
            return mStrings.length;
        }

        @Override
        public boolean areAllItemsEnabled() {
            return true;
        }

        @Override
        public boolean isEnabled(int position) {
            return !mStrings[position].startsWith("-");
        }

        public Object getItem(int position) {
            return position;
        }

        public long getItemId(int position) {
            return position;
        }

        public View getView(int position, View convertView, ViewGroup parent) {
            TextView tv;
            if (convertView == null) {
                tv = (TextView) LayoutInflater.from(mContext).inflate(
                        android.R.layout.simple_expandable_list_item_1, parent, false);
            } else {
                tv = (TextView) convertView;
            }
            tv.setText(mStrings[position]);
            return tv;
        }

        private Context mContext;
    }
    
    private String[] mStrings = {
            "----------",
            "----------",
            "Abbaye de Belloc",
            "Abbaye du Mont des Cats",
            "Abertam",
            "----------",
            "Abondance",
            "----------",
            "Ackawi",
            "Acorn",
            "Adelost",
            "Affidelice au Chablis",
            "Afuega'l Pitu",
            "Airag",
            "----------",
            "Airedale",
            "Aisy Cendre",
            "----------",
            "Allgauer Emmentaler",
            "Alverca",
            "Ambert",
            "American Cheese",
            "Ami du Chambertin",
            "----------",
            "----------",
            "Anejo Enchilado",
            "Anneau du Vic-Bilh",
            "Anthoriro",
            "----------",
            "----------"
    };

}

 

 

1 楼 zjforandroid 2011-01-13  
为了给你留言,做了半天的论坛测试,其实我注册很久了

    
[3] ADROID 2.1 架构解析 五 电池
    来源: 互联网  发布时间: 2014-02-18
ADROID 2.1 架构解析 5 电池
5 电池
电池涉及的功能有:BatteryStatus、BatteryHealth、BatteryPresent、BatteryLevel、PlugType、BatteryVoltage、BatteryTemperature、BatteryTechnology等,它是种从下而上的表现方式,即底层电池变化后通过uevent事件向上传递电池的当前状态。

5.1 硬件调用
文件:frameworks/base/services/jni/com_android_server_BatteryService.cpp

#define POWER_SUPPLY_PATH "/sys/class/power_supply"

int register_android_server_BatteryService(JNIEnv* env)

{

  ...

  DIR* dir = opendir(POWER_SUPPLY_PATH);

    if (dir == NULL) {

        LOGE("Could not open %s\n", POWER_SUPPLY_PATH);

        return -1;

    }

    while ((entry = readdir(dir))) {

        const char* name = entry->d_name;



        // ignore "." and ".."

        if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) {

            continue;

        }



        char buf[20];

        // Look for "type" file in each subdirectory

        snprintf(path, sizeof(path), "%s/%s/type", POWER_SUPPLY_PATH, name);

        int length = readFromFile(path, buf, sizeof(buf));

        if (length > 0) {

            if (buf[length - 1] == '\n')

                buf[length - 1] = 0;



            if (strcmp(buf, "Mains") == 0) {

                snprintf(path, sizeof(path), "%s/%s/online", POWER_SUPPLY_PATH, name);

                if (access(path, R_OK) == 0)

                    gPaths.acOnlinePath = strdup(path);

            }

            else if (strcmp(buf, "USB") == 0) {

                snprintf(path, sizeof(path), "%s/%s/online", POWER_SUPPLY_PATH, name);

                if (access(path, R_OK) == 0)

                    gPaths.usbOnlinePath = strdup(path);

            }

            else if (strcmp(buf, "Battery") == 0) {

                snprintf(path, sizeof(path), "%s/%s/status", POWER_SUPPLY_PATH, name);

                if (access(path, R_OK) == 0)

                    gPaths.batteryStatusPath = strdup(path);

                snprintf(path, sizeof(path), "%s/%s/health", POWER_SUPPLY_PATH, name);

                if (access(path, R_OK) == 0)

                    gPaths.batteryHealthPath = strdup(path);

                snprintf(path, sizeof(path), "%s/%s/present", POWER_SUPPLY_PATH, name);

                if (access(path, R_OK) == 0)

                    gPaths.batteryPresentPath = strdup(path);

                snprintf(path, sizeof(path), "%s/%s/capacity", POWER_SUPPLY_PATH, name);

                if (access(path, R_OK) == 0)

                    gPaths.batteryCapacityPath = strdup(path);



                snprintf(path, sizeof(path), "%s/%s/voltage_now", POWER_SUPPLY_PATH, name);

                if (access(path, R_OK) == 0) {

                    gPaths.batteryVoltagePath = strdup(path);

                    // voltage_now is in microvolts, not millivolts

                    gVoltageDivisor = 1000;

                } else {

                    snprintf(path, sizeof(path), "%s/%s/batt_vol", POWER_SUPPLY_PATH, name);

                    if (access(path, R_OK) == 0)

                        gPaths.batteryVoltagePath = strdup(path);

                }



                snprintf(path, sizeof(path), "%s/%s/temp", POWER_SUPPLY_PATH, name);

                if (access(path, R_OK) == 0) {

                    gPaths.batteryTemperaturePath = strdup(path);

                } else {

                    snprintf(path, sizeof(path), "%s/%s/batt_temp", POWER_SUPPLY_PATH, name);

                    if (access(path, R_OK) == 0)

                        gPaths.batteryTemperaturePath = strdup(path);

                }



                snprintf(path, sizeof(path), "%s/%s/technology", POWER_SUPPLY_PATH, name);

                if (access(path, R_OK) == 0)

                    gPaths.batteryTechnologyPath = strdup(path);

            }

        }

    }

closedir(dir);

扫描/sys/class/power_supply目录下的文件夹,根据其type文件里的字符串来判断是哪一种类型:Mains、USB还是Battery,然后不同的参数对应着不同的文件



jclass clazz = env->FindClass("com/android/server/BatteryService");



    if (clazz == NULL) {

        LOGE("Can't find com/android/server/BatteryService");

        return -1;

    }

   

    gFieldIds.mAcOnline = env->GetFieldID(clazz, "mAcOnline", "Z");

    gFieldIds.mUsbOnline = env->GetFieldID(clazz, "mUsbOnline", "Z");

    gFieldIds.mBatteryStatus = env->GetFieldID(clazz, "mBatteryStatus", "I");

    gFieldIds.mBatteryHealth = env->GetFieldID(clazz, "mBatteryHealth", "I");

    gFieldIds.mBatteryPresent = env->GetFieldID(clazz, "mBatteryPresent", "Z");

    gFieldIds.mBatteryLevel = env->GetFieldID(clazz, "mBatteryLevel", "I");

    gFieldIds.mBatteryTechnology = env->GetFieldID(clazz, "mBatteryTechnology", "Ljava/lang/String;");

    gFieldIds.mBatteryVoltage = env->GetFieldID(clazz, "mBatteryVoltage", "I");

gFieldIds.mBatteryTemperature = env->GetFieldID(clazz, "mBatteryTemperature", "I");

接口说明:

env->FindClass("com/android/server/BatteryService");  获取指定文件的类。

env->GetFieldID(clazz, "mAcOnline", "Z"); 获取指定类的mAcOnline变量值。

以上代码的功能是:将frameworks/base/services/java/com/android/server/BatteryService.java里的各变量值存到全局变量里。



clazz = env->FindClass("android/os/BatteryManager");

    if (clazz == NULL) {

        LOGE("Can't find android/os/BatteryManager");

        return -1;

    }

    gConstants.statusUnknown = env->GetStaticIntField(clazz,

            env->GetStaticFieldID(clazz, "BATTERY_STATUS_UNKNOWN", "I"));

    gConstants.statusCharging = env->GetStaticIntField(clazz,

            env->GetStaticFieldID(clazz, "BATTERY_STATUS_CHARGING", "I"));

    gConstants.statusDischarging = env->GetStaticIntField(clazz,

            env->GetStaticFieldID(clazz, "BATTERY_STATUS_DISCHARGING", "I"));

    gConstants.statusNotCharging = env->GetStaticIntField(clazz,

            env->GetStaticFieldID(clazz, "BATTERY_STATUS_NOT_CHARGING", "I"));

    gConstants.statusFull = env->GetStaticIntField(clazz,

            env->GetStaticFieldID(clazz, "BATTERY_STATUS_FULL", "I"));

    gConstants.healthUnknown = env->GetStaticIntField(clazz,

            env->GetStaticFieldID(clazz, "BATTERY_HEALTH_UNKNOWN", "I"));

    gConstants.healthGood = env->GetStaticIntField(clazz,

            env->GetStaticFieldID(clazz, "BATTERY_HEALTH_GOOD", "I"));

    gConstants.healthOverheat = env->GetStaticIntField(clazz,

            env->GetStaticFieldID(clazz, "BATTERY_HEALTH_OVERHEAT", "I"));

    gConstants.healthDead = env->GetStaticIntField(clazz,

            env->GetStaticFieldID(clazz, "BATTERY_HEALTH_DEAD", "I"));

    gConstants.healthOverVoltage = env->GetStaticIntField(clazz,

            env->GetStaticFieldID(clazz, "BATTERY_HEALTH_OVER_VOLTAGE", "I"));

    gConstants.healthUnspecifiedFailure = env->GetStaticIntField(clazz,

            env->GetStaticFieldID(clazz, "BATTERY_HEALTH_UNSPECIFIED_FAILURE", "I"));

以上代码的功能是:将frameworks/base/core/java/android/os/BatteryManager.java里类的变量值存到全局变量里。



...

}

static void setBooleanField(JNIEnv* env, jobject obj, const char* path, jfieldID fieldID)

{

    const int SIZE = 16;

    char buf[SIZE];

   

    jboolean value = false;

    if (readFromFile(path, buf, SIZE) > 0) {

        if (buf[0] == '1') {

            value = true;

        }

    }

    env->SetBooleanField(obj, fieldID, value);

}



static void setIntField(JNIEnv* env, jobject obj, const char* path, jfieldID fieldID)

{

    const int SIZE = 128;

    char buf[SIZE];

   

    jint value = 0;

    if (readFromFile(path, buf, SIZE) > 0) {

        value = atoi(buf);

    }

    env->SetIntField(obj, fieldID, value);

}



static void setVoltageField(JNIEnv* env, jobject obj, const char* path, jfieldID fieldID)

{

    const int SIZE = 128;

    char buf[SIZE];



    jint value = 0;

    if (readFromFile(path, buf, SIZE) > 0) {

        value = atoi(buf);

        value /= gVoltageDivisor;

    }

    env->SetIntField(obj, fieldID, value);

}

static void android_server_BatteryService_update(JNIEnv* env, jobject obj)

{

    setBooleanField(env, obj, gPaths.acOnlinePath, gFieldIds.mAcOnline);

    setBooleanField(env, obj, gPaths.usbOnlinePath, gFieldIds.mUsbOnline);

    setBooleanField(env, obj, gPaths.batteryPresentPath, gFieldIds.mBatteryPresent);

   

    setIntField(env, obj, gPaths.batteryCapacityPath, gFieldIds.mBatteryLevel);

    setVoltageField(env, obj, gPaths.batteryVoltagePath, gFieldIds.mBatteryVoltage);

    setIntField(env, obj, gPaths.batteryTemperaturePath, gFieldIds.mBatteryTemperature);

   

    const int SIZE = 128;

    char buf[SIZE];

   

    if (readFromFile(gPaths.batteryStatusPath, buf, SIZE) > 0)

        env->SetIntField(obj, gFieldIds.mBatteryStatus, getBatteryStatus(buf));

    else

        env->SetIntField(obj, gFieldIds.mBatteryStatus,

                         gConstants.statusUnknown);

   

    if (readFromFile(gPaths.batteryHealthPath, buf, SIZE) > 0)

        env->SetIntField(obj, gFieldIds.mBatteryHealth, getBatteryHealth(buf));



    if (readFromFile(gPaths.batteryTechnologyPath, buf, SIZE) > 0)

        env->SetObjectField(obj, gFieldIds.mBatteryTechnology, env->NewStringUTF(buf));

}



static JNINativeMethod sMethods[] = {

     /* name, signature, funcPtr */

       {"native_update", "()V", (void*)android_server_BatteryService_update},

};

接口说明:

env->SetIntField(obj, fieldID, value); 将指定类的变量以整型付值。

env->SetBooleanField(obj, fieldID, value); 将指定类的变量以布尔付值。

以上代码的功能是:

将全局变量的值付给frameworks/base/core/java/android/os/BatteryManager.java里类的变量;并且将ative_update与android_server_BatteryService_update绑定。

5.2 电池服务
文件:frameworks/base/services/java/com/android/server/BatteryService.java

mUEventObserver.startObserving("SUBSYSTEM=power_supply");

private UEventObserver mUEventObserver = new UEventObserver() {

        @Override

        public void onUEvent(UEventObserver.UEvent event) {

            update();

        }

    };

监控uevent事件,响应SUBSYSTEM=power_supply的事件。

private synchronized final void update() {

        native_update();

            ...

        if (mAcOnline) {

            mPlugType = BatteryManager.BATTERY_PLUGGED_AC;

        } else if (mUsbOnline) {

            mPlugType = BatteryManager.BATTERY_PLUGGED_USB;

        } else {

            mPlugType = BATTERY_PLUGGED_NONE;

        }

        ...

        sendIntent();

              ...

    }



    private final void sendIntent() {

        //  Pack up the values and broadcast them to everyone

        Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED);

        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);

        try {

            mBatteryStats.setOnBattery(mPlugType == BATTERY_PLUGGED_NONE, mBatteryLevel);

        } catch (RemoteException e) {

            // Should never happen.

        }

       

        int icon = getIcon(mBatteryLevel);



        intent.putExtra(BatteryManager.EXTRA_STATUS, mBatteryStatus);

        intent.putExtra(BatteryManager.EXTRA_HEALTH, mBatteryHealth);

        intent.putExtra(BatteryManager.EXTRA_PRESENT, mBatteryPresent);

        intent.putExtra(BatteryManager.EXTRA_LEVEL, mBatteryLevel);

        intent.putExtra(BatteryManager.EXTRA_SCALE, BATTERY_SCALE);

        intent.putExtra(BatteryManager.EXTRA_ICON_SMALL, icon);

        intent.putExtra(BatteryManager.EXTRA_PLUGGED, mPlugType);

        intent.putExtra(BatteryManager.EXTRA_VOLTAGE, mBatteryVoltage);

        intent.putExtra(BatteryManager.EXTRA_TEMPERATURE, mBatteryTemperature);

        intent.putExtra(BatteryManager.EXTRA_TECHNOLOGY, mBatteryTechnology);



        if (false) {

            Log.d(TAG, "updateBattery level:" + mBatteryLevel +

                    " scale:" + BATTERY_SCALE + " status:" + mBatteryStatus +

                    " health:" + mBatteryHealth +  " present:" + mBatteryPresent +

                    " voltage: " + mBatteryVoltage +

                    " temperature: " + mBatteryTemperature +

                    " technology: " + mBatteryTechnology +

                    " AC powered:" + mAcOnline + " USB powered:" + mUsbOnline +

                    " icon:" + icon );

        }



        ActivityManagerNative.broadcastStickyIntent(intent, null);

    }

以上代码的功能是:

通过native_update();更新各状态变量的值,如:

private boolean mAcOnline;

    private boolean mUsbOnline;

    private int mBatteryStatus;

    private int mBatteryHealth;

    private boolean mBatteryPresent;

    private int mBatteryLevel;

    private int mBatteryVoltage;

    private int mBatteryTemperature;

    private String mBatteryTechnology;

    private boolean mBatteryLevelCritical;

然后通过:

intent.putExtra(BatteryManager.EXTRA_STATUS, mBatteryStatus);

        intent.putExtra(BatteryManager.EXTRA_HEALTH, mBatteryHealth);

        intent.putExtra(BatteryManager.EXTRA_PRESENT, mBatteryPresent);

        intent.putExtra(BatteryManager.EXTRA_LEVEL, mBatteryLevel);

        intent.putExtra(BatteryManager.EXTRA_SCALE, BATTERY_SCALE);

        intent.putExtra(BatteryManager.EXTRA_ICON_SMALL, icon);

        intent.putExtra(BatteryManager.EXTRA_PLUGGED, mPlugType);

        intent.putExtra(BatteryManager.EXTRA_VOLTAGE, mBatteryVoltage);

        intent.putExtra(BatteryManager.EXTRA_TEMPERATURE, mBatteryTemperature);

        intent.putExtra(BatteryManager.EXTRA_TECHNOLOGY, mBatteryTechnology);

              ActivityManagerNative.broadcastStickyIntent(intent, null);

发布给各实体窗口取用,EXTRA_STATUS等对应的字符是:

文件:frameworks/base/core/java/android/os/BatteryManager.java

public static final String EXTRA_STATUS = "status";

    public static final String EXTRA_HEALTH = "health";

    public static final String EXTRA_PRESENT = "present";

    public static final String EXTRA_LEVEL = "level";

    public static final String EXTRA_SCALE = "scale";

    public static final String EXTRA_ICON_SMALL = "icon-small";

    public static final String EXTRA_PLUGGED = "plugged";

    public static final String EXTRA_VOLTAGE = "voltage";

    public static final String EXTRA_TEMPERATURE = "temperature";

    public static final String EXTRA_TECHNOLOGY = "technology";

5.3 显示电池状态
文件:packages/apps/DeskClock/src/com/android/deskclock/DeskClock.java

private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {

        @Override

        public void onReceive(Context context, Intent intent) {

            final String action = intent.getAction();

            if (Intent.ACTION_DATE_CHANGED.equals(action)) {

                refreshDate();

            } else if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {

                handleBatteryUpdate(

                    intent.getIntExtra("status", BATTERY_STATUS_UNKNOWN),

                    intent.getIntExtra("level", 0));

            } else if (Intent.ACTION_DOCK_EVENT.equals(action)) {

                int state = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, -1);

                if (DEBUG) Log.d(LOG_TAG, "ACTION_DOCK_EVENT, state=" + state);

                if (state == Intent.EXTRA_DOCK_STATE_UNDOCKED) {

                    if (mLaunchedFromDock) {

                        // moveTaskToBack(false);

                        finish();

                    }

                    mLaunchedFromDock = false;

                }

            }

        }

    };

// Adapted from KeyguardUpdateMonitor.java

    private void handleBatteryUpdate(int plugStatus, int batteryLevel) {

        final boolean pluggedIn = (plugStatus == BATTERY_STATUS_CHARGING || plugStatus == BATTERY_STATUS_FULL);

        if (pluggedIn != mPluggedIn) {

            setWakeLock(pluggedIn);



            if (pluggedIn) {

                // policy: update weather info when attaching to power

                requestWeatherDataFetch();

            }

        }

        if (pluggedIn != mPluggedIn || batteryLevel != mBatteryLevel) {

            mBatteryLevel = batteryLevel;

            mPluggedIn = pluggedIn;

            refreshBattery();

        }

    }



    private void refreshBattery() {

        if (mBatteryDisplay == null) return;



        if (mPluggedIn /* || mBatteryLevel < LOW_BATTERY_THRESHOLD */) {

            mBatteryDisplay.setCompoundDrawablesWithIntrinsicBounds(

                0, 0, android.R.drawable.ic_lock_idle_charging, 0);

            mBatteryDisplay.setText(

                getString(R.string.battery_charging_level, mBatteryLevel));

            mBatteryDisplay.setVisibility(View.VISIBLE);

        } else {

            mBatteryDisplay.setVisibility(View.INVISIBLE);

        }

    }

由以上代码可知,程序通过接收广播信息,获取电池的当前节数:intent.getIntExtra("level", 0));,然后再将其显示。

    
最新技术文章:
▪Android开发之登录验证实例教程
▪Android开发之注册登录方法示例
▪Android获取手机SIM卡运营商信息的方法
▪Android实现将已发送的短信写入短信数据库的...
▪Android发送短信功能代码
▪Android根据电话号码获得联系人头像实例代码
▪Android中GPS定位的用法实例
▪Android实现退出时关闭所有Activity的方法
▪Android实现文件的分割和组装
▪Android录音应用实例教程
▪Android双击返回键退出程序的实现方法
▪Android实现侦听电池状态显示、电量及充电动...
▪Android获取当前已连接的wifi信号强度的方法
▪Android实现动态显示或隐藏密码输入框的内容
▪根据USER-AGENT判断手机类型并跳转到相应的app...
▪Android Touch事件分发过程详解
▪Android中实现为TextView添加多个可点击的文本
▪Android程序设计之AIDL实例详解
▪Android显式启动与隐式启动Activity的区别介绍
▪Android按钮单击事件的四种常用写法总结
▪Android消息处理机制Looper和Handler详解
▪Android实现Back功能代码片段总结
▪Android实用的代码片段 常用代码总结
▪Android实现弹出键盘的方法
▪Android中通过view方式获取当前Activity的屏幕截...
▪Android提高之自定义Menu(TabMenu)实现方法
▪Android提高之多方向抽屉实现方法
▪Android提高之MediaPlayer播放网络音频的实现方法...
▪Android提高之MediaPlayer播放网络视频的实现方法...
▪Android提高之手游转电视游戏的模拟操控
 


站内导航:


特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

©2012-2021,,E-mail:www_#163.com(请将#改为@)

浙ICP备11055608号-3