当我们使用 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;
}
}
}
}
}
}