Потоковая музыка в андроид студии - PullRequest
0 голосов
/ 29 июня 2018

Я хочу прослушать mp3-файл, который будет длиться около 1 часа. Я хочу воспроизвести файл в фоновом режиме. Я видел много обучающих видео. Некоторые из них использовали сервис, а некоторые использовали asyntask. Я не знаю, что я могу выбрать между ними тоже. Какой из них лучше?

Ответы [ 2 ]

0 голосов
/ 29 июня 2018

Вы определенно захотите использовать сервис, а не AsyncTask. Основная причина этого заключается в том, что если вы хотите, чтобы музыка запускалась, даже когда приложение было приостановлено / помещено в фоновый режим, например, когда пользователь переходит в другое приложение, это будет делать только служба. AsyncTasks не будет работать в фоновом режиме таким образом.

Чтобы включить некоторую справочную информацию о фоновых сервисах, они используют события из контекстов приложения, таких как действия и сервисы переднего плана, чтобы уведомить их о том, когда следует выполнять работу. Эта работа выполняется с помощью функции onStartCommand () службы. Подробнее об услугах можно прочитать в документации для Android https://developer.android.com/guide/components/services

При этом служба будет работать в фоновом режиме, но ее все равно можно будет прервать, если ОС потребуется выполнить еще одну задачу. Поэтому, чтобы музыка воспроизводилась надежно и перезапускалась вскоре после того, как ОС по какой-либо причине выгрузила службу, вам необходимо указать START_STICKY в качестве возвращаемого значения из функции onStartCommand () службы. Но, как и во всем Android, предпочитайте версию совместимости START_STICKY_COMPATIBILITY несовместимой версии. START_STICKY / START_STICKY_COMPATIBILITY подходит для возврата в случае команды PLAY. То есть если событие, которое получает служба, это PLAY.

Возврат START_STICKY или START_STICKY_COMPATIBILITY из onStartCommand () в каждом случае приведёт к появлению службы, которая никогда не умирает, что потребляет вычислительную мощность и время автономной работы телефона, на котором он работает. Это может привести к потреблению процессора и разрядке батареи. Вот почему важно возвращать START_NOT_STICKY из onStartCommand, если пользователь пытается сделать паузу. То есть если событие, которое получает служба, - это ПАУЗА.

Вот урезанная версия того, что вы можете сделать так, чтобы ваша onStartCommand вашего сервиса выглядела так:

public int onStartCommand(Intent intent, int flags, int startId) {

    if (intent.getAction().equals(ACTION_PLAY)) {
        ...
        return START_STICKY_COMPATIBILITY;
    } else { // i.e. action is ACTION_PAUSE
        ...
        return START_NOT_STICKY;
    }
}

Редактировать: чтобы оставить это и остаток этого ответа - пытаясь упростить пост, я исключил соображения, связанные с ожиданием подготовки медиаплеера. Как примечание, сервис, вероятно, также должен будет обрабатывать ожидание, пока медиаплеер готовится к отдельному событию или из обработки события PLAY. Может также быть обработано изнутри действия до запуска службы, но это может быть более или менее сложным. Объяснить остальную часть проблем / соображений в этом ответе гораздо проще, не говоря об этом аспекте проблемы, хотя это необходимо учитывать для создания функционального приложения музыкального плеера.

Необходимо также предусмотреть, когда устройство заблокировано, чтобы некоторые аппаратные устройства не отключались. Попробуйте учесть следующее в ответ на событие PLAY в onStartCommand службы, чтобы учесть это:

        // Setup Wake Mode Wake Lock so the music can play while device screen is locked
        mediaPlayer.setWakeMode(getApplicationContext(), PowerManager.FULL_WAKE_LOCK);
        // Setup wifi lock so wifi can stay on while device is locked and trying to save power
        wifiLock = ((WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE))
                .createWifiLock(WifiManager.WIFI_MODE_FULL, "mylock");
        wifiLock.acquire();

