欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

android系統(tǒng)按鍵音framework流程源碼詳細解析

 更新時間:2022年08月17日 10:01:34   作者:假裝多好123  
這篇文章主要為大家詳細介紹了android系統(tǒng)按鍵音framework流程源碼,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

android 系統(tǒng)按鍵音framework源碼解析(基于android 9.0)

今天來看下android中按鍵音的處理,首先看下按鍵是在那里開啟的。然后再看看當按下按鍵后一個按鍵音是怎么播放出來的。

1.首先在setting app里面 SoundFragment.java

private void setSoundEffectsEnabled(boolean enabled) {
? ? ? ? ? ? mAudioManager = (AudioManager) getActivity().getSystemService(Context.AUDIO_SERVICE); //1
? ? ? ? if (enabled) {
? ? ? ? ? ? mAudioManager.loadSoundEffects(); ? // 從這里可以看到調用AudioManager里面的方法打開按鍵音
? ? ? ? } else {
? ? ? ? ? ? mAudioManager.unloadSoundEffects();
? ? ? ? }
? ? ? ? Settings.System.putInt(getActivity().getContentResolver(),
? ? ? ? ? ? ? ? Settings.System.SOUND_EFFECTS_ENABLED, enabled ? 1 : 0);
? ? }

大家可能很好奇像AudioManager,WifiManager等,都是通過getSystemService 這個方法得到的。這里花一點時間順帶先說一下1處這個吧。我們先一步一步來看。(其實最終還是回到AudioManager方法里面的,不感興趣的可以直接跳過)。

2. framework/base/core/java/android/app/Activity.java

@Override
? ? public Object getSystemService(@ServiceName @NonNull String name) {
? ? ? ? if (getBaseContext() == null) {
? ? ? ? ? ? throw new IllegalStateException(
? ? ? ? ? ? ? ? ? ? "System services not available to Activities before onCreate()");
? ? ? ? }
? ? ? ? if (WINDOW_SERVICE.equals(name)) {
? ? ? ? ? ? return mWindowManager;
? ? ? ? } else if (SEARCH_SERVICE.equals(name)) {
? ? ? ? ? ? ensureSearchManager();
? ? ? ? ? ? return mSearchManager;
? ? ? ? }
? ? ? ? return super.getSystemService(name); ? ?//除了WINDOW_SERVICE和SEARCH_SERVICE外,其他服務都在父類中
? ? }

除了WINDOW_SERVICE和SEARCH_SERVICE外,其他服務都在父類中

3.framework/base/core/java/android/view/ContextThemeWrapper.java

@Override
? ? public Object getSystemService(String name) {
? ? ? ? if (LAYOUT_INFLATER_SERVICE.equals(name)) {
? ? ? ? ? ? if (mInflater == null) {
? ? ? ? ? ? ? ? mInflater = LayoutInflater.from(getBaseContext()).cloneInContext(this);
? ? ? ? ? ? }
? ? ? ? ? ? return mInflater;
? ? ? ? ? ??
? ? ? ? }
? ? ? ? return getBaseContext().getSystemService(name); ?//還要再往上
? ? }

4. framework/base/core/java/android/content/Context.java

@SuppressWarnings("unchecked")
? ? public final @Nullable <T> T getSystemService(@NonNull Class<T> serviceClass) {
? ? ? ? // Because subclasses may override getSystemService(String) we cannot
? ? ? ? // perform a lookup by class alone. ?We must first map the class to its
? ? ? ? // service name then invoke the string-based method.
? ? ? ? String serviceName = getSystemServiceName(serviceClass);
? ? ? ? return serviceName != null ? (T)getSystemService(serviceName) : null;
? ? }
/**
? ? ?* Gets the name of the system-level service that is represented by the specified class.
? ? ?*
? ? ?* @param serviceClass The class of the desired service.
? ? ?* @return The service name or null if the class is not a supported system service.
? ? ?*/
? ? public abstract @Nullable String getSystemServiceName(@NonNull Class<?> serviceClass);

