songs nach dem zufallsprinzip abspielen

  • hallo,


    ich beschäftige mich momentan mit einem musikplayer welches 3 buttons hat um damit 3 verschiedene musik-genren abzuspielen. wenn man einen button drückt, soll es zufällig aus der gewählten genre ein musikstück abspielen. leider denke ich etwas kompliziert und habe versucht das so zu lösen.


    also button1 soll nur von der genre "black" abspielen,
    button2 die genre "jazz" und
    button 3 die genre "rock".


    dafür habe ich einen raw-ordner erstellt wo sich 9 verschiedene musikdatein befinden. jede genre beinhaltet 3 musikstücke (daher 9 insgesamt). die habe ich auch folgendermaßen benannt:
    black_a, black_b und black_c
    jazz_a, jazz_b, jazz_c
    rock_a, rock_b, rock_c
    (alle befinden sich im raw-ordner)


    dann habe ich für jede Genre einen String-array erstellt:


    Die Onlick-Methode für button1 sieht so aus:

    Code
    public void PlaylistStadt(View v) {
    		Uri musicpath = Uri.parse(playlist_Black[r.nextInt(playlist_Black.length)]);
    		String path = playlist_Black[r.nextInt(playlist_Black.length)];
    		textView.setText(path);
    
    
    			mp = MediaPlayer.create(getApplicationContext(), musicpath);
    			mp.start();
    	}


    Fehlermeldung:



    keine ahnung ob meine methode richtig bzw. gut ist, mir ist leider keine weiteren eingefallen. von der fehlermeldung werde ich auch nicht schlau. wie könnte man das lösen? hat jmd. eine ratschlag oder eine lösung?

  • Wäre echt schon mal die wirklich betroffenen Codezeilen zu sehen...

    Zitat

    03-05 16:46:04.575: E/AndroidRuntime(28734): Caused by: java.lang.NullPointerException
    03-05 16:46:04.575: E/AndroidRuntime(28734): at com.example.myrandommusicplayer.MainActivity.PlaylistBlack(MainActivity.java:65)


    Irgendwas ist da null. Entweder dein getApplicationContext() oder der mp oder was auch immer in Zeile 65 deiner MainActivity.java steht.

    Je mehr Käse, desto mehr Löcher.
    Je mehr Löcher, desto weniger Käse.
    Daraus folgt: je mehr Käse, desto weniger Käse.


    »Dies ist ein Forum. Schreibt Eure Fragen in das Forum, nicht per PN!«

  • in zeile 65 steht mp.start();


    hier ist der komplette code:


  • MediaPlayer.create(...) liefert bei dir null. Daher wird eine NPE geworfen, wenn du auf mp eine weitere Methode aufrufst. Der Fehler liegt wohl bei der Uri, weswegen der MediaPlayer keine gültige Datei findet und daher null zurückgibt.


    Laut Google muss eine Uri für die raw Resourcen so aufgebaut werden: "android.resource://[package]/[res id]". Beachte dabei, dass die res id auch wirklich die statische Resource sein muss und nicht wie bei dir als String. Mach aus aus dem String Array ein int Array

    Code
    int [] playlist_Black	= {R.raw.black_a, R.raw.black_b, R.raw.black_c};


    und baue anschließend deine Uri nach dem oben genannten Muster auf. Viel einfacher ist es jedoch ohne Uri. Es gibt eine MediaPlayer.create(Context, int) der du einfach die Resource-Id übergeben kannst.

    Code
    mp = MediaPlayer.create(getApplicationContext(), playlist_Black[r.nextInt(playlistBlack.length)]);


    Noch ein paar Anmerkungen zu dem restlichen Code:

    • Variablennamen werden nur in lower CamelCase bennant (ohne _ und dergleichen)
    • Du fragst zuerst in der if ob der MediaPlayer grade was abspielt. Erst in der else jedoch initialisierst du diesen aber erst. D.h. dir wird schon am Anfang eine NPE geworfen. Versuch das logischer aufzubauen. (Ist MediaPlayer =! null dann prüfe ob gespielt wird. Ist er null, dann erstelle diesen neu.)
    • Du hast in vielen Methoden immer ein und den selben Code. Lager diesen in eine weitere Methode aus. Das ehröht die Wartbarkeit und verhindert ständiges Copy&Paste bei Änderungen. Für sowas gibt es ein bekanntes Prinzipt: DRY. Don't repeat yourself!


    block_

  • Hallo block,


    danke für deine ratschläge und hilfe. Hat super geklappt.


    so funzt es:



    wäre es auch möglich, dass immer beim drücken eines buttons stets eine andere musik abgespielt wird? ich habe ja pro genre nur 3 musikstücke. es kam vor dass die gleiche mukke 3-4 mal hintereinander zufällig gewählt wurde. bei 3 musikstücken ist das sehr wahrscheinlich.

  • mal eine andere Frage: ich habe das etwas umgeschrieben



    was ich nicht verstehe ist, das bei der textview folgendes ausgegeben wird wenn ich z.b. button3 klicke: res/raw/rock_c.mp3
    es wird stets der pfad des mp3 angezeigt. schön und gut. in der log bekomme ich aber eine komische zahl ausgegeben:


    03-06 13:01:05.520: E/Ausgabe:(31072): 2130968578


    wieso bekomme ich in der log eine komische zahl und in der textview einen pfad ausgegeben? das verstehe ich nicht.


    zudem hatte ich vorher in einem anderen musikplayer-projekt, welches auch die metainformationen des mp3-files ausliest, einen mp3 file im raw ordner. auf den mp3-file habe ich folgendermaßen zugegriffen:


    Code
    String uriPath = "android.resource://" + getPackageName() + "/raw/music";
    Uri uri = Uri.parse(uriPath);


    in meinem jetztigen projekt kann ich das aber nicht übernehmen, da der integer-wert eine komischer zahl ist. habe folgendes mal gemacht um zu sehen was ausgegeben wird:

    Code
    String uriPath = "android.resource://" + getPackageName() + i;
    					String uriPath2 = "android.resource://" + getPackageName() + "/raw/music";
    					Log.e("Ausgabe: ", uriPath);
    					Log.e("Ausgabe: ", uriPath2);


    Ausgabe ist:


    Code
    03-06 13:09:23.680: E/Ausgabe:(31456): android.resource://com.example.testproject2130968577
    03-06 13:09:23.680: E/Ausgabe:(31456): android.resource://com.example.testproject/raw/music


    warum ist das so? kann mir das einer erklären? :-/

  • wäre es auch möglich, dass immer beim drücken eines buttons stets eine andere musik abgespielt wird? ich habe ja pro genre nur 3 musikstücke. es kam vor dass die gleiche mukke 3-4 mal hintereinander zufällig gewählt wurde. bei 3 musikstücken ist das sehr wahrscheinlich.


    Du könntest den jeweiligen Index des gerade abgespielten Liedes in ein HashSet speichern und nach jedem Welchsel prüfen, ob das neue ausgewählte Lied bzw. der Index des Liedes bereits in diesem HashSet vorhanden ist. Ist er das, wähle ein neues. Ist er das nicht, spiel die Musik ab und füge den dazugehörigen Index in den HashSet. Sind alle Lieder gespielt worden, leere den HashSet und fang wieder von vorne an.


    Für die anderen Fragen:
    Die Resourcen werden in Android als statische int Variablen gespeichert. Diese "komische Zahl" ist also ganz normal. Bei dem TextView gibt es verschiedene Methoden zum setzen des Textes. Da du eine Resourcen-ID übergibst (den int Wert), wird intern der eigentliche Wert zu der Resource ermittelt. In diesem Fall dein res/raw/rock_c.mp3. In der Log findet die Ermittlung jedoch nicht statt und der eigentliche int Wert wird ganz normal ausgegeben.
    Laut dem Blog-Eintrag hier gehen beide Möglichkeiten (ist zwar schon echt lange her der Eintrag, aber es scheint sich bis heute nicht viel geändert zu haben). Zwischen Package-Name und der Res-ID gehört jedoch noch ein "/", dann sollte das ebenfalls funktionieren. Ich hab es zwar nicht getestet, aber du könntest es ja einfach mal ausprobieren und gegebenenfalls Bescheid sagen, falls dem nicht so ist :)


    Hoffe das ist einigermaßen verständlich ausgedrückt.


    block_

  • hallo block,


    danke für deine hilfe, leider hat es so auch nicht funktioniert. habe es dann mit getResources().getResourceEntryName(i) versucht und es ging. O:-)


    leider hat sich aber nun ein anderes problem dadurch herausgepuppt, und zwar hatte ich ja erwähnt, das ich in meinem projekt auch auf die meta-daten des mp3-files zugreife, also sprich den interpreter, songtitel und eventuell auch songcover abfrage und dem display aufliste. vorher hatte ich nur ein einziges mp3-file im raw ordner um es generell zu testen ob die meta-daten abgerufen wurden. die methode sah so aus, was auch tadellos funktionierte:



    jetzt habe ich ja mehrere mp3-files im raw verzeichnis die zufällig ausgewählt werden. habe die Methode von oben dann dementsprechend geändert in:



    so müsste es eigentlich funktionieren, aber ich bekomme bei mp3_parameter für artist und title stets null und cover ist die gf_cover. irgendwas scheint da mit der uri glaube ich nicht zu stimmen, obwohl ich es in der log ausgegeben und überprüft habe.


    habe folgendes eingegeben:

    Code
    String uriPath2 = "android.resource://" + getPackageName() + "/raw/music";
    String uriPath = "android.resource://" + getPackageName() + "/raw/" + getResources().getResourceEntryName(i);
    Log.e("Ausgabe", uriPath);
    Log.e("Ausgabe", uriPath2);


    ausgabe ist:

    Code
    03-07 10:52:43.250: E/Ausgabe(28800): android.resource://com.example.swipeview3/raw/black_b
    03-07 10:52:43.250: E/Ausgabe(28800): android.resource://com.example.swipeview3/raw/music


    also die uri stimmt eigentlich, warum wird dann aber null ausgegeben? ;(

  • NACHTRAG:


    ich habe jetzt herausgefunden das es nicht am code liegt, sondern eher, dass ich nun im raw ordner mehrer mp3-files habe. Also, wenn ich nur einen mp3-file im raw verzeichnis habe und direkt auf den mp3-file zugreife werden die meta-daten angezeigt. sobald ich aber einen weiteren mp3-file in den raw-verzeichnis ordner packe und trotzdem direkt auf nur eines der files zugreife (also kein random) um die metadaten abzufragen, bekomme ich null. am code habe ich nichts geändert, habe lediglich nur ein weiteres mp3-file ins raw verzeichnis hinzugefügt und dann ging es nicht mehr. entferne ich den hinzugefügten mp3-file, dann geht es wieder.
    also das verstehe ich jetzt wirklich nicht. die mp3-file haben andere bezeichnungen. warum ist das so??? ?( ?( ?(

  • Änderungen in einem Resource-Ordner werden nicht übernommen?


    Bei Eclipse ist das gerne mal der Fall, weil die Inhalte der res-Ordner nur gelegentlich in die Code-Basis übernommen werden.


    Nach Änderungen in res-Unterordnern sollte ein "Project" - "clean..." dieses Problem beheben.

  • Die Dateien in res/raw werden auch über die Resources verwaltet - nicht als Dateien im Dateisystem, sondern über interne Referenzen.


    Wenn du mehr auf Dateien Wert legst, dann ist das Verzeichnis MyProject/assets der Ort, wo du die mp3-Dateien speichern solltest und der Zugriff geht dann über getAssets().

  • also nach langen versuchen und recherchen habe ich herausgefunden, dass auch andere solche probleme mit dem MediaMetadataRetriever und mp3-files haben. solange im raw-verzeichnis nur EIN mp3-file vorliegt, funktioniert alles einwandfrei. fügt nur ein weiteres mp3-file hinzu, dann funzt der MediaMetadataRetriever nicht mehr und gibt nur noch null zurück. könnte das eventuell einer noch bestätigen?


    hier ist die activity:



    und hier die main.xml



    den raw-ordner mit den jeweiligen mp3-files mit den entsprechenden benennungen müssten noch übernommen werden. dann könnte man es testen. gibt es alternativen zum MediaMetadataRetriever um an die metadaten von audiodatein zu bekommen?

  • ok, lag irgendwie an den mp3-datein das ich ständig null bekommen habe. daher habe ich nur zwei mp3-datein genommen und in den raw-ordner gepackt, auf deren meta-daten zugegriffen und auch angezeigt werden kann (habe diese einzeln probiert). problem ist folgendes: wenn ich auf den button klicke, song wird abgespielt und es erscheinen auch die metadaten des songs. sobald ich wieder auf den button klicke und zufällig auch der andere song abgespielt wird, steht trotzdem in der textview die meta-daten des vorherigen songs. diese bleiben immer dort erhalten, so oft ich auch auf den button klicke. :(
    habe inzwischen die uri und uripath über einen log eintrag gecheckt, ohne fehler. es wird der path des anderen songs übernommen, aber die strings artist und title sind immer die gleichen. das ist echt zum haare rupfen ;(

  • Gib doch noch mal zusätzlich zu artist und title auch den uriPath aus - vielleicht greifst du ja an der Stelle irgenwie auf die falsche Datei zu.


    Ansonsten hab ich noch den Tipp, die Dateien in den asset-Ordner zu packen statt in res/raw - irgendwie sind die ja eher Zubehör als Rohdaten. Nur ist dann der Zugriff auf die Dateien etwas anders, aber das ist dann ein anderes Thema. Zusätzlich könnte noch eine Playlist in einer Datei oder vielleicht in der Datenbank eine sinnvolle Anpassung sein. Dann kannst du die Playlists einfacher ändern als hier im Code mit int-Arrays. ^^

  • Hallo uwe,


    Zitat

    habe inzwischen die uri und uripath über einen log eintrag gecheckt, ohne fehler. es wird der path des anderen songs übernommen,

    das habe ich schon gemacht. uripath wird bei jedem sound-wechsel richtig übernommen. aber artist und title ändern sich dementsprechend komischerweise nicht, was überhaupt keinen sinn ergibt. ich verstehe nicht, warum ich das über assets-ordner machen soll!? ich habe ja kein problem mit dem zugriff auf die datein bzw. mit dem abspielen, sondern eher mit dem metadatareciever. :(

  • NACHTRAG:


    ich habe es gerade über den emulator getestet und siehe da es geht wunderbar. bis dahin hatte ich die projekte direkt an meinen smartphone (S2) geschickt und getestet. eventuell wurde es gecached oder so keine ahnung. wenn man bei eclipse das projekt an smartphone ausführt, dann wird die app automatisch gelöscht und von neu installiert. das heißt, der cache müsste auch weg sein oder nicht? woran könnte es liegen, dass es beim emulator richtig läuft und beim smartphone nicht?

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!