A面播放实现
This commit is contained in:
parent
7315e81db2
commit
7f065a1835
@ -4,6 +4,10 @@
|
|||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
|
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
|
||||||
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
|
||||||
|
android:maxSdkVersion="32" />
|
||||||
|
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name=".MusicApplication"
|
android:name=".MusicApplication"
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package com.hi.music.player.adapter;
|
package com.hi.music.player.adapter;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@ -11,10 +12,11 @@ import androidx.annotation.NonNull;
|
|||||||
import androidx.recyclerview.widget.DiffUtil;
|
import androidx.recyclerview.widget.DiffUtil;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import com.bumptech.glide.Glide; // 确保你添加了 Glide 依赖
|
import com.bumptech.glide.Glide;
|
||||||
import com.hi.music.player.R;
|
import com.hi.music.player.R;
|
||||||
import com.hi.music.player.helper.AudioItemDiffCallback;
|
import com.hi.music.player.helper.AudioItemDiffCallback;
|
||||||
import com.hi.music.player.javabean.A_data.AudioItem;
|
import com.hi.music.player.javabean.A_data.AudioItem;
|
||||||
|
import com.hi.music.player.ui.activity.A_PlayActivity;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -24,7 +26,6 @@ public class A_InstrumentAdapter extends RecyclerView.Adapter<A_InstrumentAdapte
|
|||||||
private Context context;
|
private Context context;
|
||||||
private List<AudioItem> audioItems = new ArrayList<>();
|
private List<AudioItem> audioItems = new ArrayList<>();
|
||||||
|
|
||||||
// 构造函数
|
|
||||||
public A_InstrumentAdapter(Context context) {
|
public A_InstrumentAdapter(Context context) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
}
|
}
|
||||||
@ -42,18 +43,25 @@ public class A_InstrumentAdapter extends RecyclerView.Adapter<A_InstrumentAdapte
|
|||||||
|
|
||||||
Log.d("------","--------"+audioItem.getImage());
|
Log.d("------","--------"+audioItem.getImage());
|
||||||
|
|
||||||
|
|
||||||
// 加载图片,确保不使用 file:// 前缀,并将路径传递给 Glide
|
|
||||||
Glide.with(context)
|
Glide.with(context)
|
||||||
.load("file:///android_asset/" + audioItem.getImage()) // 正确的路径
|
.load("file:///android_asset/" + audioItem.getImage()) // 正确的路径
|
||||||
.into(holder.imageView);
|
.into(holder.imageView);
|
||||||
|
|
||||||
// 设置其他数据(如音频名称、描述等)如果有的话
|
holder.itemView.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
Intent intent = new Intent(context, A_PlayActivity.class);
|
||||||
|
intent.putExtra("Path", audioItem);
|
||||||
|
context.startActivity(intent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemCount() {
|
public int getItemCount() {
|
||||||
return audioItems.size(); // 返回实际的项目数量
|
return audioItems.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateData(List<AudioItem> newAudioItems) {
|
public void updateData(List<AudioItem> newAudioItems) {
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package com.hi.music.player.adapter;
|
package com.hi.music.player.adapter;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
@ -14,6 +15,7 @@ import com.bumptech.glide.Glide;
|
|||||||
import com.hi.music.player.R;
|
import com.hi.music.player.R;
|
||||||
import com.hi.music.player.helper.AudioItemDiffCallback;
|
import com.hi.music.player.helper.AudioItemDiffCallback;
|
||||||
import com.hi.music.player.javabean.A_data.AudioItem;
|
import com.hi.music.player.javabean.A_data.AudioItem;
|
||||||
|
import com.hi.music.player.ui.activity.A_PlayActivity;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -38,10 +40,19 @@ public class A_NatureAdapter extends RecyclerView.Adapter<A_NatureAdapter.ViewHo
|
|||||||
|
|
||||||
AudioItem audioItem = audioItems.get(position);
|
AudioItem audioItem = audioItems.get(position);
|
||||||
|
|
||||||
|
|
||||||
Glide.with(context)
|
Glide.with(context)
|
||||||
.load("file:///android_asset/" + audioItem.getImage())
|
.load("file:///android_asset/" + audioItem.getImage())
|
||||||
.into(holder.imageView);
|
.into(holder.imageView);
|
||||||
|
|
||||||
|
holder.itemView.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
Intent intent = new Intent(context, A_PlayActivity.class);
|
||||||
|
intent.putExtra("Path", audioItem);
|
||||||
|
context.startActivity(intent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package com.hi.music.player.adapter;
|
package com.hi.music.player.adapter;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@ -15,6 +16,7 @@ import com.bumptech.glide.Glide;
|
|||||||
import com.hi.music.player.R;
|
import com.hi.music.player.R;
|
||||||
import com.hi.music.player.helper.AudioItemDiffCallback;
|
import com.hi.music.player.helper.AudioItemDiffCallback;
|
||||||
import com.hi.music.player.javabean.A_data.AudioItem;
|
import com.hi.music.player.javabean.A_data.AudioItem;
|
||||||
|
import com.hi.music.player.ui.activity.A_PlayActivity;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -47,7 +49,14 @@ public class A_WhiteAdapter extends RecyclerView.Adapter<A_WhiteAdapter.ViewHold
|
|||||||
.load("file:///android_asset/" + audioItem.getImage()) // 正确的路径
|
.load("file:///android_asset/" + audioItem.getImage()) // 正确的路径
|
||||||
.into(holder.imageView);
|
.into(holder.imageView);
|
||||||
|
|
||||||
// 设置其他数据(如音频名称、描述等)如果有的话
|
holder.itemView.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
Intent intent = new Intent(context, A_PlayActivity.class);
|
||||||
|
intent.putExtra("Path", audioItem);
|
||||||
|
context.startActivity(intent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
package com.hi.music.player.javabean.A_data;
|
package com.hi.music.player.javabean.A_data;
|
||||||
|
|
||||||
public class AudioItem {
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class AudioItem implements Serializable {
|
||||||
private String name;
|
private String name;
|
||||||
private String file;
|
private String file;
|
||||||
private String image;
|
private String image;
|
||||||
|
|||||||
@ -11,6 +11,8 @@ import com.hi.music.player.adapter.A_HomeViewPagerAdapter;
|
|||||||
import com.hi.music.player.databinding.ActivityAhomeBinding;
|
import com.hi.music.player.databinding.ActivityAhomeBinding;
|
||||||
import com.hi.music.player.databinding.HomeTabCustomBinding;
|
import com.hi.music.player.databinding.HomeTabCustomBinding;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class A_HomeActivity extends BaseActivity<ActivityAhomeBinding> {
|
public class A_HomeActivity extends BaseActivity<ActivityAhomeBinding> {
|
||||||
|
|
||||||
// 图标数组定义为类成员,避免重复
|
// 图标数组定义为类成员,避免重复
|
||||||
@ -96,7 +98,7 @@ public class A_HomeActivity extends BaseActivity<ActivityAhomeBinding> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void updateTabIcon(TabLayout.Tab tab, boolean isSelected) {
|
private void updateTabIcon(TabLayout.Tab tab, boolean isSelected) {
|
||||||
HomeTabCustomBinding tabBinding = HomeTabCustomBinding.bind(tab.getCustomView());
|
HomeTabCustomBinding tabBinding = HomeTabCustomBinding.bind(Objects.requireNonNull(tab.getCustomView()));
|
||||||
int position = tab.getPosition();
|
int position = tab.getPosition();
|
||||||
tabBinding.homeIcon.setImageResource(isSelected ? selectedIcons[position] : defaultIcons[position]);
|
tabBinding.homeIcon.setImageResource(isSelected ? selectedIcons[position] : defaultIcons[position]);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,11 +1,23 @@
|
|||||||
package com.hi.music.player.ui.activity;
|
package com.hi.music.player.ui.activity;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.media.MediaPlayer;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.widget.SeekBar;
|
||||||
|
|
||||||
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
|
|
||||||
|
import com.hi.music.player.R;
|
||||||
import com.hi.music.player.databinding.ActivityAplayBinding;
|
import com.hi.music.player.databinding.ActivityAplayBinding;
|
||||||
|
import com.hi.music.player.javabean.A_data.AudioItem;
|
||||||
|
import com.hi.music.player.ui.activity.viewmodel.A_VMPlay;
|
||||||
|
|
||||||
public class A_PlayActivity extends BaseActivity<ActivityAplayBinding> {
|
public class A_PlayActivity extends BaseActivity<ActivityAplayBinding> {
|
||||||
|
|
||||||
|
private AudioItem audioItem;
|
||||||
|
private MediaPlayer mediaPlayer;
|
||||||
|
private A_VMPlay playViewModel;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ActivityAplayBinding getViewBinding() {
|
protected ActivityAplayBinding getViewBinding() {
|
||||||
@ -15,13 +27,68 @@ public class A_PlayActivity extends BaseActivity<ActivityAplayBinding> {
|
|||||||
@Override
|
@Override
|
||||||
protected void onCreateInit() {
|
protected void onCreateInit() {
|
||||||
|
|
||||||
|
Intent intent = getIntent();
|
||||||
|
audioItem = (AudioItem) intent.getSerializableExtra("Path");
|
||||||
|
if (audioItem == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String path = audioItem.getFile();
|
||||||
|
Log.d("------", "--------" + path);
|
||||||
|
|
||||||
|
playViewModel = new ViewModelProvider(this).get(A_VMPlay.class);
|
||||||
|
mediaPlayer = new MediaPlayer();
|
||||||
|
|
||||||
|
playViewModel.initializePlayer(path);
|
||||||
|
|
||||||
|
// 观察进度更新
|
||||||
|
playViewModel.getProgress().observe(this, progress -> {
|
||||||
|
vb.songSeekbar.setProgress(progress);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 观察播放状态
|
||||||
|
playViewModel.isPlaying().observe(this, isPlaying -> {
|
||||||
|
vb.playButton.setBackgroundResource(isPlaying ? R.drawable.play : R.drawable.pause);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 观察当前时间
|
||||||
|
playViewModel.getCurrentTime().observe(this, currentTime -> {
|
||||||
|
vb.current.setText(currentTime);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 观察总时间
|
||||||
|
playViewModel.getTotalTime().observe(this, totalTime -> {
|
||||||
|
vb.time.setText(totalTime);
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onInitClick() {
|
protected void onInitClick() {
|
||||||
|
vb.playButton.setOnClickListener(v -> playViewModel.togglePlay());
|
||||||
|
|
||||||
|
vb.songSeekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||||
|
if (fromUser) {
|
||||||
|
playViewModel.seekTo(progress); // 拖动进度条时控制音频
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||||
|
// 暂停更新进度
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||||
|
// 恢复更新进度
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isFullScreen() {
|
public boolean isFullScreen() {
|
||||||
return true;
|
return true;
|
||||||
@ -34,6 +101,6 @@ public class A_PlayActivity extends BaseActivity<ActivityAplayBinding> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
|
// 处理其他点击事件
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -14,6 +14,8 @@ import androidx.viewbinding.ViewBinding;
|
|||||||
|
|
||||||
import com.hi.music.player.helper.ViewModelScope;
|
import com.hi.music.player.helper.ViewModelScope;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
public abstract class BaseActivity<T extends ViewBinding> extends AppCompatActivity implements View.OnClickListener{
|
public abstract class BaseActivity<T extends ViewBinding> extends AppCompatActivity implements View.OnClickListener{
|
||||||
|
|
||||||
private final ViewModelScope mViewModelScope = new ViewModelScope();
|
private final ViewModelScope mViewModelScope = new ViewModelScope();
|
||||||
|
|||||||
@ -0,0 +1,105 @@
|
|||||||
|
package com.hi.music.player.ui.activity.viewmodel;
|
||||||
|
|
||||||
|
import android.app.Application;
|
||||||
|
import android.content.res.AssetFileDescriptor;
|
||||||
|
import android.media.MediaPlayer;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.lifecycle.AndroidViewModel;
|
||||||
|
import androidx.lifecycle.LiveData;
|
||||||
|
import androidx.lifecycle.MutableLiveData;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class A_VMPlay extends AndroidViewModel {
|
||||||
|
private MediaPlayer mediaPlayer;
|
||||||
|
private final MutableLiveData<String> currentTime = new MutableLiveData<>();
|
||||||
|
private final MutableLiveData<String> totalTime = new MutableLiveData<>();
|
||||||
|
private final MutableLiveData<Boolean> isPlaying = new MutableLiveData<>(false);
|
||||||
|
private final MutableLiveData<Integer> progress = new MutableLiveData<>(0); // 添加进度 LiveData
|
||||||
|
|
||||||
|
public A_VMPlay(Application application) {
|
||||||
|
super(application);
|
||||||
|
mediaPlayer = new MediaPlayer();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取进度的 LiveData
|
||||||
|
public LiveData<Integer> getProgress() {
|
||||||
|
return progress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LiveData<String> getCurrentTime() {
|
||||||
|
return currentTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LiveData<String> getTotalTime() {
|
||||||
|
return totalTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LiveData<Boolean> isPlaying() {
|
||||||
|
return isPlaying;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initializePlayer(String path) {
|
||||||
|
try {
|
||||||
|
AssetFileDescriptor afd = getApplication().getAssets().openFd(path);
|
||||||
|
mediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
|
||||||
|
mediaPlayer.prepare();
|
||||||
|
mediaPlayer.setOnPreparedListener(mp -> {
|
||||||
|
totalTime.setValue(formatTime(mediaPlayer.getDuration()));
|
||||||
|
startUpdatingProgress();
|
||||||
|
});
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.e("MediaPlayerError", "Could not open asset file: " + path, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void togglePlay() {
|
||||||
|
if (mediaPlayer.isPlaying()) {
|
||||||
|
mediaPlayer.pause();
|
||||||
|
isPlaying.setValue(false);
|
||||||
|
} else {
|
||||||
|
mediaPlayer.start();
|
||||||
|
isPlaying.setValue(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startUpdatingProgress() {
|
||||||
|
new Thread(() -> {
|
||||||
|
while (mediaPlayer != null) {
|
||||||
|
if (mediaPlayer.isPlaying()) {
|
||||||
|
int currentPosition = mediaPlayer.getCurrentPosition();
|
||||||
|
currentTime.postValue(formatTime(currentPosition));
|
||||||
|
progress.postValue((int) ((currentPosition / (float) mediaPlayer.getDuration()) * 100)); // 更新进度
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Thread.sleep(1000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void seekTo(int progress) {
|
||||||
|
if (mediaPlayer != null) {
|
||||||
|
int duration = mediaPlayer.getDuration();
|
||||||
|
mediaPlayer.seekTo((int) (duration * progress / 100.0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String formatTime(int milliseconds) {
|
||||||
|
int minutes = (milliseconds / 1000) / 60;
|
||||||
|
int seconds = (milliseconds / 1000) % 60;
|
||||||
|
return String.format("%02d:%02d", minutes, seconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCleared() {
|
||||||
|
super.onCleared();
|
||||||
|
if (mediaPlayer != null) {
|
||||||
|
mediaPlayer.release();
|
||||||
|
mediaPlayer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,13 +1,25 @@
|
|||||||
package com.hi.music.player.ui.fragmnt;
|
package com.hi.music.player.ui.fragmnt;
|
||||||
|
|
||||||
|
import static android.app.Activity.RESULT_OK;
|
||||||
|
|
||||||
|
import android.Manifest;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.core.app.ActivityCompat;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
|
||||||
import com.hi.music.player.databinding.FragmentAImportBinding;
|
import com.hi.music.player.databinding.FragmentAImportBinding;
|
||||||
import com.hi.music.player.ui.activity.A_SettingActivity;
|
import com.hi.music.player.ui.activity.A_SettingActivity;
|
||||||
|
|
||||||
|
|
||||||
public class A_ImportFragment extends BaseFragment<FragmentAImportBinding> {
|
public class A_ImportFragment extends BaseFragment<FragmentAImportBinding> {
|
||||||
|
|
||||||
|
private static final int REQUEST_CODE_READ_MEDIA_AUDIO = 1001;
|
||||||
|
private static final int REQUEST_CODE_PICK_AUDIO = 1002;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected FragmentAImportBinding getFragmentVb() {
|
protected FragmentAImportBinding getFragmentVb() {
|
||||||
@ -28,10 +40,72 @@ public class A_ImportFragment extends BaseFragment<FragmentAImportBinding> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void initEvent() {
|
public void initEvent() {
|
||||||
|
|
||||||
Vb.setting.setOnClickListener(v -> {
|
Vb.setting.setOnClickListener(v -> {
|
||||||
Intent intent = new Intent(getContext(), A_SettingActivity.class);
|
Intent intent = new Intent(getContext(), A_SettingActivity.class);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Vb.add.setOnClickListener(v -> {
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.READ_MEDIA_AUDIO) != PackageManager.PERMISSION_GRANTED) {
|
||||||
|
ActivityCompat.requestPermissions(requireActivity(),
|
||||||
|
new String[]{Manifest.permission.READ_MEDIA_AUDIO},
|
||||||
|
REQUEST_CODE_READ_MEDIA_AUDIO);
|
||||||
|
} else {
|
||||||
|
openAudioPicker();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
|
||||||
|
ActivityCompat.requestPermissions(requireActivity(),
|
||||||
|
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
|
||||||
|
REQUEST_CODE_READ_MEDIA_AUDIO);
|
||||||
|
} else {
|
||||||
|
openAudioPicker();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 处理权限请求结果
|
||||||
|
@Override
|
||||||
|
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||||
|
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||||
|
if (requestCode == REQUEST_CODE_READ_MEDIA_AUDIO) {
|
||||||
|
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||||
|
openAudioPicker();
|
||||||
|
} else {
|
||||||
|
Toast.makeText(requireContext(), "Permission denied", Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打开音频选择器
|
||||||
|
private void openAudioPicker() {
|
||||||
|
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
|
||||||
|
intent.setType("audio/*"); // 设置 MIME 类型为音频
|
||||||
|
intent.addCategory(Intent.CATEGORY_OPENABLE); // 限制为可打开的文件
|
||||||
|
startActivityForResult(intent, REQUEST_CODE_PICK_AUDIO);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 处理 Activity 结果
|
||||||
|
@Override
|
||||||
|
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
|
if (requestCode == REQUEST_CODE_PICK_AUDIO && resultCode == RESULT_OK) {
|
||||||
|
if (data != null) {
|
||||||
|
Uri audioUri = data.getData();
|
||||||
|
// 处理音频文件,例如播放或显示在列表中
|
||||||
|
Toast.makeText(requireContext(), "Audio Selected: " + audioUri.toString(), Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,9 @@
|
|||||||
|
package com.hi.music.player.ui.fragmnt.viewmodel;
|
||||||
|
|
||||||
|
import androidx.lifecycle.ViewModel;
|
||||||
|
|
||||||
|
public class A_VMImport extends ViewModel {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,8 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
android:shape="rectangle">
|
<solid android:color="#FFFFFF" />
|
||||||
|
<corners android:radius="18dp"/>
|
||||||
<corners android:radius="24dp" />
|
|
||||||
<solid android:color="#FFFFFF"/> <!-- 填充颜色 -->
|
|
||||||
|
|
||||||
</shape>
|
</shape>
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
android:id="@+id/main"
|
android:id="@+id/main"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
android:background="@drawable/home_background"
|
||||||
tools:context=".ui.activity.A_HomeActivity">
|
tools:context=".ui.activity.A_HomeActivity">
|
||||||
|
|
||||||
<androidx.viewpager2.widget.ViewPager2
|
<androidx.viewpager2.widget.ViewPager2
|
||||||
|
|||||||
@ -74,7 +74,7 @@
|
|||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
android:layout_marginEnd="16dp"
|
android:layout_marginEnd="16dp"
|
||||||
android:max="100"
|
android:max="100"
|
||||||
android:progress="50"
|
android:progress="0"
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/play_button"
|
app:layout_constraintBottom_toBottomOf="@+id/play_button"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/play_button"
|
app:layout_constraintEnd_toStartOf="@+id/play_button"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
@ -86,17 +86,16 @@
|
|||||||
android:layout_height="60dp"
|
android:layout_height="60dp"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
android:layout_marginEnd="16dp"
|
android:layout_marginEnd="16dp"
|
||||||
android:background="@drawable/pause_big"
|
android:background="@drawable/pause"
|
||||||
android:contentDescription="Play Button"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/artist_album_text" />
|
app:layout_constraintTop_toBottomOf="@id/artist_album_text" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/volume"
|
android:id="@+id/current"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
android:text="1:48"
|
android:text="00:00"
|
||||||
android:textColor="@android:color/white"
|
android:textColor="@android:color/white"
|
||||||
android:textSize="12sp"
|
android:textSize="12sp"
|
||||||
app:layout_constraintStart_toStartOf="@id/song_seekbar"
|
app:layout_constraintStart_toStartOf="@id/song_seekbar"
|
||||||
@ -127,7 +126,6 @@
|
|||||||
android:layout_width="52dp"
|
android:layout_width="52dp"
|
||||||
android:layout_height="52dp"
|
android:layout_height="52dp"
|
||||||
android:layout_marginStart="16dp"
|
android:layout_marginStart="16dp"
|
||||||
android:contentDescription="Previous Button"
|
|
||||||
android:src="@mipmap/light" />
|
android:src="@mipmap/light" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
@ -135,7 +133,6 @@
|
|||||||
android:layout_width="52dp"
|
android:layout_width="52dp"
|
||||||
android:layout_height="52dp"
|
android:layout_height="52dp"
|
||||||
android:layout_marginStart="14dp"
|
android:layout_marginStart="14dp"
|
||||||
android:contentDescription="Repeat Button"
|
|
||||||
android:src="@mipmap/timing" />
|
android:src="@mipmap/timing" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
@ -143,7 +140,6 @@
|
|||||||
android:layout_width="52dp"
|
android:layout_width="52dp"
|
||||||
android:layout_height="52dp"
|
android:layout_height="52dp"
|
||||||
android:layout_marginStart="14dp"
|
android:layout_marginStart="14dp"
|
||||||
android:contentDescription="Next Button"
|
|
||||||
android:src="@drawable/sleep" />
|
android:src="@drawable/sleep" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|||||||
@ -21,6 +21,7 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/ready_to_sleep"
|
android:text="@string/ready_to_sleep"
|
||||||
|
android:textColor="@color/white"
|
||||||
android:textSize="44sp"
|
android:textSize="44sp"
|
||||||
android:textStyle="italic|bold" />
|
android:textStyle="italic|bold" />
|
||||||
|
|
||||||
@ -29,6 +30,7 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/we_ve_carefully_prepared_sounds_for_you"
|
android:text="@string/we_ve_carefully_prepared_sounds_for_you"
|
||||||
|
android:textColor="@color/white"
|
||||||
android:textSize="14sp" />
|
android:textSize="14sp" />
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
@ -47,17 +49,18 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
android:text="@string/white_noise"
|
android:text="@string/white_noise"
|
||||||
|
android:textColor="@color/white"
|
||||||
android:textSize="20sp" />
|
android:textSize="20sp" />
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/recyclerView_second"
|
android:id="@+id/recyclerView_second"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
tools:itemCount="1"
|
|
||||||
tools:listitem="@layout/item_a_home_2"
|
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
android:nestedScrollingEnabled="false"
|
android:nestedScrollingEnabled="false"
|
||||||
android:orientation="horizontal" />
|
android:orientation="horizontal"
|
||||||
|
tools:itemCount="1"
|
||||||
|
tools:listitem="@layout/item_a_home_2" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/fourth_line_text"
|
android:id="@+id/fourth_line_text"
|
||||||
@ -65,17 +68,18 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
android:text="@string/voice_of_nature"
|
android:text="@string/voice_of_nature"
|
||||||
|
android:textColor="@color/white"
|
||||||
android:textSize="20sp" />
|
android:textSize="20sp" />
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/recyclerView_third"
|
android:id="@+id/recyclerView_third"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
tools:itemCount="1"
|
|
||||||
tools:listitem="@layout/item_a_home_3"
|
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
android:nestedScrollingEnabled="false"
|
android:nestedScrollingEnabled="false"
|
||||||
android:orientation="horizontal" />
|
android:orientation="horizontal"
|
||||||
|
tools:itemCount="1"
|
||||||
|
tools:listitem="@layout/item_a_home_3" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|||||||
@ -1,13 +1,20 @@
|
|||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content">
|
||||||
android:background="@drawable/round_rectangle">
|
|
||||||
|
<androidx.cardview.widget.CardView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="141dp"
|
||||||
|
app:cardCornerRadius="18dp"
|
||||||
|
app:cardElevation="0dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/background_image"
|
android:id="@+id/background_image"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="141dp"
|
android:layout_height="match_parent"
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerCrop"
|
||||||
android:src="@mipmap/cover" />
|
android:src="@mipmap/cover" />
|
||||||
|
|
||||||
@ -15,10 +22,10 @@
|
|||||||
android:id="@+id/overlay"
|
android:id="@+id/overlay"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="bottom"
|
||||||
android:background="#B2000000"
|
android:background="#B2000000"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:padding="8dp"
|
android:padding="8dp">
|
||||||
app:layout_constraintBottom_toBottomOf="parent">
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
@ -40,7 +47,7 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Evening"
|
android:text="Evening"
|
||||||
android:textColor="#FFFFFF"
|
android:textColor="@android:color/darker_gray"
|
||||||
android:textSize="14sp" />
|
android:textSize="14sp" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
@ -52,4 +59,6 @@
|
|||||||
android:src="@drawable/pause_flat" />
|
android:src="@drawable/pause_flat" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
</androidx.cardview.widget.CardView>
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|||||||
@ -4,13 +4,23 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<androidx.cardview.widget.CardView
|
||||||
|
android:id="@+id/card_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="118dp"
|
||||||
|
app:cardCornerRadius="18dp"
|
||||||
|
app:cardElevation="0dp"
|
||||||
|
app:layout_constraintBottom_toTopOf="@id/title">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/image"
|
android:id="@+id/image"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="118dp"
|
android:layout_height="match_parent"
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerCrop"
|
||||||
android:src="@mipmap/cover"
|
android:src="@mipmap/cover" />
|
||||||
app:layout_constraintBottom_toTopOf="@id/title" />
|
|
||||||
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/title"
|
android:id="@+id/title"
|
||||||
@ -19,10 +29,10 @@
|
|||||||
android:layout_marginStart="4dp"
|
android:layout_marginStart="4dp"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
android:text="Title"
|
android:text="Title"
|
||||||
android:textColor="#000000"
|
android:textColor="@color/white"
|
||||||
android:textSize="15sp"
|
android:textSize="15sp"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/image" />
|
app:layout_constraintTop_toBottomOf="@id/card_view" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/time"
|
android:id="@+id/time"
|
||||||
@ -31,7 +41,7 @@
|
|||||||
android:layout_marginStart="4dp"
|
android:layout_marginStart="4dp"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
android:text="Time"
|
android:text="Time"
|
||||||
android:textColor="#666666"
|
android:textColor="@android:color/darker_gray"
|
||||||
android:textSize="12sp"
|
android:textSize="12sp"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/title" />
|
app:layout_constraintTop_toBottomOf="@id/title" />
|
||||||
|
|||||||
@ -5,17 +5,26 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:padding="8dp">
|
android:padding="8dp">
|
||||||
|
|
||||||
<ImageView
|
<androidx.cardview.widget.CardView
|
||||||
android:id="@+id/cover"
|
android:id="@+id/card_view"
|
||||||
android:layout_width="48dp"
|
android:layout_width="48dp"
|
||||||
android:layout_height="48dp"
|
android:layout_height="48dp"
|
||||||
android:layout_marginStart="16dp"
|
android:layout_marginStart="16dp"
|
||||||
android:background="@drawable/round_rectangle"
|
app:cardCornerRadius="10dp"
|
||||||
android:scaleType="centerCrop"
|
app:cardElevation="0dp"
|
||||||
android:src="@mipmap/cover"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/cover"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:scaleType="centerCrop"
|
||||||
|
android:src="@mipmap/cover" />
|
||||||
|
|
||||||
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/title"
|
android:id="@+id/title"
|
||||||
@ -25,7 +34,7 @@
|
|||||||
android:text="Top Text"
|
android:text="Top Text"
|
||||||
android:textColor="@android:color/black"
|
android:textColor="@android:color/black"
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
app:layout_constraintStart_toEndOf="@+id/cover"
|
app:layout_constraintStart_toEndOf="@+id/card_view"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
@ -37,7 +46,7 @@
|
|||||||
android:textColor="@android:color/darker_gray"
|
android:textColor="@android:color/darker_gray"
|
||||||
android:textSize="14sp"
|
android:textSize="14sp"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintStart_toEndOf="@+id/cover"
|
app:layout_constraintStart_toEndOf="@+id/card_view"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/title" />
|
app:layout_constraintTop_toBottomOf="@+id/title" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user