? ? /**
? ? ?* Use with {@link #getSystemService(String)} to retrieve a
? ? ?* {@link android.os.PowerManager} for controlling power management,
? ? ?* including "wake locks," which let you keep the device on while
? ? ?* you're running long tasks.
? ? ?*/
? ? public static final String POWER_SERVICE = "power";

? ?/**
? ? ?* Use with {@link #getSystemService(String)} to retrieve a
? ? ?* {@link android.view.WindowManager} for accessing the system's window
? ? ?* manager.
? ? ?*
? ? ?* @see #getSystemService(String)
? ? ?* @see android.view.WindowManager
? ? ?*/
? ? public static final String WINDOW_SERVICE = "window";

? ? /**
? ? ?* Use with {@link #getSystemService(String)} to retrieve a {@link
? ? ?* android.net.wifi.WifiManager} for handling management of
? ? ?* Wi-Fi access.
? ? ?*
? ? ?* @see #getSystemService(String)
? ? ?* @see android.net.wifi.WifiManager
? ? ?*/
? ? public static final String WIFI_SERVICE = "wifi";

? ? /**
? ? ?* Use with {@link #getSystemService(String)} to retrieve a
? ? ?* {@link android.media.AudioManager} for handling management of volume,
? ? ?* ringer modes and audio routing.
? ? ?*
? ? ?* @see #getSystemService(String)
? ? ?* @see android.media.AudioManager ? ?//在audiomanager 里面
? ? ?*/
? ? public static final String AUDIO_SERVICE = "audio";
framework/base/media/java/android/media/AudioManager.java
**
?* AudioManager provides access to volume and ringer mode control.
?*/
@SystemService(Context.AUDIO_SERVICE) ?//通過注解來講AUDIO_SERVICE與AudioManager綁定在一塊
public class AudioManager {

? ? private Context mOriginalContext;
? ? private Context mApplicationContext;
? ? private long mVolumeKeyUpTime;

這里可以看到,之前那些wifimanager,audiomanager 都是這樣來設置得到的。
好了,再繼續(xù)說按鍵音的事,就是到AudioManager里面。

5. framework/base/media/java/android/media/AudioManager.java

/**
? ? ?* ?Load Sound effects.
? ? ?* ?This method must be called when sound effects are enabled.
*/
? ? public void loadSoundEffects() {
? ? ? ? final IAudioService service = getService();
? ? ? ? try {
? ? ? ? ? ? service.loadSoundEffects();
? ? ? ? } catch (RemoteException e) {
? ? ? ? ? ? throw e.rethrowFromSystemServer();
? ? ? ? }
? ? }
private static IAudioService getService()
{
? ? if (sService != null) {
? ? ? ? return sService;
? ? }
? ? IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
? ? sService = IAudioService.Stub.asInterface(b);
? ? return sService;
}

這里不得不再說一下。其實最后還是跑到AudiioService里面了。通過跨進程binder來拿到audioservice的對象。這里再順帶說一下那些service都是在哪里設置的。

6. framework/base/core/java/android/os/ServiceManager.java

/**
? ? ?* Returns a reference to a service with the given name
? ? ?* @param name the name of the service to get
? ? ?* @return a reference to the service, or <code>null</code> if the service doesn't exist
*/
? ? public static IBinder getService(String name) {
? ? ? ? try {
? ? ? ? ? ? IBinder service = sCache.get(name); ? //在這個里面拿到
? ? ? ? ? ? if (service != null) {
? ? ? ? ? ? ? ? return service;
? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? return Binder.allowBlocking(rawGetService(name));
? ? ? ? ? ? }
? ? ? ? } catch (RemoteException e) {
? ? ? ? ? ? Log.e(TAG, "error in getService", e);
? ? ? ? }
? ? ? ? return null;
? ? }
/**
? ? ?* Cache for the "well known" services, such as WM and AM.
*/
? ? private static HashMap<String, IBinder> sCache = new HashMap<String, IBinder>();

? ? /**
? ? ?* This is only intended to be called when the process is first being brought
? ? ?* up and bound by the activity manager. There is only one thread in the process
? ? ?* at that time, so no locking is done.
? ? ?*
? ? ?* @param cache the cache of service references
? ? ?* @hide
? ? ?*/
? ? public static void initServiceCache(Map<String, IBinder> cache) {
? ? ? ? if (sCache.size() != 0) {
? ? ? ? ? ? throw new IllegalStateException("setServiceCache may only be called once");
? ? ? ? }
? ? ? ? sCache.putAll(cache);
? ? }

從上面可以看到 sCache 是一個Map。所以之前拿到的那些管理的對象(wifiManager,AudioManage,WindowManager等等),都是通過get map拿到的。

7. framework/base/services/core/java/com/android/server/audio/AudioService.java

/**
? ? ?* Loads samples into the soundpool.
? ? ?* This method must be called at first when sound effects are enabled
? ? ?*/
? ? public boolean loadSoundEffects() {
? ? ? ? int attempts = 3;
? ? ? ? LoadSoundEffectReply reply = new LoadSoundEffectReply();

? ? ? ? synchronized (reply) {
? ? ? ? ? ? sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, reply, 0); //發(fā)送消息
? ? ? ? ? ? while ((reply.mStatus == 1) && (attempts-- > 0)) {
? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? reply.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
? ? ? ? ? ? ? ? } catch (InterruptedException e) {
? ? ? ? ? ? ? ? ? ? Log.w(TAG, "loadSoundEffects Interrupted while waiting sound pool loaded.");
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? return (reply.mStatus == 0);
? ? }

當在setting里面打開按鍵音之后會調這來,從類名就可以看出是加載事件。后面按鍵聲的的播放之前也會調用到這里來。

case MSG_LOAD_SOUND_EFFECTS:
? ? ? ? ? ? ? ? ? ? //FIXME: onLoadSoundEffects() should be executed in a separate thread as it
? ? ? ? ? ? ? ? ? ? // can take several dozens of milliseconds to complete
? ? ? ? ? ? ? ? ? ? boolean loaded = onLoadSoundEffects(); ? // 調用這個方法
? ? ? ? ? ? ? ? ? ? if (msg.obj != null) {
? ? ? ? ? ? ? ? ? ? ? ? LoadSoundEffectReply reply = (LoadSoundEffectReply)msg.obj;
? ? ? ? ? ? ? ? ? ? ? ? synchronized (reply) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? reply.mStatus = loaded ? 0 : -1;
? ? ? ? ? ? ? ? ? ? ? ? ? ? reply.notify();
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? break;
private boolean onLoadSoundEffects() {
? ? ? ? ? ? int status;

? ? ? ? ? ? synchronized (mSoundEffectsLock) {
? ? ? ? ? ? ? ? if (!mSystemReady) {
? ? ? ? ? ? ? ? ? ? Log.w(TAG, "onLoadSoundEffects() called before boot complete");
? ? ? ? ? ? ? ? ? ? return false;
? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? if (mSoundPool != null) {
? ? ? ? ? ? ? ? ? ? return true;
? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? loadTouchSoundAssets(); ? ? // 記載要播放聲音的資源

? ? ? ? ? ? ? ? mSoundPool = new SoundPool.Builder()
? ? ? ? ? ? ? ? ? ? ? ? .setMaxStreams(NUM_SOUNDPOOL_CHANNELS)
? ? ? ? ? ? ? ? ? ? ? ? .setAudioAttributes(new AudioAttributes.Builder()
? ? ? ? ? ? ? ? ? ? ? ? ? ? .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
? ? ? ? ? ? ? ? ? ? ? ? ? ? .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
? ? ? ? ? ? ? ? ? ? ? ? ? ? .build())
? ? ? ? ? ? ? ? ? ? ? ? .build(); ? ?//鏈式調用
? ? ? ? ? ? ? ? mSoundPoolCallBack = null;
? ? ? ? ? ? ? ? mSoundPoolListenerThread = new SoundPoolListenerThread();
? ? ? ? ? ? ? ? mSoundPoolListenerThread.start();
? ? ? ? ? ? ? ? int attempts = 3;
? ? ? ? ? ? ? ? while ((mSoundPoolCallBack == null) && (attempts-- > 0)) {
? ? ? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? ? ? // Wait for mSoundPoolCallBack to be set by the other thread
? ? ? ? ? ? ? ? ? ? ? ? mSoundEffectsLock.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
? ? ? ? ? ? ? ? ? ? } catch (InterruptedException e) {
? ? ? ? ? ? ? ? ? ? ? ? Log.w(TAG, "Interrupted while waiting sound pool listener thread.");
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? if (mSoundPoolCallBack == null) {
? ? ? ? ? ? ? ? ? ? Log.w(TAG, "onLoadSoundEffects() SoundPool listener or thread creation error");
? ? ? ? ? ? ? ? ? ? if (mSoundPoolLooper != null) {
? ? ? ? ? ? ? ? ? ? ? ? mSoundPoolLooper.quit();
? ? ? ? ? ? ? ? ? ? ? ? mSoundPoolLooper = null;
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? mSoundPoolListenerThread = null;
? ? ? ? ? ? ? ? ? ? mSoundPool.release();
? ? ? ? ? ? ? ? ? ? mSoundPool = null;
? ? ? ? ? ? ? ? ? ? return false;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? /*
? ? ? ? ? ? ? ? ?* poolId table: The value -1 in this table indicates that corresponding
? ? ? ? ? ? ? ? ?* file (same index in SOUND_EFFECT_FILES[] has not been loaded.
? ? ? ? ? ? ? ? ?* Once loaded, the value in poolId is the sample ID and the same
? ? ? ? ? ? ? ? ?* sample can be reused for another effect using the same file.
? ? ? ? ? ? ? ? ?*/
? ? ? ? ? ? ? ? int[] poolId = new int[SOUND_EFFECT_FILES.size()];
? ? ? ? ? ? ? ? for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.size(); fileIdx++) {
? ? ? ? ? ? ? ? ? ? poolId[fileIdx] = -1;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? /*
? ? ? ? ? ? ? ? ?* Effects whose value in SOUND_EFFECT_FILES_MAP[effect][1] is -1 must be loaded.
? ? ? ? ? ? ? ? ?* If load succeeds, value in SOUND_EFFECT_FILES_MAP[effect][1] is > 0:
? ? ? ? ? ? ? ? ?* this indicates we have a valid sample loaded for this effect.
? ? ? ? ? ? ? ? ?*/

? ? ? ? ? ? ? ? int numSamples = 0;
? ? ? ? ? ? ? ? for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) {
? ? ? ? ? ? ? ? ? ? // Do not load sample if this effect uses the MediaPlayer
? ? ? ? ? ? ? ? ? ? if (SOUND_EFFECT_FILES_MAP[effect][1] == 0) {
? ? ? ? ? ? ? ? ? ? ? ? continue;
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == -1) {
? ? ? ? ? ? ? ? ? ? ? ? String filePath = getSoundEffectFilePath(effect);
? ? ? ? ? ? ? ? ? ? ? ? int sampleId = mSoundPool.load(filePath, 0);
? ? ? ? ? ? ? ? ? ? ? ? if (sampleId <= 0) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? Log.w(TAG, "Soundpool could not load file: "+filePath);
? ? ? ? ? ? ? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? ? ? ? ? ? ? SOUND_EFFECT_FILES_MAP[effect][1] = sampleId;
? ? ? ? ? ? ? ? ? ? ? ? ? ? poolId[SOUND_EFFECT_FILES_MAP[effect][0]] = sampleId;
? ? ? ? ? ? ? ? ? ? ? ? ? ? numSamples++;
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? ? ? ? ? SOUND_EFFECT_FILES_MAP[effect][1] =
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? poolId[SOUND_EFFECT_FILES_MAP[effect][0]];
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? // wait for all samples to be loaded
? ? ? ? ? ? ? ? if (numSamples > 0) {
? ? ? ? ? ? ? ? ? ? mSoundPoolCallBack.setSamples(poolId);

? ? ? ? ? ? ? ? ? ? attempts = 3;
? ? ? ? ? ? ? ? ? ? status = 1;
? ? ? ? ? ? ? ? ? ? while ((status == 1) && (attempts-- > 0)) {
? ? ? ? ? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? ? ? ? ? mSoundEffectsLock.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
? ? ? ? ? ? ? ? ? ? ? ? ? ? status = mSoundPoolCallBack.status();
? ? ? ? ? ? ? ? ? ? ? ? } catch (InterruptedException e) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? Log.w(TAG, "Interrupted while waiting sound pool callback.");
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? ? ? status = -1;
? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? if (mSoundPoolLooper != null) {
? ? ? ? ? ? ? ? ? ? mSoundPoolLooper.quit();
? ? ? ? ? ? ? ? ? ? mSoundPoolLooper = null;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? mSoundPoolListenerThread = null;
? ? ? ? ? ? ? ? if (status != 0) {
? ? ? ? ? ? ? ? ? ? Log.w(TAG,
? ? ? ? ? ? ? ? ? ? ? ? ? ? "onLoadSoundEffects(), Error "+status+ " while loading samples");
? ? ? ? ? ? ? ? ? ? for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) {
? ? ? ? ? ? ? ? ? ? ? ? if (SOUND_EFFECT_FILES_MAP[effect][1] > 0) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? SOUND_EFFECT_FILES_MAP[effect][1] = -1;
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? mSoundPool.release();
? ? ? ? ? ? ? ? ? ? mSoundPool = null;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? return (status == 0);
? ? ? ? }

8.接下來看看當按下一個按鍵后按鍵音的觸發(fā)

當按下一個按鍵或者焦點落到一個view上時,會有很多種情況,如下,

無論如何,最后都會調用到如下的方法中

framework/base/media/java/android/media/AudioManager.java

public void ?playSoundEffect(int effectType) {
? ? ? ? if (effectType < 0 || effectType >= NUM_SOUND_EFFECTS) {
? ? ? ? ? ? return;
? ? ? ? }
? ? ? ? if (!querySoundEffectsEnabled(Process.myUserHandle().getIdentifier())) {
? ? ? ? ? ? return;
? ? ? ? }
? ? ? ? final IAudioService service = getService();
? ? ? ? try {
? ? ? ? ? ? service.playSoundEffect(effectType);
? ? ? ? } catch (RemoteException e) {
? ? ? ? ? ? throw e.rethrowFromSystemServer();
? ? ? ? }
? ? }

還是會到AudioSetvice中。

9.framework/base/services/core/java/com/android/server/audio/AudioService.java

/** @see AudioManager#playSoundEffect(int) */
? ? public void playSoundEffect(int effectType) {
? ? ? ? playSoundEffectVolume(effectType, -1.0f);
? ? }

? ? /** @see AudioManager#playSoundEffect(int, float) */
? ? public void playSoundEffectVolume(int effectType, float volume) {
? ? ? ? // do not try to play the sound effect if the system stream is muted
? ? ? ? if (isStreamMutedByRingerOrZenMode(STREAM_SYSTEM)) {
? ? ? ? ? ? return;
? ? ? ? }

? ? ? ? if (effectType >= AudioManager.NUM_SOUND_EFFECTS || effectType < 0) {
? ? ? ? ? ? Log.w(TAG, "AudioService effectType value " + effectType + " out of range");
? ? ? ? ? ? return;
? ? ? ? }

? ? ? ? sendMsg(mAudioHandler, MSG_PLAY_SOUND_EFFECT, SENDMSG_QUEUE, // 發(fā)送消息
? ? ? ? ? ? ? ? effectType, (int) (volume * 1000), null, 0);
? ? }
case MSG_PLAY_SOUND_EFFECT:
? ? ? ? ? ? ? ? ? ? onPlaySoundEffect(msg.arg1, msg.arg2);
? ? ? ? ? ? ? ? ? ? break;

private void onPlaySoundEffect(int effectType, int volume) {
? ? ? ? ? ? synchronized (mSoundEffectsLock) {

? ? ? ? ? ? ? ? onLoadSoundEffects(); ? ?//上面提到過的的加載

? ? ? ? ? ? ? ? if (mSoundPool == null) {
? ? ? ? ? ? ? ? ? ? return;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? float volFloat;
? ? ? ? ? ? ? ? // use default if volume is not specified by caller
? ? ? ? ? ? ? ? if (volume < 0) {
? ? ? ? ? ? ? ? ? ? volFloat = (float)Math.pow(10, (float)sSoundEffectVolumeDb/20);
? ? ? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? ? ? volFloat = volume / 1000.0f;
? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? if (SOUND_EFFECT_FILES_MAP[effectType][1] > 0) {
? ? ? ? ? ? ? ? ? ? mSoundPool.play(SOUND_EFFECT_FILES_MAP[effectType][1],
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? volFloat, volFloat, 0, 0, 1.0f);
? ? ? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? ? ? MediaPlayer mediaPlayer = new MediaPlayer();
? ? ? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? ? ? String filePath = getSoundEffectFilePath(effectType); ?//得到播放音頻資源的地址。如果要替換資源,可以到此位置替換
? ? ? ? ? ? ? ? ? ? ? ? mediaPlayer.setDataSource(filePath);
? ? ? ? ? ? ? ? ? ? ? ? mediaPlayer.setAudioStreamType(AudioSystem.STREAM_SYSTEM);
? ? ? ? ? ? ? ? ? ? ? ? mediaPlayer.prepare();
? ? ? ? ? ? ? ? ? ? ? ? mediaPlayer.setVolume(volFloat);
? ? ? ? ? ? ? ? ? ? ? ? mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
? ? ? ? ? ? ? ? ? ? ? ? ? ? public void onCompletion(MediaPlayer mp) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? cleanupPlayer(mp);
? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? });
? ? ? ? ? ? ? ? ? ? ? ? mediaPlayer.setOnErrorListener(new OnErrorListener() {
? ? ? ? ? ? ? ? ? ? ? ? ? ? public boolean onError(MediaPlayer mp, int what, int extra) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? cleanupPlayer(mp);
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? return true;
? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? });
? ? ? ? ? ? ? ? ? ? ? ? mediaPlayer.start(); ? ? //開始播放
? ? ? ? ? ? ? ? ? ? } catch (IOException ex) {
? ? ? ? ? ? ? ? ? ? ? ? Log.w(TAG, "MediaPlayer IOException: "+ex);
? ? ? ? ? ? ? ? ? ? } catch (IllegalArgumentException ex) {
? ? ? ? ? ? ? ? ? ? ? ? Log.w(TAG, "MediaPlayer IllegalArgumentException: "+ex);
? ? ? ? ? ? ? ? ? ? } catch (IllegalStateException ex) {
? ? ? ? ? ? ? ? ? ? ? ? Log.w(TAG, "MediaPlayer IllegalStateException: "+ex);
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }

到此,android 系統(tǒng)的按鍵音的流程就走完了。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

最新評論