Другая проблема заключается в том, что ваш пользователь в идеале сможет убить службу, если она запущена. Если они убьют приложение, оно не убьет службу, как предполагалось, и музыка продолжит играть. Таким образом, пользователь должен иметь возможность контролировать службу с помощью уведомлений с элементами управления для приостановки и воспроизведения музыки. Это можно сделать с помощью службы переднего плана. Если вы хотите добавить слой обслуживания переднего плана, вы можете добавить вызов startForeground () в onStartCommand () службы в ответ на событие широковещания для PLAY. Вот урезанное onStartCommand () с добавленной логикой переднего плана:

public int onStartCommand(Intent intent, int flags, int startId) {

    if (intent.getAction().equals(ACTION_PLAY)) {
        ...
        Notification notification = setupNotification(); // where setupNotification is your own function
        startForeground(1, notification);
        return START_STICKY_COMPATIBILITY;
    } else { // i.e. action is ACTION_PAUSE
        ...
        stopForeground(false);

        // NotificationManagerCompat needed here for swipeable notification b/c service will be killed
        Notification notification = setupNotification();
        NotificationManagerCompat nmc = NotificationManagerCompat.from(this);
        nmc.notify(1, notification);
        return START_NOT_STICKY;
    }
}

Функции startForeground () принимают идентификатор и объект уведомления в качестве своих параметров. Уведомление может быть создано с помощью NotificationCompat.Builder с кодом, который выглядит примерно так (отмечая, что некоторые переменные здесь должны быть вставлены в соответствующее приложение):

Bitmap icon = BitmapFactory.decodeResource(getResources(),
        R.drawable.ic_launcher_round_large);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
        .setContentTitle(getString(R.string.app_name))
        .setContentText("Music is now playing") // change to paused on paused
        .setTicker("Music Playing")
        .setSmallIcon(R.drawable.status_bar_icon_xhdpi_48px)
        .setLargeIcon(Bitmap.createScaledBitmap(icon, 128, 128, false))
        .setContentIntent(pendingTapIntent)
        .setDeleteIntent(pendingSwipeIntent)
        .addAction(iconId, buttonText, pendingButtonIntent)
        .setWhen(System.currentTimeMillis());

Обратите внимание на ожидающие намерения в коде выше. Они создаются с помощью класса PendingIntent.То есть создать ожидающее намерение для кнопки воспроизведения в уведомлении, например, так (где «this» - это фоновая служба, если вы создаете это намерение из фоновой службы)

 Intent playIntent = new Intent(this, MyService.class);
            playIntent.setAction(ACTION_PLAY);
            PendingIntent pendingPlayIntent = PendingIntent.getService(this, 0, playIntent, 0);

Аналогично, создайте ожидающее намерение, когда пользователь нажимает на уведомление, чтобы оно открывало приложение со следующим кодом (опять же, где «this» - это фоновая служба, если вы создаете это намерение из фоновой службы). ):

Intent notificationIntent = new Intent(this, StreamActivity.class);
        notificationIntent.setAction("ACTION_MAIN");
        notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

Кроме того, создайте ожидающее намерение для действия смахивания в уведомлении, чтобы убить фоновую службу, подобную этой (опять же, где «this» - фоновая служба, если вы создаете эту цель из фоновой службы):

Intent swipeIntent = new Intent(this, MyService.class);
swipeIntent.setAction(ACTION_END_SERVICE);
PendingIntent pendingSwipeIntent = PendingIntent.getService(this, 0, swipeIntent, 0);

Надеюсь, этого достаточно, чтобы начать, но я бы порекомендовал начать этот процесс без сложного уровня активности на переднем плане. Затем добавьте его, как только увидите, что воспроизведение музыки из приложения работает.

0 голосов
/ 29 июня 2018

Если вы хотите, чтобы музыка воспроизводилась даже после выхода пользователя из приложения, для этого вам нужно использовать службу переднего плана. Все музыкальные проигрыватели используют этот подход.

Если вы хотите, чтобы музыка заканчивалась, когда у пользователя есть перикулярная активность, только в этом случае будет рассматриваться что-то, кроме службы.

Асинхронная задача не должна использоваться для этой цели, поскольку она идеально подходит для небольших фоновых задач. Воспроизведение музыки не в этой категории.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...