4

当我们使用 Thread 播放音乐时,该项目仍然会弹出 ANR。

--这里有 ANR keyDispatchingTimedOut 日志和 SoundManager 供参考----- -- 日志开始 ---:

DALVIK THREADS:
(mutexes: tll=0 tsl=0 tscl=0 ghl=0 hwl=0 hwll=0)
"main" prio=5 tid=1 NATIVE
  | group="main" sCount=1 dsCount=0 obj=0x40022300 self=0xce70
  | sysTid=2144 nice=0 sched=0/0 cgrp=default handle=-1345006496
  at android.os.MessageQueue.nativePollOnce(Native Method)
  at android.os.MessageQueue.next(MessageQueue.java:119)
  at android.os.Looper.loop(Looper.java:110)
  at android.app.ActivityThread.main(ActivityThread.java:3683)
  at java.lang.reflect.Method.invokeNative(Native Method)
  at java.lang.reflect.Method.invoke(Method.java:507)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:864)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:622)
  at dalvik.system.NativeStart.main(Native Method)

"SoundPoolThread" prio=5 tid=11 NATIVE
  | group="main" sCount=1 dsCount=0 obj=0x405b84d0 self=0x236e20
  | sysTid=2155 nice=0 sched=0/0 cgrp=default handle=2170064
  at dalvik.system.NativeStart.run(Native Method)

"SoundPool" prio=5 tid=10 NATIVE
  | group="main" sCount=1 dsCount=0 obj=0x405ba348 self=0x212120
  | sysTid=2154 nice=0 sched=0/0 cgrp=default handle=2189688
  at dalvik.system.NativeStart.run(Native Method)

"Timer-0" prio=5 tid=9 TIMED_WAIT
  | group="main" sCount=1 dsCount=0 obj=0x4056c488 self=0x212af8
  | sysTid=2152 nice=0 sched=0/0 cgrp=default handle=2151992
  at java.lang.Object.wait(Native Method)
  - waiting on <0x4056c488> (a java.util.Timer$TimerImpl)
  at java.lang.Object.wait(Object.java:395)
  at java.util.Timer$TimerImpl.run(Timer.java:238)

"Binder Thread #2" prio=5 tid=7 NATIVE
  | group="main" sCount=1 dsCount=0 obj=0x40514f50 self=0x1aa300
  | sysTid=2150 nice=0 sched=0/0 cgrp=default handle=590104
  at dalvik.system.NativeStart.run(Native Method)

"Binder Thread #1" prio=5 tid=6 NATIVE
  | group="main" sCount=1 dsCount=0 obj=0x40514e88 self=0x197748
  | sysTid=2149 nice=0 sched=0/0 cgrp=default handle=1667104
  at dalvik.system.NativeStart.run(Native Method)

"Compiler" daemon prio=5 tid=5 VMWAIT
  | group="system" sCount=1 dsCount=0 obj=0x40511908 self=0x197610
  | sysTid=2148 nice=0 sched=0/0 cgrp=default handle=1667040
  at dalvik.system.NativeStart.run(Native Method)

"Signal Catcher" daemon prio=5 tid=4 RUNNABLE
  | group="system" sCount=0 dsCount=0 obj=0x40511848 self=0x198000
  | sysTid=2147 nice=0 sched=0/0 cgrp=default handle=586176
  at dalvik.system.NativeStart.run(Native Method)

"GC" daemon prio=5 tid=3 VMWAIT
  | group="system" sCount=1 dsCount=0 obj=0x405117a0 self=0x196760
  | sysTid=2146 nice=0 sched=0/0 cgrp=default handle=592768
  at dalvik.system.NativeStart.run(Native Method)

"HeapWorker" daemon prio=5 tid=2 VMWAIT
  | group="system" sCount=1 dsCount=0 obj=0x405116e8 self=0x8ff80
  | sysTid=2145 nice=0 sched=0/0 cgrp=default handle=592704
  at dalvik.system.NativeStart.run(Native Method)

// 下面是我的 SoundManager 类供参考。

