SoundPool spinnt wirklich??

  • Antworten:21
  • OffenNicht stickyBentwortet
  • Forum-Beiträge: 1.525

14.08.2013 05:20:14 via Website

Hallo liebes Forum.


Ich habe echt ein komisches SoundPool Problem.

Und zwar teste ich es auf einem Nexus 4, Samsung S3 Mini und ein Sony Xperia S.
Alle haben Jelly Bean drauf.

Nun möchte ich durch den SoundPool ein Sound starten lassen.
Beim S3 Mini klappt alles wunderbar. Ohne das ich den Sound vorladen lassen muss durch:
1soundPool.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {
2 public void onLoadComplete(SoundPool soundPool, int sampleId,int status) {
3
4 loaded = true;
5
6 }
7 });

Lade ich aber den Sound so vor, dann geht es nicht auf dem S3 Mini. Nur ohne.

Komischerweise geht aber weder mit oder ohne vorladen die Sounds nicht beim Nexus 4 oder Sony Xperia S.
Habe alles versucht. Die Sounds in .mp3 oder .wav oder sehr sehr klein gemacht.

Verstehe nicht wo das Problem ist. Warum es beim S3 Mini Funktioniert und bei den anderen nicht.

Hoffe einer von euch kann mir weiterhelfen.


LG

Antworten
  • Forum-Beiträge: 141

14.08.2013 07:31:40 via Website

Soweit ich weiß muss man alle Soundfiles laden bevor man diese über das soundpool object wiedergeben kann.
Wie sieht denn dein Code aus?

Habe meinen jetzt bisher nur auf nem Nexus 10 laufen lassen, aber das klappt:

1public void createSoundPool(){
2
3 soundFile = new int[numberOfSounds];
4 Log.i("SOUND", "Number of sound files: "+soundFile.length);
5
6 mySoundpool = new SoundPool(soundFile.length, AudioManager.STREAM_MUSIC, 0);
7
8 mySoundpool.setOnLoadCompleteListener(new OnLoadCompleteListener() {
9 @Override
10 public void onLoadComplete(SoundPool soundPool, int sampleId,
11 int status) {
12 if(sampleId==soundFile[numberOfSounds]){
13 loaded = true;
14 Log.i("SOUND", "All sound files loaded");
15 }
16 }
17 });
18 }

1public void loadSounds(){
2 myAudiomanager = (AudioManager)this.getSystemService(Context.AUDIO_SERVICE);
3 volume = myAudiomanager.getStreamVolume(AudioManager.STREAM_MUSIC);
4soundFile[0] = mySoundpool.load(getApplicationContext(), R.raw......);
5//...
6//...
7//...
8}

1public void playSounds(){
2mySoundpool.play(soundFile[0], volume, volume, 1, 0, 1f);
3//...
4//...
5//...
6}

Antworten
  • Forum-Beiträge: 1.727

14.08.2013 10:40:38 via Website

Ist dennoch sehr naiv programmiert:

Schaut man auf die Docu :

public abstract void onLoadComplete (SoundPool soundPool, int sampleId, int status)

Wozu gibt es das status Flag wenn man danach einfach davon ausgeht das es ok ist ?

Und es kann gut sein das die Sounds async geladen werden und du somit eine racecodition auf deinem boolean flag hast, daher setzt das mal volatile

Windmate HD, See you @ IO 14 , Worked on Wundercar, Glass V3, LG G Watch, Moto 360, Android TV

Antworten
  • Forum-Beiträge: 141

14.08.2013 18:43:10 via Website

Die boolean war auf volatile ;)

Ich bin davon ausgegangen, dass er die sounds nacheinander läd - sofern ich sie nacheinander "loade".
In der if-clause im onLoadCompleteListener habe ich dann nur den "letzten" sound geprüft. Falls dieser dann eben geladen wurde die boolean auf true gesetzt.

Also sollte ich beim letzten sound das statusflag als Bedingung dazu tun?

Entschuldige dass ich in deinem Thread Fragen stelle Michele..

— geändert am 14.08.2013 18:43:27

Antworten
  • Forum-Beiträge: 1.525

15.08.2013 00:42:27 via Website

Hallo.

Ist kein Problem LitteM.

Mein Code:

1public class TestSound extends Service {
2
3 public SoundPool soundPool;
4 public int soundID;
5 public boolean loaded = false;
6
7 @Override
8 public void onCreate() {
9 super.onCreate();
10
11 soundPool = new SoundPool(1, AudioManager.STREAM_MUSIC, 0);
12 soundID = soundPool.load(this, R.raw.beep, 1);
13
14 soundPool.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {
15 public void onLoadComplete(SoundPool soundPool, int sampleId,int status) {
16
17 loaded = true;
18
19 }
20 });
21 }
22
23 @Override
24 public void onStart(Intent intent, int startId) {
25 super.onStart(intent, startId);
26
27 if(loaded) {
28
29 soundPool.play(soundID, 1.0f, 1.0f, 1, 0, 1f);
30
31 }
32
33 stopSelf();
34
35 }
36
37 @Override
38 public IBinder onBind(Intent intent) {
39 return null;
40 }
41}

Eigentlich ist so nichts falsch finde ich.


LG

— geändert am 15.08.2013 00:43:12

Antworten
  • Forum-Beiträge: 1.727

21.08.2013 03:46:49 via Website

Hmm,


sieht weiterhin nach Concurency problem aus für mich.
Pack mal mehr Log ausgaben rein und schau wer wann wie Fertig ist!

Der SoundPool lädt dinge und deine onStart wird evtl zur gleichen Zeit aufgerufen.

PS: Seit 2.2 ? sollte man besser public int onStartCommand(Intent intent, int flags, int startId) überschreiben anstatt onStart

Windmate HD, See you @ IO 14 , Worked on Wundercar, Glass V3, LG G Watch, Moto 360, Android TV

Michele

Antworten
  • Forum-Beiträge: 1.525

21.08.2013 04:19:21 via Website

Hallo.

Habe es mal auf onStartCommand umgeschrieben anstatt onStart.

Das hat leider nichts geändert.
Aber wie du sagtest habe ich es mit der LogCat genauer gemacht.

Bevor der Sound fertig geladen ist,ist der Service schon wieder geschlossen wurden.
Er führt onCreate aus, dann onStartCommand, dann schließt er den Service und dann sagt er erst der Sound ist fertig geladen.

EDIT: Also mit MediaPlayer geht es ja. Aber ich will ja die Sounds über SoundPool laufen lassen.
Oder kann ich etwa die MediaPlayer Sounds auch über den AudioManager "STREAM_NOTIFICATION" oder "STREAM_SYSTEM" laufen lassen?



LG

— geändert am 21.08.2013 04:52:59

Antworten
  • Forum-Beiträge: 1.727

21.08.2013 04:58:39 via Website

Der einfachst fix wäre wohl du würdest die Sounds im Application Object halten und über den Service einfach benutzen. Das ApplicationObject ist immer da, aber auch hier musst du evtl warten bis der Pool vollgeladen wurde.

Naiv fällt mir noch ein Latch ein:

1public class TestSound extends Service {
2
3private final static int NR_OF_SOUNDS_TO_LOAD = 5:
4
5private final CountDownLatch latch = new CountDownLatch(NR_OF_SOUNDS_TO_LOAD);
6
7public SoundPool soundPool;
8public int soundID;
9public boolean loaded = false;
10
11@Override
12public void onCreate() {
13super.onCreate();
14
15 soundPool = new SoundPool(1, AudioManager.STREAM_MUSIC, 0);
16 soundID = soundPool.load(this, R.raw.beep, 1);
17
18 soundPool.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {
19 public void onLoadComplete(SoundPool soundPool, int sampleId,int status) {
20
21 Log.d("Service","Counting Down"+latch.getCount());
22 latch.countDown();
23
24 }
25 });
26 }
27
28 @Override
29 public void onStart(Intent intent, int startId) {
30 super.onStart(intent, startId);
31
32
33 try
34 {
35 latch.await(long 5, TimeUnit.SECONDS);
36 soundPool.play(soundID, 1.0f, 1.0f, 1, 0, 1f);
37
38 }
39 catch( InterruptedException e)
40 {
41 Log.wtf("Service","Loading Sound took to long or any other problem with SoundPool",e);
42 }
43 finally
44 {
45 stopSelf();
46 }
47
48
49
50 }
51
52 @Override
53 public IBinder onBind(Intent intent) {
54 return null;
55 }
56}

Der Code hab ich auf meiner Windowsbüchse mal in N++ geändert, sollte ansich stimmen. Wichtig ist das die Anzahl Sound stimmen. Sollte das laden zu lange dauern (>5 sek) bricht das ganze ab. Ich würde aber nur auf den Sound warten, andere Operationen können dem vorweg gehen der Service muss ja irgendwas machen ausser nen Sound zu spielen.
Das Interrupt Flag würde ich auch nicht neu setzen im Code, wir sind auf dem Main Thread, sicher nicht gut ;)



Evtl ließe sich auch eine Notification "missbrauchen" dafür die halt nur nen Sound spielt.

@ADMINS: Wann wird endlich mal ne Codeformatierung hier ermöglicht anstatt diesen Mist ?

