A面功能页面优化
This commit is contained in:
parent
9ca0c2cebf
commit
b67911fde7
@ -36,7 +36,7 @@
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
<activity
|
||||
android:name=".ui.activity.HomeActivity"
|
||||
android:name=".ui.activity.A_HomeActivity"
|
||||
android:exported="true"
|
||||
android:screenOrientation="portrait">
|
||||
<intent-filter>
|
||||
@ -46,7 +46,7 @@
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".ui.activity.A_HomeActivity"
|
||||
android:name=".ui.activity.HomeActivity"
|
||||
android:exported="false"></activity>
|
||||
<activity
|
||||
android:name=".ui.activity.MainActivity"
|
||||
|
||||
@ -73,6 +73,10 @@ public class A_ImportFragmentAdapter extends RecyclerView.Adapter<A_ImportFragme
|
||||
}
|
||||
}
|
||||
|
||||
// 添加方法获取音频文件列表
|
||||
public List<AudioItem> getAudioFiles() {
|
||||
return audioFiles;
|
||||
}
|
||||
|
||||
public void setOnOptionClickListener(OnOptionClickListener listener) {
|
||||
this.onOptionClickListener = listener;
|
||||
|
||||
@ -0,0 +1,75 @@
|
||||
package com.hi.music.player.helper;
|
||||
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.widget.Toast;
|
||||
|
||||
public class SettingUtil {
|
||||
public static final String PRIVACY_POLICY_URL = "https://himelody.mystrikingly.com/privacy";
|
||||
public static final String TERMS_OF_SERVICE_URL = "https://himelody.mystrikingly.com/terms";
|
||||
|
||||
// 获取当前应用的版本号
|
||||
public static String getCurrentVersion(Context context) {
|
||||
try {
|
||||
PackageManager packageManager = context.getPackageManager();
|
||||
PackageInfo packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0);
|
||||
return packageInfo.versionName; // 返回版本名称
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
return null; // 返回null表示获取版本号失败
|
||||
}
|
||||
}
|
||||
|
||||
// 发送反馈
|
||||
public static void sendFeedback(Context context, String email, String subject) {
|
||||
Intent emailIntent = new Intent(Intent.ACTION_SEND);
|
||||
emailIntent.setType("message/rfc822");
|
||||
emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[]{email});
|
||||
emailIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
|
||||
try {
|
||||
context.startActivity(Intent.createChooser(emailIntent, "Send Feedback"));
|
||||
} catch (ActivityNotFoundException ex) {
|
||||
Toast.makeText(context, "There is no app that supports sending emails", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
|
||||
// 分享应用
|
||||
public static void shareApp(Context context) {
|
||||
String appPackageName = context.getPackageName();
|
||||
String appName = context.getApplicationInfo().loadLabel(context.getPackageManager()).toString();
|
||||
String appPlayStoreLink = "https://play.google.com/store/apps/details?id=" + appPackageName;
|
||||
|
||||
Intent shareIntent = new Intent(Intent.ACTION_SEND);
|
||||
shareIntent.setType("text/plain");
|
||||
shareIntent.putExtra(Intent.EXTRA_SUBJECT, "Check out this app: " + appName);
|
||||
shareIntent.putExtra(Intent.EXTRA_TEXT, "Download " + appName + " from Google Play: " + appPlayStoreLink);
|
||||
context.startActivity(Intent.createChooser(shareIntent, "Share " + appName + " via"));
|
||||
}
|
||||
|
||||
// 打开隐私政策
|
||||
public static void openPrivacyPolicy(Context context) {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(PRIVACY_POLICY_URL));
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
// 打开服务条款
|
||||
public static void openTermsOfService(Context context) {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(TERMS_OF_SERVICE_URL));
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
// 打开Google Play
|
||||
public static void openGooglePlay(Context context, String packageName) {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + packageName));
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
try {
|
||||
context.startActivity(intent);
|
||||
} catch (ActivityNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -49,6 +49,8 @@ public class MusicPlayerForegroundService extends Service {
|
||||
private int remainingTime; // 剩余时间(毫秒)
|
||||
private boolean isTimerRunning = false; // 计时器状态
|
||||
private boolean isTimerPaused = false; // 计时器是否暂停
|
||||
private MutableLiveData<Integer> currentPosition = new MutableLiveData<>();
|
||||
private MutableLiveData<Integer> duration = new MutableLiveData<>();
|
||||
|
||||
|
||||
// 自定义Binder类
|
||||
@ -137,7 +139,7 @@ public class MusicPlayerForegroundService extends Service {
|
||||
mediaPlayer = new MediaPlayer(); // 创建新的MediaPlayer实例
|
||||
}
|
||||
|
||||
fileName.setValue(getFileNameFromPath(path)); // 设置当前文件名
|
||||
fileName.setValue(audioItem.getName()); // 设置当前文件名
|
||||
setDataSource(path); // 设置数据源
|
||||
|
||||
mediaPlayer.prepareAsync(); // 异步准备
|
||||
@ -306,10 +308,6 @@ public class MusicPlayerForegroundService extends Service {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
//获取audioItem的名字
|
||||
public String getName() {
|
||||
return mediaPlayer != null ? audioItem.getName() : null;
|
||||
}
|
||||
|
||||
//获取audioItem
|
||||
public AudioItem getAudioItem() {
|
||||
@ -321,9 +319,14 @@ public class MusicPlayerForegroundService extends Service {
|
||||
return remainingTimeLiveData; // 提供LiveData访问
|
||||
}
|
||||
|
||||
// 获取当前播放位置(毫秒)
|
||||
public int getCurrentPosition() {
|
||||
return mediaPlayer != null ? mediaPlayer.getCurrentPosition() : 0;
|
||||
// 获取当前播放位置的 LiveData
|
||||
public LiveData<Integer> getCurrentPositionLiveData() {
|
||||
return currentPosition;
|
||||
}
|
||||
|
||||
// 获取音频总时长的 LiveData
|
||||
public LiveData<Integer> getDurationLiveData() {
|
||||
return duration;
|
||||
}
|
||||
|
||||
// 获取音频总时长(毫秒)
|
||||
@ -331,6 +334,27 @@ public class MusicPlayerForegroundService extends Service {
|
||||
return mediaPlayer != null ? mediaPlayer.getDuration() : 0;
|
||||
}
|
||||
|
||||
// 播放音频时更新进度
|
||||
public void startUpdatingProgress() {
|
||||
// 获取音频总时长
|
||||
if (mediaPlayer != null) {
|
||||
duration.postValue(mediaPlayer.getDuration());
|
||||
}
|
||||
|
||||
// 使用 Handler 定时更新 currentPosition
|
||||
Handler handler = new Handler(Looper.getMainLooper());
|
||||
Runnable runnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
|
||||
currentPosition.postValue(mediaPlayer.getCurrentPosition());
|
||||
handler.postDelayed(this, 1000); // 每隔1秒更新一次
|
||||
}
|
||||
}
|
||||
};
|
||||
handler.post(runnable); // 启动更新
|
||||
}
|
||||
|
||||
// 跳转到指定播放位置
|
||||
public void seekTo(int position) {
|
||||
if (mediaPlayer != null) {
|
||||
|
||||
@ -26,7 +26,6 @@ public class A_HomeActivity extends BaseActivity<ActivityAhomeBinding> {
|
||||
|
||||
private MusicPlayerForegroundService musicService; // 音乐播放服务
|
||||
private boolean isBound = false; // 服务是否绑定
|
||||
private Handler progressHandler; // 用于更新进度的Handler
|
||||
|
||||
private final int[] defaultIcons = {R.drawable.home_unselect, R.drawable.import_unselect}; // 默认图标
|
||||
private final int[] selectedIcons = {R.drawable.home_select, R.drawable.import_select}; // 选中图标
|
||||
@ -43,8 +42,10 @@ public class A_HomeActivity extends BaseActivity<ActivityAhomeBinding> {
|
||||
isBound = true; // 服务已绑定
|
||||
Log.d("A_HomeActivity", "isBound");
|
||||
updatePlayButtonState(); // 更新播放按钮状态
|
||||
startUpdatingProgress(); // 启动进度更新
|
||||
updateProgress(); // 启动进度更新
|
||||
observeIsPlaying(); // 观察播放状态变化
|
||||
|
||||
musicService.getFileName().observe(A_HomeActivity.this, vb.topText::setText); // 设置标题
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -106,6 +107,7 @@ public class A_HomeActivity extends BaseActivity<ActivityAhomeBinding> {
|
||||
musicService.resumeAudio(); // 恢复播放
|
||||
}
|
||||
updatePlayButtonState(); // 更新播放按钮图标
|
||||
updateProgress();
|
||||
}
|
||||
}
|
||||
|
||||
@ -120,35 +122,29 @@ public class A_HomeActivity extends BaseActivity<ActivityAhomeBinding> {
|
||||
// 更新进度
|
||||
private void updateProgress() {
|
||||
if (isBound && musicService != null) {
|
||||
int currentPosition = musicService.getCurrentPosition(); // 当前播放位置
|
||||
int duration = musicService.getDuration(); // 音频总时长
|
||||
String fileName = musicService.getFileName().getValue(); // 当前文件名
|
||||
String name = musicService.getName();//// 当前文件名
|
||||
// 开始更新播放进度
|
||||
musicService.startUpdatingProgress();
|
||||
|
||||
vb.bottomText1.setText(formatTime(currentPosition)); // 更新当前时间文本
|
||||
vb.bottomText2.setText(formatTime(duration)); // 更新总时间文本
|
||||
vb.topText.setText(name); // 更新文件名文本
|
||||
// 观察当前播放位置
|
||||
musicService.getCurrentPositionLiveData().observe(this, position -> {
|
||||
if (musicService.getDurationLiveData().getValue() != null) {
|
||||
int duration = musicService.getDurationLiveData().getValue();
|
||||
vb.bottomText1.setText(formatTime(position)); // 更新当前时间文本
|
||||
|
||||
if (duration > 0) {
|
||||
int progress = (int) ((currentPosition / (float) duration) * 100); // 计算进度
|
||||
vb.circularProgressBar.setProgress(progress); // 更新进度条
|
||||
}
|
||||
if (duration > 0) {
|
||||
int progress = (int) ((position / (float) duration) * 100); // 计算进度
|
||||
vb.circularProgressBar.setProgress(progress); // 更新进度条
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 观察音频总时长
|
||||
musicService.getDurationLiveData().observe(this, duration -> {
|
||||
vb.bottomText2.setText(formatTime(duration)); // 更新总时间文本
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 启动进度更新
|
||||
private void startUpdatingProgress() {
|
||||
if (progressHandler != null) return; // 如果已存在Handler,则返回
|
||||
progressHandler = new Handler(Looper.getMainLooper());
|
||||
progressHandler.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateProgress(); // 更新进度
|
||||
progressHandler.postDelayed(this, 1000); // 每秒更新一次
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
// 观察播放状态变化
|
||||
private void observeIsPlaying() {
|
||||
if (isBound && musicService != null) {
|
||||
@ -216,9 +212,6 @@ public class A_HomeActivity extends BaseActivity<ActivityAhomeBinding> {
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
unbindService(serviceConnection); // 解绑服务
|
||||
if (progressHandler != null) {
|
||||
progressHandler.removeCallbacksAndMessages(null); // 移除所有回调
|
||||
}
|
||||
}
|
||||
|
||||
// 格式化时间
|
||||
|
||||
@ -46,13 +46,12 @@ public class A_PlayActivity extends BaseActivity<ActivityAplayBinding> {
|
||||
|
||||
// 设置观察者
|
||||
musicService.getIsPlaying().observe(A_PlayActivity.this, this::updatePlayButton);
|
||||
// musicService.getFileName().observe(A_PlayActivity.this, vb.songTitle::setText);
|
||||
vb.songTitle.setText(musicService.getName());
|
||||
musicService.getFileName().observe(A_PlayActivity.this, vb.songTitle::setText);
|
||||
|
||||
// 更新进度条和时间
|
||||
updateSeekBarAndTime(); // 添加这一行以确保服务连接时更新UI
|
||||
|
||||
startUpdatingProgress(); // 启动进度更新
|
||||
musicService.startUpdatingProgress(); // 启动进度更新
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -134,36 +133,33 @@ public class A_PlayActivity extends BaseActivity<ActivityAplayBinding> {
|
||||
musicService.resumeAudio();
|
||||
}
|
||||
}
|
||||
if (musicService != null) {
|
||||
musicService.startUpdatingProgress();
|
||||
}
|
||||
});
|
||||
|
||||
vb.backButton.setOnClickListener(v -> finish()); // 返回按钮点击事件
|
||||
}
|
||||
|
||||
// 启动进度更新
|
||||
private void startUpdatingProgress() {
|
||||
if (progressHandler == null) {
|
||||
progressHandler = new Handler(Looper.getMainLooper());
|
||||
progressHandler.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateSeekBarAndTime(); // 更新进度条和时间
|
||||
progressHandler.postDelayed(this, 1000); // 每秒更新
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
// 更新进度条和时间显示
|
||||
private void updateSeekBarAndTime() {
|
||||
if (isBound && musicService != null && Boolean.TRUE.equals(musicService.getIsPlaying().getValue())) {
|
||||
int currentPosition = musicService.getCurrentPosition(); // 当前播放进度
|
||||
int duration = musicService.getDuration(); // 音频总时长
|
||||
if (duration > 0) {
|
||||
// 更新进度条和时间显示
|
||||
vb.songSeekbar.setProgress((int) ((currentPosition / (float) duration) * 100));
|
||||
vb.current.setText(formatTime(currentPosition));
|
||||
if (isBound && musicService != null) {
|
||||
// 观察当前播放进度
|
||||
musicService.getCurrentPositionLiveData().observe(this, position -> {
|
||||
if (musicService.getDurationLiveData().getValue() != null) {
|
||||
int duration = musicService.getDurationLiveData().getValue();
|
||||
if (duration > 0) {
|
||||
vb.songSeekbar.setProgress((int) ((position / (float) duration) * 100));
|
||||
vb.current.setText(formatTime(position));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 观察音频总时长
|
||||
musicService.getDurationLiveData().observe(this, duration -> {
|
||||
vb.time.setText(formatTime(duration));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -273,28 +269,6 @@ public class A_PlayActivity extends BaseActivity<ActivityAplayBinding> {
|
||||
bottomSheetDialog.show(); // 显示 BottomSheetDialog
|
||||
}
|
||||
|
||||
|
||||
// 格式化时间显示
|
||||
private String formatTime(int milliseconds) {
|
||||
int minutes = (milliseconds / 1000) / 60;
|
||||
int seconds = (milliseconds / 1000) % 60;
|
||||
return String.format(Locale.getDefault(), "%d:%02d", minutes, seconds);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (isBound) {
|
||||
unbindService(serviceConnection); // 解绑服务
|
||||
isBound = false;
|
||||
}
|
||||
if (progressHandler != null) {
|
||||
progressHandler.removeCallbacksAndMessages(null); // 移除所有更新任务
|
||||
progressHandler = null; // 释放引用
|
||||
}
|
||||
}
|
||||
|
||||
// 进度条的监听器
|
||||
private class SeekBarListener implements SeekBar.OnSeekBarChangeListener {
|
||||
|
||||
@ -316,8 +290,17 @@ public class A_PlayActivity extends BaseActivity<ActivityAplayBinding> {
|
||||
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||
startUpdatingProgress(); // 拖动结束后重新启动进度更新
|
||||
musicService.startUpdatingProgress();
|
||||
; // 拖动结束后重新启动进度更新
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 格式化时间显示
|
||||
private String formatTime(int milliseconds) {
|
||||
int minutes = (milliseconds / 1000) / 60;
|
||||
int seconds = (milliseconds / 1000) % 60;
|
||||
return String.format(Locale.getDefault(), "%d:%02d", minutes, seconds);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -334,4 +317,17 @@ public class A_PlayActivity extends BaseActivity<ActivityAplayBinding> {
|
||||
public void onClick(View v) {
|
||||
// 处理其他点击事件
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (isBound) {
|
||||
unbindService(serviceConnection); // 解绑服务
|
||||
isBound = false;
|
||||
}
|
||||
if (progressHandler != null) {
|
||||
progressHandler.removeCallbacksAndMessages(null); // 移除所有更新任务
|
||||
progressHandler = null; // 释放引用
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@ package com.hi.music.player.ui.activity;
|
||||
import android.view.View;
|
||||
|
||||
import com.hi.music.player.databinding.ActivityAsettingBinding;
|
||||
import com.hi.music.player.helper.SettingUtil;
|
||||
|
||||
public class A_SettingActivity extends BaseActivity<ActivityAsettingBinding> {
|
||||
|
||||
@ -20,6 +21,26 @@ public class A_SettingActivity extends BaseActivity<ActivityAsettingBinding> {
|
||||
@Override
|
||||
protected void onInitClick() {
|
||||
|
||||
|
||||
vb.version.setText("Version: " + SettingUtil.getCurrentVersion(this));
|
||||
|
||||
vb.feedback.setOnClickListener(v -> {
|
||||
SettingUtil.sendFeedback(this, "john.mckinley@examplepetstore.com", "Feedback");
|
||||
});
|
||||
|
||||
vb.share.setOnClickListener(v -> {
|
||||
SettingUtil.shareApp(this);
|
||||
});
|
||||
|
||||
vb.privacy.setOnClickListener(v -> {
|
||||
SettingUtil.openPrivacyPolicy(this);
|
||||
});
|
||||
|
||||
vb.terms.setOnClickListener(v -> {
|
||||
SettingUtil.openTermsOfService(this);
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -5,12 +5,14 @@ import static android.app.Activity.RESULT_OK;
|
||||
import android.Manifest;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Intent;
|
||||
import android.content.UriPermission;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Environment;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
@ -71,14 +73,24 @@ public class A_ImportFragment extends BaseFragment<FragmentAImportBinding> {
|
||||
|
||||
private void updateAudioList(List<AudioItem> audioFiles) {
|
||||
adapter.setAudioFiles(audioFiles);
|
||||
// 每次更新音频列表时,重新持久化权限
|
||||
for (AudioItem item : audioFiles) {
|
||||
Uri audioUri = Uri.parse(item.getFile());
|
||||
checkPersistableUriPermission(audioUri);
|
||||
}
|
||||
}
|
||||
|
||||
private void initEvent() {
|
||||
// 确保只设置一次点击事件
|
||||
Vb.setting.setOnClickListener(v -> startActivity(new Intent(getContext(), A_SettingActivity.class)));
|
||||
Vb.add.setOnClickListener(v -> checkAndOpenAudioPicker());
|
||||
Vb.add.setOnClickListener(v -> {
|
||||
Log.d("A_ImportFragment", "Add button clicked"); // 添加调试日志
|
||||
checkAndOpenAudioPicker();
|
||||
});
|
||||
adapter.setOnOptionClickListener(this::showPopupWindow);
|
||||
}
|
||||
|
||||
|
||||
private void showPopupWindow(int position, String filePath, View anchorView) {
|
||||
// 膨胀 PopupWindow 的布局
|
||||
View popupView = LayoutInflater.from(requireContext()).inflate(R.layout.options_popup_window, null);
|
||||
@ -90,7 +102,6 @@ public class A_ImportFragment extends BaseFragment<FragmentAImportBinding> {
|
||||
true);
|
||||
|
||||
// 设置背景为透明
|
||||
// popupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
|
||||
popupWindow.setOutsideTouchable(true); // 允许点击外部关闭
|
||||
|
||||
// 获取 PopupWindow 中的控件
|
||||
@ -109,12 +120,9 @@ public class A_ImportFragment extends BaseFragment<FragmentAImportBinding> {
|
||||
});
|
||||
|
||||
// 显示 PopupWindow,设置其位置
|
||||
int[] location = new int[2];
|
||||
anchorView.getLocationOnScreen(location);
|
||||
popupWindow.showAsDropDown(anchorView, 0, 10); // 在 anchorView 下方显示
|
||||
}
|
||||
|
||||
|
||||
private void showRenameDialog(int position) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(requireContext());
|
||||
View dialogView = LayoutInflater.from(requireContext()).inflate(R.layout.rename_dialog, null);
|
||||
@ -129,10 +137,7 @@ public class A_ImportFragment extends BaseFragment<FragmentAImportBinding> {
|
||||
|
||||
confirm.setOnClickListener(view -> {
|
||||
String newName = inputField.getText().toString();
|
||||
|
||||
// 更新适配器中的音频文件名称
|
||||
adapter.updateTitle(position, newName);
|
||||
|
||||
Toast.makeText(requireContext(), "新名称: " + newName + ", 项目: " + position, Toast.LENGTH_SHORT).show();
|
||||
subDialog.dismiss();
|
||||
});
|
||||
@ -149,6 +154,7 @@ public class A_ImportFragment extends BaseFragment<FragmentAImportBinding> {
|
||||
}
|
||||
|
||||
private void checkAndOpenAudioPicker() {
|
||||
Log.d("A_ImportFragment", "checkAndOpenAudioPicker called"); // 添加调试日志
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.READ_MEDIA_AUDIO) != PackageManager.PERMISSION_GRANTED) {
|
||||
requestPermissions(Manifest.permission.READ_MEDIA_AUDIO);
|
||||
@ -164,6 +170,7 @@ public class A_ImportFragment extends BaseFragment<FragmentAImportBinding> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void requestPermissions(String permission) {
|
||||
ActivityCompat.requestPermissions(requireActivity(), new String[]{permission}, REQUEST_CODE_READ_MEDIA_AUDIO);
|
||||
}
|
||||
@ -173,6 +180,7 @@ public class A_ImportFragment extends BaseFragment<FragmentAImportBinding> {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
if (requestCode == REQUEST_CODE_READ_MEDIA_AUDIO) {
|
||||
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
Log.d("A_ImportFragment", "Permission granted");
|
||||
openAudioPicker();
|
||||
} else {
|
||||
Toast.makeText(requireContext(), "Permission denied", Toast.LENGTH_SHORT).show();
|
||||
@ -180,6 +188,7 @@ public class A_ImportFragment extends BaseFragment<FragmentAImportBinding> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void openAudioPicker() {
|
||||
if (!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
|
||||
Toast.makeText(getContext(), "外部存储不可用", Toast.LENGTH_LONG).show();
|
||||
@ -200,7 +209,10 @@ public class A_ImportFragment extends BaseFragment<FragmentAImportBinding> {
|
||||
if (requestCode == REQUEST_CODE_PICK_AUDIO && resultCode == RESULT_OK && data != null) {
|
||||
Uri selectedAudioUri = data.getData();
|
||||
if (selectedAudioUri != null) {
|
||||
requireActivity().grantUriPermission(requireActivity().getPackageName(), selectedAudioUri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
// 持久化 URI 访问权限
|
||||
requireActivity().getContentResolver().takePersistableUriPermission(
|
||||
selectedAudioUri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
|
||||
try {
|
||||
viewModel.addAudioFile(selectedAudioUri);
|
||||
} catch (IOException e) {
|
||||
@ -213,6 +225,26 @@ public class A_ImportFragment extends BaseFragment<FragmentAImportBinding> {
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
// 检查所有音频文件的持久化权限
|
||||
for (AudioItem item : adapter.getAudioFiles()) {
|
||||
Uri audioUri = Uri.parse(item.getFile());
|
||||
checkPersistableUriPermission(audioUri);
|
||||
}
|
||||
observeAudioFiles();
|
||||
}
|
||||
|
||||
// 检查并持久化权限
|
||||
private void checkPersistableUriPermission(Uri uri) {
|
||||
boolean hasPermission = false;
|
||||
for (UriPermission permission : requireContext().getContentResolver().getPersistedUriPermissions()) {
|
||||
if (permission.getUri().equals(uri) && permission.isReadPermission()) {
|
||||
hasPermission = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasPermission) {
|
||||
requireContext().getContentResolver().takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,7 +83,7 @@
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="60dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:background="@drawable/pause"
|
||||
android:background="@drawable/play"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/song_seekbar"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/song_seekbar" />
|
||||
|
||||
@ -43,6 +43,7 @@
|
||||
|
||||
<!-- First row -->
|
||||
<LinearLayout
|
||||
android:id="@+id/about"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
@ -66,10 +67,10 @@
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<ImageView
|
||||
<TextView
|
||||
android:id="@+id/version"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/arrow_right" />
|
||||
android:layout_height="wrap_content" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Second row -->
|
||||
@ -97,6 +98,7 @@
|
||||
android:textSize="16sp" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/feedback"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/arrow_right" />
|
||||
@ -127,6 +129,7 @@
|
||||
android:textSize="16sp" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/share"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/arrow_right" />
|
||||
@ -156,6 +159,7 @@
|
||||
android:textSize="16sp" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/privacy"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/arrow_right" />
|
||||
@ -185,6 +189,7 @@
|
||||
android:textSize="16sp" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/terms"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/arrow_right" />
|
||||
|
||||
@ -13,8 +13,8 @@
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="32sp"
|
||||
android:text="Parents voice"
|
||||
android:textSize="32sp"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="32sp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
@ -33,8 +33,11 @@
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/import_recycler"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toBottomOf="@+id/title" />
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
app:layout_constraintTop_toBottomOf="@+id/title"
|
||||
app:layout_constraintBottom_toBottomOf="parent"/>
|
||||
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/add"
|
||||
|
||||
@ -51,12 +51,12 @@
|
||||
android:textSize="14sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/play_icon"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:src="@drawable/play_flat" />
|
||||
<!-- <ImageView-->
|
||||
<!-- android:id="@+id/play_icon"-->
|
||||
<!-- android:layout_width="32dp"-->
|
||||
<!-- android:layout_height="32dp"-->
|
||||
<!-- android:layout_gravity="center_vertical"-->
|
||||
<!-- android:src="@drawable/play_flat" />-->
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
|
||||
@ -9,7 +9,6 @@
|
||||
android:id="@+id/card_view"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginStart="16dp"
|
||||
app:cardCornerRadius="10dp"
|
||||
app:cardElevation="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
@ -25,7 +24,6 @@
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="wrap_content"
|
||||
@ -49,14 +47,14 @@
|
||||
app:layout_constraintStart_toEndOf="@+id/card_view"
|
||||
app:layout_constraintTop_toBottomOf="@+id/title" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/pause"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:src="@drawable/play_shadow"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
<!-- <ImageView-->
|
||||
<!-- android:id="@+id/pause"-->
|
||||
<!-- android:layout_width="20dp"-->
|
||||
<!-- android:layout_height="20dp"-->
|
||||
<!-- android:layout_marginStart="8dp"-->
|
||||
<!-- android:src="@drawable/play_shadow"-->
|
||||
<!-- app:layout_constraintBottom_toBottomOf="parent"-->
|
||||
<!-- app:layout_constraintEnd_toEndOf="parent"-->
|
||||
<!-- app:layout_constraintTop_toTopOf="parent" />-->
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user