2015-08-29 8 views
1

Я разрабатываю виджет, который воспроизводит случайный звук. Моя проблема заключается в том, чтобы использовать сервис, который я использую для обработки MediaPlayer, и воспроизводить звуки для загрузки звуковых файлов, которые я сохранил в папке с активами моего приложения.
Вместо SoundPool, как в моем приложении, я выбрал MediaPlayer, так как он имеет onCompletionListener, который позволяет мне остановить службу после того, как звук был полностью воспроизведен. Таким образом, я надеюсь минимизировать использование ресурсов виджета.Загрузить файлы с данными в фоновом режиме

Точнее, в моем коде (checkout the [now outdated] commit on GitHub) Я пытаюсь загрузить случайный звук с помощью метода MediaPlayercreate()using an Uri to file:///android_asset/pathToFile.
Это, однако, генерирует исключение IOException во время выполнения.

@Override 
public int onStartCommand(Intent intent, int flags, int startId) { 
    if (intent != null) { 
     final String action = intent.getAction(); 
     if (ACTION_PLAY_FART.equals(action)) { 
      Log.v(LOG_TAG, "Intent received"); 

      String pathToFile = String.format(
        Locale.US, 
        "fart%02d.ogg", 
        Utility.getIntBetween(1, 15) 
      ); 
      MediaPlayer tempMediaPlayer = MediaPlayer.create(
        this, 
        Uri.parse("file:///android_asset/"+pathToFile) 
      ); 
      tempMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { 
       @Override 
       public void onCompletion(MediaPlayer mp) { 
        mp.release(); 
        stopSelf(); 
       } 
      }); 
      Log.v(LOG_TAG, "Start playing"); 
      tempMediaPlayer.start(); 
     } 
    } 

    return START_NOT_STICKY; 
} 

Есть простой способ (я. Е., Кроме Content Provider) для нагрузки эти файлы активов из внутриService?


[редактировать, предоставляя больше информации]

По-видимому, можно получить доступ к файлам активов, но MediaPlayer не может загрузить их должным образом.

Я изменил код для этого:

@Override 
public int onStartCommand(Intent intent, int flags, int startId) { 
    if (intent != null) { 
     final String action = intent.getAction(); 
     if (ACTION_PLAY_FART.equals(action)) { 
      Log.v(LOG_TAG, "Intent received"); 

      String pathToFile = String.format(
        Locale.US, 
        "fart%02d.ogg", 
        Utility.getIntBetween(1, 15) 
      ); 
      try { 
       AssetFileDescriptor assetFD = this.getAssets().openFd(pathToFile); 

       MediaPlayer tempMediaPlayer = new MediaPlayer(); 
       tempMediaPlayer.setDataSource(assetFD.getFileDescriptor()); 
       tempMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { 
        @Override 
        public void onCompletion(MediaPlayer mp) { 
         mp.release(); 
         stopSelf(); 
        } 
       }); 
       Log.v(LOG_TAG, "Start playing"); 
       tempMediaPlayer.start(); 
      } catch (IOException e) { 
       Log.e(LOG_TAG, "File "+pathToFile+" could not be loaded.", e); 
      } 
     } 
    } 

Выход я получаю:

08-29 15:29:54.868 10191-10191/com.y0hy0h.furzknopf V/VolatileFartService﹕ Intent received 
08-29 15:29:54.868 10191-10191/com.y0hy0h.furzknopf V/MediaPlayer﹕ constructor 
08-29 15:29:54.868 10191-10191/com.y0hy0h.furzknopf V/MediaPlayer﹕ setListener 
08-29 15:29:54.868 10191-10191/com.y0hy0h.furzknopf V/MediaPlayer﹕ setDataSource(51, 0, 576460752303423487) 
08-29 15:29:54.898 10191-10191/com.y0hy0h.furzknopf E/MediaPlayer﹕ Unable to to create media player 
08-29 15:29:54.908 10191-10191/com.y0hy0h.furzknopf E/VolatileFartService﹕ File fart07.ogg could not be loaded. 
    java.io.IOException: setDataSourceFD failed.: status=0x80000000 
      at android.media.MediaPlayer.setDataSource(Native Method) 
      at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1032) 
      at com.y0hy0h.furzknopf.widget.VolatileFartService.onStartCommand(VolatileFartService.java:39) 
      at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2524) 
      at android.app.ActivityThread.access$1900(ActivityThread.java:138) 
      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1302) 
      at android.os.Handler.dispatchMessage(Handler.java:99) 
      at android.os.Looper.loop(Looper.java:137) 
      at android.app.ActivityThread.main(ActivityThread.java:4929) 
      at java.lang.reflect.Method.invokeNative(Native Method) 
      at java.lang.reflect.Method.invoke(Method.java:511) 
      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:798) 
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:565) 
      at dalvik.system.NativeStart.main(Native Method) 

Обратите внимание, что линии 39 является

tempMediaPlayer.setDataSource(assetFD.getFileDescriptor()); 

Alternitavely, есть путь к p ass FileDescriptor или другой объект для загрузки службы?

Возможно, существует еще один способ для обработки воспроизведения, возможно, нескольких звуков одновременно, чем для добавления этой функции в Service?

+0

Вы можете загрузить файл из папки Assets в службе, но, прежде чем предлагать ответ, Пожалуйста, включите ваши коды, чтобы люди могли легко помочь, а не предполагая, что вы можете или не можете понадобиться , – Want2bExpert

+0

Я добавил фрагмент кода. Для большей части кода я включил ссылки на мой репозиторий GitHub. Это плохой способ предоставить код, должен ли я включать больше кода прямо в Stackoverflow? – J0hj0h

+0

Вы пробовали AssetManager asset = Context.get assets(); asset.open ("имя_файла") ;? – Want2bExpert

ответ

0

В качестве альтернативы Want2bExpert's suggestion перемещения файлов в RES/сырую папку, файлы активы могут быть загружены «вручную» в MediaPlayer.


По-видимому, активы not stored as would be expected. Вместо этого стартовая позиция и длина актива вместе с его (, но неAsset -) FileDescriptor должны быть переданы на MediaPlayer.

Рабочий код:

String pathToFile = String.format(
     Locale.US, 
     "fart%02d.ogg", 
     Utility.getIntBetween(1, 15) 
); 

try { 
    AssetFileDescriptor assetFD = getAssets().openFd(pathToFile); 
    MediaPlayer tempMediaPlayer = new MediaPlayer(); 
    tempMediaPlayer.setDataSource(
      assetFD.getFileDescriptor(), 
      assetFD.getStartOffset(), 
      assetFD.getLength() 
    ); 
    assetFD.close(); 
    tempMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { 
     @Override 
     public void onCompletion(MediaPlayer mp) { 
      mp.release(); 
      stopSelf(); 
     } 
    }); 
    tempMediaPlayer.prepare(); 
    Log.v(LOG_TAG, "Start playing"); 
    tempMediaPlayer.start(); 
} catch (IOException e) { 
    Log.e(LOG_TAG, "File "+pathToFile+" could not be loaded.", e); 
} 
0

Попробуйте это;

  • Создайте необработанную папку внутри вашего ресурса, например. Рез/сырье
  • поместить файлы играть в необработанной папке
  • загрузки файл с помощью мультимедийного проигрывателя, как показано ниже

    MediaPlayer MediaPlayer = MediaPlayer.create (serviceClass.this, R.raw.sound_file_1); медиаплеер.Начало();

Дополнительная информация; http://developer.android.com/guide/topics/media/mediaplayer.html#mpandservices

+0

Откуда я могу передать 'context' для' create() '? – J0hj0h

+0

Вы пытались объявить глобальную переменную Context в сервисе? Я не помню, чтобы делать это раньше, но попробуй. Например. в вашем классе сервиса Контекстный контекст = это; – Want2bExpert

+0

Единственное место, предоставляемое службой «Контекст», находится в статическом методе 'createIntentPlayFart()'. Я не могу установить переменную-член. Кроме того, я обновил свой вопрос, так как ваше предложение помогло мне решить проблему. – J0hj0h

Смежные вопросы