public class SoundManager {

private static final String TAG = "SoundManager";
private static boolean DEBUG = IConstants.DEBUG;

private SoundPool soundPool;
private HashMap<String, Integer> mapSound = new HashMap<String, Integer>();
private AudioManager audioManager;
private String inUseThemePath;
private int currentPlayStreamID;
private int currentPlayNonstop = 0;

private SoundPlayTask soundPlayTask = null;

public SoundManager(Context context) {
    audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
}

public void playSound(String soundFile, int loop, int nonstop) {
    if (soundPool == null)
        return;

    if (DEBUG) Log.i(TAG, "playSound enter");
    if (soundPlayTask != null) {

        soundPlayTask.cancel();
        try {
            soundPlayTask.join(100);
            if (soundPlayTask.isAlive()) {
                if (DEBUG) Log.i(TAG, "force stop the thread");
                soundPlayTask.interrupt();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        soundPlayTask = null;
    }
    soundPlayTask = new SoundPlayTask(this, soundFile, loop, nonstop);
    soundPlayTask.start();
             Log.i(TAG, "playSound leave");
}

public void stopSound() {

    if (soundPool == null)
        return;
    if (soundPlayTask == null)
        return;


    soundPlayTask.cancel();
    try {

        soundPlayTask.join(100);
        if (soundPlayTask.isAlive()) {
            if (DEBUG) Log.i(TAG, "force stop the thread");
            soundPlayTask.interrupt();
        }

    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    soundPlayTask = null;

    new SoundStopTask(this, currentPlayStreamID, currentPlayNonstop).start();

    Log.i(TAG, "stopSound leaving");
}

public void initThemeSound(String inUsethemePath) {
    this.inUseThemePath = inUsethemePath;
    soundPool = new SoundPool(3, AudioManager.STREAM_MUSIC, 0);
}

public void release() {
    if (soundPool != null) {
        for (String soundFile : mapSound.keySet()) {
            Integer soundID = mapSound.get(soundFile);
            soundPool.unload(soundID);
        }
        soundPool.stop(currentPlayStreamID);
        soundPool.release();
    }
    mapSound.clear();

    if (soundPlayTask != null)
        soundPlayTask.cancel();
    soundPlayTask = null;

    soundPool = null;
    currentPlayStreamID = 0;
    inUseThemePath = null;
}

public static class SoundStopTask extends Thread {
    private SoundManager soundManager;
    private int currentPlayStreamID;
    private int nonstop;
    public SoundStopTask(SoundManager soundManager, int currentPlayStreamID, int nonstop) {
        this.soundManager = soundManager;
        this.currentPlayStreamID = currentPlayStreamID;
        this.nonstop = nonstop;
    }

    public void run() {
        synchronized (soundManager) {
            Log.i(TAG, "SoundStopTask to cancel the sound " + currentPlayStreamID + " in mainthread" + " currentPlayNonstop=" + nonstop);
            if (nonstop == 0 && currentPlayStreamID != 0) {
                if (DEBUG) Log.i(TAG, "stopSound canceled the sound ");
                soundManager.soundPool.stop(currentPlayStreamID);
                currentPlayStreamID = 0;
            }
        }
    }
}

public static class SoundPlayTask extends Thread {
    private SoundManager soundManager;
    private boolean isCancelled = false;
    private String soundFile;
    private int loop;
    private int nonstop;

    public SoundPlayTask(SoundManager soundManager, String soundFile, int loop, int nonstop) {
        this.soundManager = soundManager;
        this.soundFile = soundFile;
        this.loop = loop;
        this.nonstop = nonstop;
    }

    public void cancel() {
        isCancelled = true;
    }

    @Override
    public void run() {
        if (DEBUG) Log.i(TAG, "enter doInBackground");

        synchronized (soundManager) {
            int ringerMode = soundManager.audioManager.getRingerMode();
            if (ringerMode == AudioManager.RINGER_MODE_SILENT || ringerMode == AudioManager.RINGER_MODE_VIBRATE)
                return;

            if (isCancelled)
                return;
            Log.i(TAG, "doInBackground begin to play sound");

            soundManager.currentPlayNonstop = nonstop;

            Integer soundID;
            soundID = soundManager.mapSound.get(soundFile);
            if (soundID == null) {
                soundID = soundManager.soundPool.load(soundManager.inUseThemePath + soundFile, 1);
                soundManager.mapSound.put(soundFile, soundID);
            }

            if (soundID == 0)
                return;

            Log.i(TAG, "doInBackground get the sound id " + soundID);

            if (isCancelled)
                return;


            float actualVolume = (float) soundManager.audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
            float maxVolume = (float) soundManager.audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
            float volume = actualVolume / maxVolume;

            soundManager.currentPlayStreamID = soundManager.soundPool.play(soundID, volume, volume, 1, 0-loop, 1f);

            if (isCancelled) {
                if (DEBUG) Log.i(TAG, "doInBackground begin to cancel after begining to play " + soundManager.currentPlayStreamID);
                if (soundManager.currentPlayNonstop == 0 && soundManager.currentPlayStreamID != 0) {soundManager.soundPool.stop(soundManager.currentPlayStreamID);
                    soundManager.currentPlayStreamID = 0;
                }
            }
        }

    }
}
}
4

0 回答 0