我正在创建一个使用Tabbed Fragments的音乐播放器应用。 Player组件(将文件列表和链接回放操作加载到按钮的方法)设置在PlayerFragment类中的嵌套Player类中。
我打算加载我的应用程序,第一个片段是播放器,其中会出现一个文件列表,一旦用户按下列表中的文件,它就会播放。
现在,我遇到的问题是我正在尝试创建一个Player实例,然后调用方法initializeAllComponents(),顾名思义,它将实例化Player类,允许Player出现在片段视图中,允许按钮使用各自的方法。
我已经四处寻找,但我找不到能够解决问题的答案。
当我打开应用程序时,对initializeAllComponents()的调用会导致应用程序立即关闭。
该应用目前基于许可证下的Lite Music API,但稍后会对其进行大量修改。这就是代码看起来如此相似的原因。现在我只想在开始重新处理按钮和MediaPlayer方法之前,正确加载Fragment并包含一个有效的音乐播放器。
MainActivity和TabFragment(本例中为FragmentPager类)类正常工作,因此我不会包含它们。它们允许应用程序显示标签视图,并在OnCreateView中不包含调用时加载片段,但是PlayerFragment会破坏应用程序,就像现在在OnCreateView方法中调用一样。
我也知道Player类在没有Fragment实现的Main Activity中设置时正常工作。所以它似乎必须调用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>
答案 0 :(得分:1)
我也在尝试开发相同类型的应用程序,是的,您可以通过使用带有选项卡的片段并使用服务类通过服务器在片段中播放歌曲来实现。