— geändert am 21.08.2013 05:01:19

Windmate HD, See you @ IO 14 , Worked on Wundercar, Glass V3, LG G Watch, Moto 360, Android TV

Michele

Antworten
Gelöschter Account
  • Forum-Beiträge: 47

21.08.2013 22:57:35 via Website

Servus,

hatte das selbe Problem. Klappt das nun bei dir?

Antworten
  • Forum-Beiträge: 1.525

22.08.2013 01:57:22 via Website

Hallo.

Danke dir sehr Mac.:*)

So funktioniert es "erstmal".

Aber leider wird alles erst in 5sek ausgeführt was in der onStart ist.

Durch
1latch.await((long) 5, TimeUnit.SECONDS);

@Nachbar90: Wie hast du es hinbekommen denn, wenn du sagst du hattest das selbe Problem.:D



LG

— geändert am 22.08.2013 02:04:18

Antworten
  • Forum-Beiträge: 1.727

22.08.2013 02:11:43 via Website

Ich glaube nicht das er 5 Sekunden wartet. Maximal 5 Sekunden damit der Main Thread nicht blockiert wird.

Oder du schiebst das ins ApplicationObject dann ist es immer da und du musst nur einmal laden ...

— geändert am 22.08.2013 02:14:56

Windmate HD, See you @ IO 14 , Worked on Wundercar, Glass V3, LG G Watch, Moto 360, Android TV

Michele

Antworten
  • Forum-Beiträge: 1.525

22.08.2013 02:13:26 via Website

Mhh ok.

Ich werde weiter basteln.

Danke dir erstmal sehr.


LG

Antworten
  • Forum-Beiträge: 1.525

22.08.2013 02:18:41 via Website

Mac Systems
Irgendwie ist das aber noch zu häcky ....

Wie meinst du das nun genau?:D


LG

Antworten
  • Forum-Beiträge: 1.727

22.08.2013 02:25:07 via Website

Nun ja dem MainThread zu blocken ist nicht gerade cool. Auch wenn das erstmal geht. Wenn du z.b 20 Sounds lädst dauert es eben halt evtl je nach Device und Speicher länger. Gewöhnlich würde ich erwarten das ein Service eine Notification einstellt die dann evtl einen Sound spielt. Der User will ja wissen das was passiert ist. Im fall das irgendein Fall nicht eingetretten ist macht man einfach nix.

Windmate HD, See you @ IO 14 , Worked on Wundercar, Glass V3, LG G Watch, Moto 360, Android TV

Antworten
  • Forum-Beiträge: 1.525

22.08.2013 02:29:35 via Website

Mhhmm ja stimmt schon.

Ich teste gerade bisschen mit dem MediaPlayer rum.

Verstehe nicht warum das mit dem sofort klappt.


LG

Antworten
  • Forum-Beiträge: 1.727

22.08.2013 02:35:41 via Website

Der MediaPlayer hat auch eine art "prefetching" daher sollte das ähnliche Probleme verursachen :ph34r:

Windmate HD, See you @ IO 14 , Worked on Wundercar, Glass V3, LG G Watch, Moto 360, Android TV

Antworten
  • Forum-Beiträge: 1.525

22.08.2013 02:37:12 via Website

Naja ich teste weiter. Irgendwie muss es ja gehen.

Danke dir trotzdem erstmal Mac.


LG

Antworten
  • Forum-Beiträge: 1.525

23.08.2013 00:43:36 via Website

Soooo.

Ich habe es nun hinbekommen soweit.
Habe es erstmal in einer Activity getestet.
Geht aber auch im Service so.

1public class MainActivity extends Activity implements View.OnClickListener {
2
3 public MediaPlayer mp;
4
5 @Override
6 protected void onCreate(Bundle savedInstanceState) {
7 super.onCreate(savedInstanceState);
8 setContentView(R.layout.activity_main);
9
10 ImageView imageView = (ImageView) findViewById(R.id.imageView);
11 imageView.setOnClickListener(this);
12
13 mp = new MediaPlayer();
14 mp.setAudioStreamType(AudioManager.STREAM_NOTIFICATION);
15 try {
16 mp.setDataSource(this, Uri.parse("android.resource://com.example.myapplication/" + R.raw.beep));
17 } catch (IOException e) {
18 e.printStackTrace();
19 }
20 try {
21 mp.prepare();
22 } catch (IOException e) {
23 e.printStackTrace();
24 }
25
26 }
27
28 @Override
29 public void onClick(View v) {
30
31 mp.start();
32
33 }
34}

So geht es wunderbar.


LG

— geändert am 23.08.2013 00:44:15

Antworten