Intereting Posts
Ошибка аннотаций Android с Android Studio Update 1.0 ORMLite сбросить все таблицы Речь в текст из собственного звукового файла Отключить один ключ на пользовательской клавиатуре на Android Как увеличить максимальный размер кучи виртуального устройства Android? Невозможно понизить базу данных с версии `n` до` n-1` на Samsung Пользовательский контроль яркости / цвета края для ListView? Как я могу ограничить показ в галерее Android только одним элементом для броска? Измените сгенерированное имя apk из "app-debug.apk" Android Как эмулировать поведение @android: id / empty в GridView? Как я могу продавать свои Android-приложения в стране, которая официально не поддерживается торговцами Android-Market? Одна игра C #, чтобы управлять ими всеми (iOS, Android, WP7, W7, Mac OS X и XBOX) Больше не требуется ActivityManager – не проблема службы Вызвать методы или функции класса C ++ из Java на андроид без повторного создания класса / переменной при каждом вызове Добавление базы данных / backend в приложения для Android

Android всеобъемлющей отказоустойчивой музыкальной службы на нескольких мероприятиях

Я знаю, что этот вопрос задавался много раз раньше и может показаться конгломератом нескольких вопросов, но я считаю, что это важно и важно для многих разработчиков; Мне нужно создать Service фоновой музыки, которая может работать во многих действиях для моей игры Android, которая заканчивается, когда приложение прекращается и приостанавливается во всех следующих случаях:

  1. Запускается определенная Activity которая имеет свою собственную музыку. (Возобновление, когда эта AndEngine завершается. Это происходит как действие AndEngine .)
  2. Нажимается домашний экран, а приложение зашифровывается, или приложение завершается. Возвращает, когда приложение возвращается на передний план. Требуется использование onUserLeaveHint() . Еще одна полезная ссылка.
  3. Телефон получает вызов и прерывает приложение. Возобновляется, когда вызов был обработан. Требуется использование TelephonyManager аналогичное этому .
  4. Экран заблокирован. (Повторное использование после того, как экран был разблокирован.) Требуется использование ACTION_USER_PRESENT , что кажется очень проблематичным .
  5. В основном музыка приостанавливается всякий раз, когда приложение не отображается или когда пользователю показан специальный вид активности # 1.

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

Мне любопытно, что AndEngine имеет ни одной из этих проблем с их музыкой, поэтому, возможно, поиск в исходном коде поможет кому-то найти ответ. Я использую последнюю функциональную версию GLES1 из Google Code .

Я также рассмотрел следующие ссылки на создание хорошей музыкальной Service :

  • Остановка фоновой музыки
  • http://www.codeproject.com/Articles/258176/Adding-Background-Music-to-Android-App
  • Служба фоновой музыки Android
  • Воспроизведение музыки BG через работу в Android
  • http://www.rbgrn.net/content/307-light-racer-20-days-61-64-completion

Я хотел бы, чтобы Service решений:

  • Минимизируйте использование BroadcastReceivers и дополнений / разрешений Android Manifest, если возможно
  • Самостоятельная проверка и проверка ошибок

Другие примечания

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

Спасибо всем заблаговременно! Удачи!

Изменить – вот фрагменты кода, не стесняйтесь улучшать или игнорировать:

Проигрыватель Media Player

 import android.content.SharedPreferences; import android.media.MediaPlayer; import android.preference.PreferenceManager; import android.util.Log; public class CarefulMediaPlayer { final SharedPreferences sp; final MediaPlayer mp; private boolean isPlaying = false; public CarefulMediaPlayer(final MediaPlayer mp, final MusicService ms) { sp = PreferenceManager.getDefaultSharedPreferences(ms.getApplicationContext()); this.mp = mp; } public void start() { if (sp.getBoolean("com.embed.candy.music", true) && !isPlaying) { mp.start(); isPlaying = true; } } public void pause() { if (isPlaying) { mp.pause(); isPlaying = false; } } public void stop() { isPlaying = false; try { mp.stop(); mp.release(); } catch (final Exception e) {} } } 

Музыкальный сервис

 import android.app.Service; import android.content.Intent; import android.media.MediaPlayer; import android.os.IBinder; public class MusicService extends Service { static CarefulMediaPlayer mPlayer = null; @Override public IBinder onBind(final Intent arg0) { return null; } @Override public void onCreate() { super.onCreate(); final MediaPlayer mp = MediaPlayer.create(this, R.raw.title_music); mp.setLooping(true); mPlayer = new CarefulMediaPlayer(mp,this); } @Override public int onStartCommand(final Intent intent, final int flags, final int startId) { mPlayer.start(); return 1; } @Override public void onStart(final Intent intent, final int startId) { } public IBinder onUnBind(final Intent arg0) { return null; } public static void onStop() { mPlayer.stop(); } public static void onPause() { if (mPlayer!=null) { mPlayer.pause(); } } public static void onResume() { if (mPlayer!=null) { mPlayer.start(); } } @Override public void onDestroy() { mPlayer.stop(); mPlayer = null; } @Override public void onLowMemory() { } } 

