前提・実現したいこと
Android StudioでAndroidアプリを開発しています。
内部ストレージ内のMusicフォルダに格納されているmp3ファイルとディレクトリを読み込んでリストで表示させ、ファイルをタッチした場合は再生し、ディレクトリをタッチした場合はディレクトリの中身をさらに表示し、その中のファイルをタッチすると再生するというものです。
発生している問題・エラーメッセージ
参照するディレクトリ直下に置かれているmp3ファイルは表示され、再生されるのですが、ディレクトリをタッチすると、中身のファイル一覧は表示されるのですが、タッチするとアプリがクラッシュしてしまいます。
おそらく、最初に作った配列が残ってしまっているものだと思うのですが、どのように解決して良いのかわかりません。
java.lang.ArrayIndexOutOfBoundsException: length=4; index=5 at com.example.mp3player_process.MainActivity$1.onItemClick(MainActivity.java:65)
該当のソースコード
package com.example.mp3player_process; import android.media.MediaPlayer; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.util.Log; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.CompoundButton; import android.widget.ListView; import androidx.appcompat.app.AppCompatActivity; import com.google.android.material.switchmaterial.SwitchMaterial; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity { //メディアプレイヤーフィールドを作成 private MediaPlayer _player = null; //音楽リスト格納フィールド作成 private List<String> songList = new ArrayList<>(); private ListView lv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //アダプターの作成 lv = findViewById(R.id.songList); songList = new ArrayList<>(); //指定したディレクトリ内のmp3フォルダすべて読み込み File songDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC); String songPath = songDir.getPath(); File[] files = new File(songPath).listFiles(); ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, songList); if (files != null) { //Musicディレクトリ以下のmp3ファイルをリストに格納 for (int i = 0; i < files.length; i++) { //ファイルであること、.mp3で名前が終わっている事を条件にリストに追加 if (files[i].isFile() && files[i].getName().endsWith(".mp3")) { songList.add(files[i].getName()); //ディレクトリだった場合… } else if (files[i].isDirectory()) { songList.add(files[i].getName()); } } //アダプターをセット lv.setAdapter(adapter); lv.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { //タッチした項目がファイルだった場合… Log.d("onClick", "取得したパスは"+files[position].getAbsolutePath()+""); ListView listView = (ListView) parent; //songの中にはパスが入っている?(ファイル名?) String song = (String) listView.getItemAtPosition(position); //フルパスを取っておく String Fpath = files[position].getAbsolutePath(); play(Fpath); //タッチした項目がディレクトリだった場合… if (files[position].isDirectory()){ Log.d("onClick", "取得したパスは"+files[position].getAbsolutePath()+""); //リストを初期化 songList.clear(); lv.setAdapter(adapter); //選択したディレクトリの中にあるmp3ファイルを格納するフィールド作成 File songDir = new File(files[position].getAbsolutePath()); Log.d("OnclickDir", "取得したディレクトリのパスは"+songDir+"です"); String selectedDirPath = songDir.getPath(); File[] Selectedfiles = new File(selectedDirPath).listFiles(); if (Selectedfiles != null) { //タッチしたディレクトリ内のmp3フォルダすべて読み込み for (int i = 0; i < Selectedfiles.length; i++){ if (Selectedfiles[i].isFile() && Selectedfiles[i].getName().endsWith("mp3")) { //ファイル名をリストに収納 songList.add(Selectedfiles[i].getName()); Log.d("selectedDir", i+"番目に"+ Selectedfiles[i].getName()+"が格納されました"); } } } lv.setAdapter(adapter); Log.d("OnclickDir", "現在の配列の長さは"+ Selectedfiles.length+"です"); } } }); } //ループ処理 SwitchMaterial loopswitch = findViewById(R.id.swloop); //リピート再生のスイッチのリスナ loopswitch.setOnCheckedChangeListener(new LoopSwitchChangedListener()); }
試したこと
配列の参照がおかしいことがわかっているのですが、どのようにコードを書き換えてよいかわかりません。
補足情報(FW/ツールのバージョンなど)
回答3件
あなたの回答
tips
プレビュー