【发布时间】:2016-08-13 23:29:50
【问题描述】:
我正在创建一个使用选项卡式片段的音乐播放器应用。 Player 组件(加载文件列表并将播放操作链接到按钮的方法)设置在 PlayerFragment 类中的嵌套 Player 类中。
我打算加载我的应用,第一个片段是播放器,其中将显示文件列表,一旦用户按下列表中的文件,它就会播放。
现在,我遇到的问题是我正在尝试创建 Player 的实例,然后调用方法 initializeAllComponents(),顾名思义,该方法将实例化 Player 类,允许 Player 出现在 Fragment View 中并允许按钮使用它们各自的方法。
我已经四处搜索,但没有找到解决问题的答案。
当我打开应用程序时,对 initializeAllComponents() 的调用会导致应用程序立即关闭。
该应用目前基于 Lite Music API 并获得许可,但稍后会进行大量修改。这就是代码看起来如此相似的原因。现在我只希望片段能够正确加载并包含一个正常工作的音乐播放器,然后再开始修改按钮和 MediaPlayer 方法。
MainActivity 和 TabFragment(在本例中为 FragmentPager 类)类工作正常,因此我不会包含它们。它们允许应用程序显示选项卡式视图并在它们不包含 OnCreateView 内部调用时正常加载片段,但 PlayerFragment 会破坏应用程序,因为它现在在 OnCreateView 方法内部调用。
我还知道,当在没有 Fragment 实现的主 Activity 中设置 Player 类时,它可以正常工作。所以看来一定是 OnCreateView() 中对 player.initializeAllComponents() 的调用破坏了一切,但我不知道为什么。
有没有一种方法可以调用 initializeAllComponents() 来正确地为 Fragment 充气而不会出错?我只是没有正确实例化 Player 子类吗?还是 Player 子类不能在 Fragment 中工作?
任何帮助将不胜感激。
代码如下:
PlayerFragment.java
import android.content.DialogInterface;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.support.v4.app.Fragment;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.AppCompatSeekBar;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.SeekBar;
import android.widget.TextView;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;
public class PlayerFragment extends Fragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Player.class.getMethods();
Player player = new Player();
player.initializeAllComponents();
return inflater.inflate(R.layout.player_layout, null);
}
class Player extends AppCompatActivity implements MediaPlayer.OnCompletionListener, SeekBar.OnSeekBarChangeListener {
private View parent_view;
private LinearLayout lyt_main;
// playlist
private ListView listview;
private LinearLayout lyt_progress;
private LinearLayout lyt_list;
// player
private Button bt_play;
private Button bt_next;
private Button bt_prev;
private Button btn_repeat;
private Button btn_shuffle;
private AppCompatSeekBar seek_song_progressbar;
private TextView tv_song_title;
private TextView tv_song_current_duration;
private TextView tv_song_total_duration;
// Media Player
private MediaPlayer mp;
// Handler to update UI timer, progress bar etc,.
private Handler mHandler = new Handler();
//private SongsManager songManager;
private MusicUtils utils;
private int currentSongIndex = 0;
private boolean isShuffle = false;
private boolean isRepeat = false;
// the items (songs) we have queried
private ArrayList<MusicItem> mItems = new ArrayList<MusicItem>();
private MusicItem cur_music = null;
private DatabaseHandler db;
public void initializeAllComponents() {
parent_view = findViewById(R.id.main_content);
db = new DatabaseHandler(getApplicationContext());
lyt_main = (LinearLayout) findViewById(R.id.lyt_main);
initPlaylistComponents();
initPlayerComponents();
}
private void initPlayerComponents() {
// All player buttons
bt_play = (Button) findViewById(R.id.bt_play);
bt_next = (Button) findViewById(R.id.bt_next);
bt_prev = (Button) findViewById(R.id.bt_prev);
btn_repeat = (Button) findViewById(R.id.btn_repeat);
btn_shuffle = (Button) findViewById(R.id.btn_shuffle);
seek_song_progressbar = (AppCompatSeekBar) findViewById(R.id.seek_song_progressbar);
tv_song_title = (TextView) findViewById(R.id.tv_song_title);
tv_song_title.setSelected(true);
tv_song_current_duration = (TextView) findViewById(R.id.tv_song_current_duration);
tv_song_total_duration = (TextView) findViewById(R.id.tv_song_total_duration);
// Media Player
mp = new MediaPlayer();
//songManager = new SongsManager();
utils = new MusicUtils();
// Listeners
seek_song_progressbar.setOnSeekBarChangeListener(this); // Important
mp.setOnCompletionListener(this); // Important
// Getting all songs list songsList = songManager.getPlayList();
buttonPlayerAction();
}
private void initPlaylistComponents() {
listview = (ListView) findViewById(R.id.list_main);
lyt_progress = (LinearLayout) findViewById(R.id.lyt_progress);
lyt_list = (LinearLayout) findViewById(R.id.lyt_list);
lyt_progress.setVisibility(View.GONE);
mItems.clear();
mItems = db.getAllMusicFiles();
listview.setAdapter(new MusicFileListAdapter(Player.this, mItems));
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
playSong(mItems.get(arg2));
}
});
}
/**
* Play button click event plays a song and changes button to pause image
* pauses a song and changes button to play image
*/
private void buttonPlayerAction() {
bt_play.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
if (mItems.size() > 0) {
// check for already playing
if (mp.isPlaying()) {
if (mp != null) {
mp.pause();
// Changing button image to play button
bt_play.setBackgroundResource(R.drawable.btn_play);
}
} else {
// Resume song
if (mp != null) {
mp.start();
// Changing button image to pause button
bt_play.setBackgroundResource(R.drawable.btn_pause);
}
}
} else {
Snackbar.make(parent_view, "Song not found", Snackbar.LENGTH_SHORT).show();
}
}
});
/**
* Next button click event
* Plays next song by taking currentSongIndex + 1
* */
bt_next.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
// check if next song is there or not
if (currentSongIndex < (mItems.size() - 1)) {
playSong(mItems.get(currentSongIndex + 1));
currentSongIndex = currentSongIndex + 1;
} else {
// play first song
playSong(mItems.get(0));
currentSongIndex = 0;
}
}
});
/**
* Back button click event
* Plays previous song by currentSongIndex - 1
* */
bt_prev.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
if (currentSongIndex > 0) {
playSong(mItems.get(currentSongIndex - 1));
currentSongIndex = currentSongIndex - 1;
} else {
// play last song
playSong(mItems.get(mItems.size() - 1));
currentSongIndex = mItems.size() - 1;
}
}
});
/**
* Button Click event for Repeat button
* Enables repeat flag to true
* */
btn_repeat.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
if (isRepeat) {
isRepeat = false;
Snackbar.make(parent_view, "Repeat is OFF", Snackbar.LENGTH_SHORT).show();
btn_repeat.setBackgroundResource(R.drawable.btn_repeat);
} else {
// make repeat to true
isRepeat = true;
Snackbar.make(parent_view, "Repeat is ON", Snackbar.LENGTH_SHORT).show();
// make shuffle to false
isShuffle = false;
btn_repeat.setBackgroundResource(R.drawable.btn_repeat_focused);
btn_shuffle.setBackgroundResource(R.drawable.btn_shuffle);
}
}
});
/**
* Button Click event for Shuffle button
* Enables shuffle flag to true
* */
btn_shuffle.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
if (isShuffle) {
isShuffle = false;
Snackbar.make(parent_view, "Shuffle is OFF", Snackbar.LENGTH_SHORT).show();
btn_shuffle.setBackgroundResource(R.drawable.btn_shuffle);
} else {
// make repeat to true
isShuffle = true;
Snackbar.make(parent_view, "Shuffle is ON", Snackbar.LENGTH_SHORT).show();
// make shuffle to false
isRepeat = false;
btn_shuffle.setBackgroundResource(R.drawable.btn_shuffle_focused);
btn_repeat.setBackgroundResource(R.drawable.btn_repeat);
}
}
});
}
/**
* Function to play a song
*/
public void playSong(MusicItem msc) {
// Play song
try {
mp.reset();
mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
mp.setDataSource(getApplicationContext(), msc.getURI());
mp.prepare();
mp.start();
cur_music = msc;
// Displaying Song title
String songTitle = msc.getTitle();
tv_song_title.setText(songTitle);
// Changing Button Image to pause image
bt_play.setBackgroundResource(R.drawable.btn_pause);
// set Progress bar values
seek_song_progressbar.setProgress(0);
seek_song_progressbar.setMax(100);
// Updating progress bar
updateProgressBar();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Update timer on seekbar
*/
public void updateProgressBar() {
mHandler.postDelayed(mUpdateTimeTask, 100);
}
/**
* Background Runnable thread
*/
private Runnable mUpdateTimeTask = new Runnable() {
public void run() {
long totalDuration = mp.getDuration();
long currentDuration = mp.getCurrentPosition();
// Displaying Total Duration time
tv_song_total_duration.setText("" + utils.milliSecondsToTimer(totalDuration));
// Displaying time completed playing
tv_song_current_duration.setText("" + utils.milliSecondsToTimer(currentDuration));
// Updating progress bar
int progress = (int) (utils.getProgressPercentage(currentDuration, totalDuration));
seek_song_progressbar.setProgress(progress);
// Running this thread after 100 milliseconds
mHandler.postDelayed(this, 100);
}
};
public class loadFiles extends AsyncTask<String, String, String> {
MusicRetriever mRetriever;
String status = "success";
public loadFiles() {
mRetriever = new MusicRetriever(getContentResolver());
}
@Override
protected void onPreExecute() {
mItems.clear();
lyt_progress.setVisibility(View.VISIBLE);
lyt_list.setVisibility(View.GONE);
super.onPreExecute();
}
@Override
protected String doInBackground(String... params) {
try {
Thread.sleep(1000);
mRetriever.prepare();
mItems = mRetriever.getAllItem();
status = "success";
} catch (Exception e) {
status = "failed";
}
return null;
}
@Override
protected void onPostExecute(String result) {
if (!status.equals("failed")) {
lyt_progress.setVisibility(View.GONE);
lyt_list.setVisibility(View.VISIBLE);
listview.setAdapter(new MusicFileListAdapter(Player.this, mItems));
//if(musicfiles.size()>0){
db.truncateTableScan();
db.addMusicFiles(mItems);
}
super.onPostExecute(result);
}
}
// 2.0 and above
@Override
public void onBackPressed() {
moveTaskToBack(true);
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
// TODO Auto-generated method stub
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// remove message Handler from updating progress bar
mHandler.removeCallbacks(mUpdateTimeTask);
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
mHandler.removeCallbacks(mUpdateTimeTask);
int totalDuration = mp.getDuration();
int currentPosition = utils.progressToTimer(seekBar.getProgress(), totalDuration);
// forward or backward to certain seconds
mp.seekTo(currentPosition);
// update timer progress again
updateProgressBar();
}
@Override
public void onCompletion(MediaPlayer arg0) {
// check for repeat is ON or OFF
if (isRepeat) {
// repeat is on play same song again
playSong(mItems.get(currentSongIndex));
} else if (isShuffle) {
// shuffle is on - play a random song
Random rand = new Random();
currentSongIndex = rand.nextInt((mItems.size() - 1) - 0 + 1) + 0;
playSong(mItems.get(currentSongIndex));
} else {
// no repeat or shuffle ON - play next song
if (currentSongIndex < (mItems.size() - 1)) {
playSong(mItems.get(currentSongIndex + 1));
currentSongIndex = currentSongIndex + 1;
} else {
// play first song
playSong(mItems.get(0));
currentSongIndex = 0;
}
}
}
// stop player when destroy
@Override
public void onDestroy() {
super.onDestroy();
mp.release();
}
@Override
protected void onResume() {
if (mp.isPlaying()) {
updateProgressBar();
bt_play.setBackgroundResource(R.drawable.btn_pause);
} else {
bt_play.setBackgroundResource(R.drawable.btn_play);
}
if(!Tools.isAllPermissionGranted(this)){
showDialogPermission();
}else{
if(db.getAllMusicFiles().size()==0){
new loadFiles().execute("");
}
}
super.onResume();
}
private void showDialogPermission(){
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(getString(R.string.dialog_title_permission));
builder.setMessage(getString(R.string.dialog_content_permission));
builder.setCancelable(false);
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
Tools.goToPermissionSettingScreen(Player.this);
}
});
builder.show();
}
}
}
player_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/main_content">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/tv_song_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:marqueeRepeatLimit="marquee_forever"
android:maxLines="1"
android:singleLine="true"
android:text="Song Title"
android:background="@color/orange"
android:textAppearance="@style/TextAppearance.AppCompat.Title"
android:textColor="@color/white" />
<LinearLayout
android:id="@+id/lyt_main"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/orange"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:layout_marginTop="5dp"
android:gravity="center_horizontal"
android:orientation="horizontal"
android:paddingLeft="10dp"
android:paddingRight="10dp">
<Button
android:id="@+id/btn_repeat"
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_margin="3dp"
android:background="@drawable/btn_repeat" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:orientation="horizontal">
<Button
android:id="@+id/bt_prev"
android:layout_width="35dp"
android:layout_height="35dp"
android:background="@drawable/btn_previous" />
<Button
android:id="@+id/bt_play"
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"
android:background="@drawable/btn_play" />
<Button
android:id="@+id/bt_next"
android:layout_width="35dp"
android:layout_height="35dp"
android:background="@drawable/btn_next" />
</LinearLayout>
<Button
android:id="@+id/btn_shuffle"
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_margin="3dp"
android:background="@drawable/btn_shuffle" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginTop="10dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_song_current_duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0.00"
android:textColor="@color/white" />
<android.support.v7.widget.AppCompatSeekBar
android:id="@+id/seek_song_progressbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:progress="0"
android:theme="@style/SeekBarStyle" />
<TextView
android:id="@+id/tv_song_total_duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0.00"
android:textColor="@color/white" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="20dp"
android:layout_gravity="right"
android:gravity="center_vertical"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="SONG INFO HERE"/>
</LinearLayout>
</LinearLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/lyt_progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:gravity="center"
android:orientation="vertical">
<ProgressBar
android:id="@+id/progress_loadfiles"
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Scanning" />
</LinearLayout>
<LinearLayout
android:id="@+id/lyt_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ListView
android:id="@+id/list_main"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:divider="@android:color/transparent"
android:dividerHeight="0dp"
android:paddingTop="5dp" />
</LinearLayout>
</RelativeLayout>
</LinearLayout>
</RelativeLayout>
【问题讨论】:
标签: android android-fragments tabs audio-player android-music-player