Улучшенный класс базовой активности

 import android.app.Activity; import android.content.Intent; import android.os.PowerManager; import android.telephony.TelephonyManager; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; import android.widget.ImageView; public abstract class BetterActivity extends Activity { private boolean isHome = true; @Override protected void onResume() { System.gc(); super.onResume(); MusicService.onResume(); isHome = true; } @Override protected void onPause() { if (((TelephonyManager)getSystemService(TELEPHONY_SERVICE)).getCallState()==TelephonyManager.CALL_STATE_RINGING || !((PowerManager)getSystemService(POWER_SERVICE)).isScreenOn()) { MusicService.onPause(); } super.onPause(); System.gc(); } @Override public boolean onKeyDown (final int keyCode, final KeyEvent ke) { switch (keyCode) { case KeyEvent.KEYCODE_BACK: isHome = false; default: return super.onKeyDown(keyCode, ke); } } @Override public void startActivity(final Intent i) { isHome = false; super.startActivity(i); } @Override protected void onUserLeaveHint() { if (isHome) { MusicService.onPause(); } super.onUserLeaveHint(); } } 

Solutions Collecting From Web of "Android всеобъемлющей отказоустойчивой музыкальной службы на нескольких мероприятиях"

Сначала вот какой-то код. Ниже я дам вам объяснение.

 public class MusicService extends Service { // service binder private final IBinder mBinder = new LocalBinder(); // music player controling game music private static CarefulMediaPlayer mPlayer = null; @Override public void onCreate() { // load music file and create player MediaPlayer mediaPlayer = MediaPlayer.create(this, R.raw.title_music); mediaPlayer.setLooping(true); mPlayer = new CarefulMediaPlayer(mediaPlayer, this); } @Override public void onDestroy() { super.onDestroy(); } // ========================= // Player methods // ========================= public void musicStart() { mPlayer.start(); } public void musicStop() { mPlayer.stop(); } public void musicPause() { mPlayer.pause(); } /** * Class for clients to access. Because we know this service always runs in * the same process as its clients, we don't need to deal with IPC. */ public class LocalBinder extends Binder { MusicService getService() { return MusicService.this; } } @Override public IBinder onBind(Intent arg0) { return mBinder; } } 

Мероприятия:

 public class StartupActivity extends Activity { // bounded service private static MusicService mBoundService; // whetere service is bounded or not private boolean mIsBound; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_startup); doBindService(); // HOW TO WORK WITH THE SERVICE: // call the following methods whenever // you want to interact with you // music player // =================================== // call this eg in onPause() of your Activities StartupActivity.getService().musicPause(); // call this eg in onStop() of your Activities StartupActivity.getService().musicStop(); // call this eg in onResume() of your Activities StartupActivity.getService().musicStart(); } @Override public void onDestroy() { super.onDestroy(); doUnbindService(); } private final ServiceConnection mServiceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName className, IBinder service) { setService(((MusicService.LocalBinder) service).getService()); } @Override public void onServiceDisconnected(ComponentName className) { setService(null); } }; private void doBindService() { Intent service = new Intent(getBaseContext(), MusicService.class); // start service and bound it startService(service); bindService(new Intent(this, MusicService.class), mServiceConnection, Context.BIND_AUTO_CREATE); mIsBound = true; } private void doUnbindService() { if (mIsBound) { // Detach existing connection. unbindService(mServiceConnection); mIsBound = false; } } public static MusicService getService() { return mBoundService; } private static void setService(MusicService mBoundService) { StartupActivity.mBoundService = mBoundService; } } 

Прежде всего, вы получили услугу, которая работает в фоновом режиме. Эта служба создает объект mediaPlayer, как и вы. С помощью localBinder вы можете связать службу в своей деятельности (-ях) и получить доступ к ней, как обычный Java-объект. Активность, которую я опубликовал, привязывает службу. В методе onCreate () вы можете найти способ взаимодействия с медиаплеер. Вы можете привязать любое действие к своей службе.

Другое решение:

 public class CarefulMediaPlayer { final SharedPreferences sp; final MediaPlayer mp; private boolean isPlaying = false; private static CarefulMediaPlayer instance; public CarefulMediaPlayer(final MediaPlayer mp, final MusicService ms) { sp = PreferenceManager.getDefaultSharedPreferences(ms.getApplicationContext()); this.mp = mp; instance = this; } public static CarefulMediaPlayer getInstance() { return instance; } public void start() { if (sp.getBoolean("com.embed.candy.music", true) && !isPlaying) { mp.start(); isPlaying = true; } } public void pause() { if (isPlaying) { mp.pause(); isPlaying = false; } } public void stop() { isPlaying = false; try { mp.stop(); mp.release(); } catch (final Exception e) {} } } 

Затем вы можете приостановить, воспроизвести и остановить музыку, вызвав CarefulMediaPlayer.getInstance (). Play ();

Я сделал это так, и я доволен результатом:

1-й создать сервис:

 public class LocalService extends Service { // This is the object that receives interactions from clients. See RemoteService for a more complete example. private final IBinder mBinder = new LocalBinder(); private MediaPlayer player; /** * Class for clients to access. Because we know this service always runs in * the same process as its clients, we don't need to deal with IPC. */ public class LocalBinder extends Binder { LocalService getService() { return LocalService.this; } } @Override public void onCreate() { } @Override public int onStartCommand(Intent intent, int flags, int startId) { // We want this service to continue running until it is explicitly stopped, so return sticky. return START_STICKY; } @Override public void onDestroy() { destroy(); } @Override public IBinder onBind(Intent intent) { return mBinder; } public void play(int res) { try { player = MediaPlayer.create(this, res); player.setLooping(true); player.setVolume(0.1f, 0.1f); player.start(); } catch(Exception e) { e.printStackTrace(); } } public void pause() { if(null != player && player.isPlaying()) { player.pause(); player.seekTo(0); } } public void resume() { try { if(null != player && !player.isPlaying()) { player.start(); } } catch(Exception e) { e.printStackTrace(); } } public void destroy() { if(null != player) { if(player.isPlaying()) { player.stop(); } player.release(); player = null; } } } 

2-й , создайте базовую активность и расширьте все свои действия в том, что вы хотите воспроизвести фоновую музыку от нее:

 public class ActivityBase extends Activity { private Context context = ActivityBase.this; private final int [] background_sound = { R.raw.azilum_2, R.raw.bg_sound_5 }; private LocalService mBoundService; private boolean mIsBound = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); doBindService(); } @Override protected void onStart() { super.onStart(); try { if(null != mBoundService) { Random rand = new Random(); int what = background_sound[rand.nextInt(background_sound.length)]; mBoundService.play(what); } } catch(Exception e) { e.printStackTrace(); } } @Override protected void onStop() { super.onStop(); basePause(); } protected void baseResume() { try { if(null != mBoundService) { mBoundService.resume(); } } catch(Exception e) { e.printStackTrace(); } } protected void basePause() { try { if(null != mBoundService) { mBoundService.pause(); } } catch(Exception e) { e.printStackTrace(); } } private ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { // This is called when the connection with the service has been // established, giving us the service object we can use to // interact with the service. Because we have bound to a explicit // service that we know is running in our own process, we can // cast its IBinder to a concrete class and directly access it. mBoundService = ((LocalService.LocalBinder) service).getService(); if(null != mBoundService) { Random rand = new Random(); int what = background_sound[rand.nextInt(background_sound.length)]; mBoundService.play(what); } } public void onServiceDisconnected(ComponentName className) { // This is called when the connection with the service has been // unexpectedly disconnected -- that is, its process crashed. // Because it is running in our same process, we should never // see this happen. mBoundService = null; if(null != mBoundService) { mBoundService.destroy(); } } }; private void doBindService() { // Establish a connection with the service. We use an explicit // class name because we want a specific service implementation that // we know will be running in our own process (and thus won't be // supporting component replacement by other applications). Intent i = new Intent(getApplicationContext(), LocalService.class); bindService(i, mConnection, Context.BIND_AUTO_CREATE); mIsBound = true; } private void doUnbindService() { if (mIsBound) { // Detach our existing connection. unbindService(mConnection); mIsBound = false; } } @Override protected void onDestroy() { super.onDestroy(); doUnbindService(); } } 

И все, теперь у вас есть фоновый звук во всех действиях, которые расширены из ActivityBase.

Вы можете даже управлять функциональностью паузы / возобновления, вызывая basePause () / baseResume ().

Не забудьте объявить службу в манифесте:

 <service android:name="com.gga.screaming.speech.LocalService" /> 

В процессе запуска мы привязываемся и запускаем сервис отдельно. Это неправильно, так как служба будет продолжать работать после выхода активности, поскольку мы не вызывали stopService () в любом месте. Итак, часть «startService (service)» должна быть удалена, поскольку служба привязки уже « автоматически создает » службу.

Пожалуйста, поправьте меня, если кто-то получит противоположные результаты

 startService(service);// remove this part bindService(new Intent(this, MusicService.class), mServiceConnection, Context.BIND_AUTO_CREATE);