Я использую MediaSessionService в качестве службы переднего плана для воспроизведения звука (в моем проекте аудиоплеера для Android). Раньше я использовал ExoPlayer и службу, тогда я извлекал (метод getAudios(Activity Activity)) аудиофайлы с устройства с помощью ContentResolver и устанавливал аудиоданные в объекте AudioModel. И в тот раз все было в порядке и работало хорошо в Android 10. Но когда я переключился на MediaSessionService и выполнил все приведенные здесь инструкции, приложение отлично работает в Android 8, но звук не воспроизводится в Android 10. Когда я проверяю журнал, у меня появляется видел, что после буферизации плеер переходит в состояние ожидания, что указывает на то, что с mediaItem происходит какая-то ошибка (насколько я знаю до сих пор). Но то же самое работает и в Android 8, то есть плеер переходит в состояние готовности после состояния буферизации. Мне интересно, есть ли какие-либо другие требования к разрешениям в Android 10?
Позвольте мне еще раз подчеркнуть один момент: без использования MediaSession, MediaController и т. д. все работает нормально как в Android 8, так и в 10.
= Build.VERSION_CODES.Q) {
collections = MediaStore.Audio.Media.getContentUri(MediaStore.VOLUME_EXTERNAL);
} else collections = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
String[] projection = new String[]{
MediaStore.Audio.Media._ID,
MediaStore.Audio.Media.DISPLAY_NAME,
MediaStore.Audio.Media.ALBUM,
MediaStore.Audio.Media.ARTIST,
MediaStore.Audio.Media.DATE_ADDED,
MediaStore.Audio.Media.DURATION,
MediaStore.Audio.Media.SIZE,
MediaStore.Audio.Media.DATA
};
try (Cursor cursor = resolver.query(collections, projection, null, null, null)) {
assert cursor != null;
int idCol = cursor.getColumnIndex(MediaStore.Audio.Media._ID);
int nameCol = cursor.getColumnIndex(MediaStore.Audio.Media.DISPLAY_NAME);
int albumCol = cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM);
int artistCol = cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST);
int dateAddedCol = cursor.getColumnIndex(MediaStore.Audio.Media.DATE_ADDED);
int durationCol = cursor.getColumnIndex(MediaStore.Audio.Media.DURATION);
int sizeCol = cursor.getColumnIndex(MediaStore.Audio.Media.SIZE);
int dataCol = cursor.getColumnIndex(MediaStore.Audio.Media.DATA);
while (cursor.moveToNext()) {
AudioModel model = new AudioModel(Uri.parse(cursor.getString(dataCol)), cursor.getString(nameCol));
model.setMedia_id(cursor.getString(idCol));
model.setAlbum(cursor.getString(albumCol));
model.setArtist(cursor.getString(artistCol));
model.setDateAdded(cursor.getString(dateAddedCol));
model.setSize(cursor.getLong(sizeCol));
model.setDuration(cursor.getLong(durationCol));
audioModels.add(model);
}
} catch (NullPointerException e) {
Constants.LOG.log("Exception: " + e.getMessage());
}
mutableLiveData.setValue(audioModels);
return mutableLiveData;
}
@UnstableApi public class MediaSessionCallback implements MediaSession.Callback {
@NonNull
@Override
public ListenableFuture onAddMediaItems(@NonNull MediaSession mediaSession, @NonNull MediaSession.ControllerInfo controller, @NonNull List mediaItems) {
Constants.LOG.mediaSessionLog("MediaSession > onAddMediaItems, size -> "+mediaItems.size());
List updatedMediaItems = mediaItems.stream().peek(
mediaItem ->
mediaItem.buildUpon()
.setUri(mediaItem.requestMetadata.mediaUri)
.build()).collect(Collectors.toList());
return Futures.immediateFuture(updatedMediaItems);
}
@NonNull
@OptIn(markerClass = UnstableApi.class) @Override
public ListenableFuture onSetMediaItems(@NonNull MediaSession mediaSession, @NonNull MediaSession.ControllerInfo controller, @NonNull List mediaItems, int startIndex, long startPositionMs) {
Constants.LOG.mediaSessionLog("MediaSession > onAddMediaItems, size > "+mediaItems.size()+", startIndex > "+startIndex);
return MediaSession.Callback.super.onSetMediaItems(mediaSession, controller, mediaItems, startIndex, startPositionMs);
}
}
public class AudioPlaybackService extends MediaSessionService {
private ExoPlayer player;
private MediaSession mediaSession = null;
// Create your Player and MediaSession in the onCreate lifecycle event
@OptIn(markerClass = UnstableApi.class) @Override
public void onCreate() {
super.onCreate();
if (this.player == null) this.player = new ExoPlayer.Builder(this).build();
this.mediaSession = new MediaSession.Builder(this, player)
.setCallback(new MediaSessionCallback())
.build();
}
// The user dismissed the app from the recent tasks
@Override
public void onTaskRemoved(@Nullable Intent rootIntent) {
Player player = this.mediaSession.getPlayer();
if (!player.getPlayWhenReady()
|| player.getMediaItemCount() == 0
|| player.getPlaybackState() == Player.STATE_ENDED) {
// Stop the service if not playing, continue playing in the background
// otherwise.
stopSelf();
}
}
@Nullable
@Override
public MediaSession onGetSession(@NonNull MediaSession.ControllerInfo controllerInfo) {
return this.mediaSession;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
if (intent == null || intent.getAction() == null) return Service.START_NOT_STICKY;
String action = intent.getAction();
this.player = PlayerCreator.getPlayer(getApplicationContext());
switch (action) {
case Constants.Service.START_AUDIO_PLAYBACK_FOREGROUND:
startForeground(Constants.Notification.AUDIO_PLAYING_NOTIFICATION_CHANNEL_ID, createNotification());
playMusic();
break;
case Constants.Service.STOP_AUDIO_PLAYBACK_FOREGROUND:
stopForeground(true);
playPause();
stopSelf();
break;
case Constants.Service.PLAY_PAUSE_AUDIO_PLAYBACK_FOREGROUND:
startForeground(Constants.Notification.AUDIO_PLAYING_NOTIFICATION_CHANNEL_ID, createNotification());
playPause();
break;
case Constants.Service.NEXT_AUDIO_PLAYBACK_FOREGROUND:
startForeground(Constants.Notification.AUDIO_PLAYING_NOTIFICATION_CHANNEL_ID, createNotification());
next();
break;
case Constants.Service.PREVIOUS_AUDIO_PLAYBACK_FOREGROUND:
startForeground(Constants.Notification.AUDIO_PLAYING_NOTIFICATION_CHANNEL_ID, createNotification());
previous();
break;
case Constants.Service.MEDIA_ITEM_TRANSITION:
startForeground(Constants.Notification.AUDIO_PLAYING_NOTIFICATION_CHANNEL_ID, createNotification());
break;
}
return START_NOT_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
this.mediaSession.getPlayer().release();
this.mediaSession.release();
this.mediaSession = null;
super.onDestroy();
}
}
setUpPlayer — это метод, который используется для установки медиаэлементов в проигрыватель. Он извлекает идентификатор и uri из класса модели, создает mediaItem, а затем устанавливает значение MediaController
@OptIn(markerClass = UnstableApi.class)
private void setUpPlayer(List audioModels) {
Constants.LOG.log("In setup player");
if (this.binding == null) this.onDestroy(); // TODO: Destroying the fragment
// Initialize Exoplayer;
this.mediaController.addListener(this);
// Setting the ExoPlayer MediaItems / MediaSources
List mediaItemList = new ArrayList();
for (AudioModel file : audioModels) {
Constants.LOG.mediaSessionLog("AudioModel URI : "+file.getData());
MediaItem item = new MediaItem.Builder().setMediaId(file.getMedia_id()).setUri(file.getData()).build();
Constants.LOG.mediaSessionLog("Audio URI : "+item.requestMetadata.mediaUri);
mediaItemList.add(item);
}
this.mediaController.setMediaItems(mediaItemList);
this.mediaController.prepare();
this.binding.progressBarAudioFileLoad.setVisibility(View.GONE);
}
Здесь я запрашиваю разрешения
public class HomeActivity extends AppCompatActivity {
private String[] permissions;
/**
* settingOpenResultLauncher is used to open setting for permission grant and check the result
*/
private ActivityResultLauncher settingOpenResultLauncher;
private ActivityHomeBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
Constants.LOG.lifeCycleLog(this.getClass().getSimpleName()+this.INSTANCE_ID+": onCreate");
// Handle the splash screen transition.
SplashScreen.installSplashScreen(this);
super.onCreate(savedInstanceState);
//Do the below before initializing binding
this.permissions = new String[]{Manifest.permission.READ_EXTERNAL_STORAGE};
if(!isPermissionsGranted()) requestPermission(permissions);
this.settingOpenResultLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),
result -> {
if(!isPermissionsGranted()) requestPermission(HomeActivity.this.permissions);
else finish();
});
}
private void requestPermission(String... permissions) {
// TODO: add other permissions which are needed
ActivityCompat.requestPermissions(HomeActivity.this,
permissions,
Constants.PERMISSIONS.PERMISSIONS_CODE);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == Constants.PERMISSIONS.PERMISSIONS_CODE) {
int i = 0;
for (; i < grantResults.length; i++) {
if (grantResults == PackageManager.PERMISSION_DENIED) {
if(!shouldShowRequestPermissionRationale(permissions)) {
// This executes when second time requesting the permission
// TODO: Show any alert that why the permission(s) should be granted
openSetting();
} else requestPermission(permissions);
}
}
}
}
/**
* This method is used to open settings when user selects don't show permission asking again
*/
private void openSetting() {
Intent i = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getPackageName(), null);
i.setData(uri);
if (this.settingOpenResultLauncher == null) {
Toast.makeText(this, "Unable to open setting", Toast.LENGTH_SHORT).show();
return;
}
this.settingOpenResultLauncher.launch(i);
}
private boolean isPermissionsGranted() {
String[] permissions;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
permissions = new String[]{Manifest.permission.READ_MEDIA_AUDIO,
Manifest.permission.READ_MEDIA_VIDEO};
} else {
permissions = new String[]{Manifest.permission.READ_EXTERNAL_STORAGE};
}
// TODO: for android 13+ which permissions are not handled, handle those below
for (String permission : permissions)
if (ContextCompat.checkSelfPermission(HomeActivity.this, permission)
== PackageManager.PERMISSION_DENIED)
return false;
return true;
}
}
Подробнее здесь: https://stackoverflow.com/questions/784 ... -and-above
MediaSession не может воспроизводить звук в Android 10 и выше ⇐ Android
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение