2013-09-07 2 views
1

Мне нужна фоновая музыка во всех моих действиях. Он должен остановиться, когда приложение не находится на переднем плане. Поскольку я разрабатываю для 2.3, я не могу использовать класс ActivityLifeCycleCallBacks. Я реализовал решение по адресу Checking if an Android application is running in the background, а затем решил сделать медиаплеер синглетом и использовать его в сервисе.Служба поддержки медиаплееров Android не прекратит играть

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

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

PlayAudio.java

import ... 
public class PlayAudio extends Service{ 
    private static final Intent Intent = null; 
    MediaPlayer objPlayer; 
    private int length = 0; 
    boolean mIsPlayerRelease = true; 
    private static PlayAudio uniqueIstance; //the singleton 
    static PlayAudio mService; 
    static boolean mBound = false; // boolean to check if the service containing this singleton is binded to some activity 
    public static boolean activityVisible; // boolean to check if the activity using the player is foreground or not 

//My attempt to make a singleton 
public static PlayAudio getUniqueIstance(){ 
    if (uniqueIstance == null) { 
     uniqueIstance = new PlayAudio(); 
    } 
    return uniqueIstance; 
} 
public static boolean isActivityVisible() { 
    return activityVisible; 
    } 

    public static void activityResumed() { 
    activityVisible = true; 
    } 

    public static void activityPaused() { 
    activityVisible = false; 
    } 
static public ServiceConnection mConnection = new ServiceConnection() {// helper for the activity 

    public void onServiceConnected(ComponentName className, 
      IBinder service) { 
     LocalBinder binder = (LocalBinder) service; 
     mService = binder.getService(); 
     mBound = true; 
    } 

    public void onServiceDisconnected(ComponentName arg0) { 
     mBound = false; 
    } 
}; 
public static Intent createIntent (Context context) { //helper for the activity using the player 
    Intent intent = new Intent(context, PlayAudio.class); 
    return intent; 
} 
private final IBinder mBinder = new LocalBinder(); 

public class LocalBinder extends Binder { 
    PlayAudio getService() { 
     // Return this instance so clients can call public methods 
     return PlayAudio.this; 
    } 
} 
@Override 
public IBinder onBind(Intent intent) { 
    return mBinder; 
} 
public void onCreate(){ 
    super.onCreate(); 
    Log.d(LOGCAT, "Service Started!"); 
    objPlayer = MediaPlayer.create(this,R.raw.kickstarterreduced); 
    objPlayer.setLooping(true); 
    mIsPlayerRelease = false; 
} 

public int onStartCommand(Intent intent, int flags, int startId){ 
    objPlayer.start(); 
    Log.d(LOGCAT, "Media Player started!"); 
    if(objPlayer.isLooping() != true){ 
     Log.d(LOGCAT, "Problem in Playing Audio"); 
    } 
    return 1; 
} 

public void onStop(){ 
    objPlayer.setLooping(false); 
    objPlayer.stop(); 
    objPlayer.release(); 
    mIsPlayerRelease = true; 
} 

public void onPause(){ 
    if(objPlayer.isPlaying()) 
    { 
     objPlayer.pause(); 
     length=objPlayer.getCurrentPosition(); // save the position in order to be able to resume from here 
    } 
} 
public void resumeMusic() // if length is 0 the player just start from zero 
{ if (mIsPlayerRelease == true) { 
    objPlayer = MediaPlayer.create(this,R.raw.kickstarterreduced); 
    mIsPlayerRelease = false; 
} 
    if(objPlayer.isPlaying()==false) 
    { 
     if (length != 0) objPlayer.seekTo(length); 
     objPlayer.start(); 
    } 
} 

} 

И это те методы, которые я внедрившие в классе каждого вида деятельности в

SharedPreferences sharedPrefs; 
PlayAudio playerIstanced; 
public static boolean activityVisible; 
@Override 
public void onStart() { 
    super.onStart(); 
    sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this); 
    } 
@Override 
public void onResume() { 
     super.onResume(); 
     playerIstanced= PlayAudio.getUniqueIstance(); //call singleton 
     bindService(PlayAudio.createIntent(this), playerIstanced.mConnection, Context.BIND_AUTO_CREATE); // create the service 
     if (sharedPrefs.getBoolean("sound", true) == true) {// if sound is enabled in option it will start the service 
      startService(PlayAudio.createIntent(this)); 
      playerIstanced.mService.activityResumed(); 
      if (playerIstanced.mBound == true) { 
      playerIstanced.mService.resumeMusic(); 
      } 
     } 

    } 
    @Override 
    public void onPause() { 
     super.onPause(); 
     playerIstanced.mService.activityPaused(); 
     final Handler handler = new Handler(); 
     handler.postDelayed(new Runnable() { 
     public void run() { 
      //If the phone lags when changing activity (between onPause() and the other activity onResume() the music won't stop. If after 500ms onResume() is not called it means the activity went background...Am I messing with service here? 
      if (playerIstanced.mService.isActivityVisible() != true) { 
       playerIstanced.mService.onPause(); 
      } 
     } 
     }, 500); 

} 
    @Override 
    public void onStop(){ 
     super.onStop(); 
     // Unbind from the service 
     if (playerIstanced.mService.mBound) { 
      playerIstanced.mService.mBound = false; 
      unbindService(playerIstanced.mService.mConnection); 

     } 
    } 



} 

ответ

2

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

Эта часть должна быть в КАЖДОЙ деятельности onPause:

public void onPause(){ 
    super.onPause(); 
     Context context = getApplicationContext(); 
       ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); 
       List<RunningTaskInfo> taskInfo = am.getRunningTasks(1); 
       if (!taskInfo.isEmpty()) { 
        ComponentName topActivity = taskInfo.get(0).topActivity; 
        if (!topActivity.getPackageName().equals(context.getPackageName())) { 
        StopPlayer(); 
        Toast.makeText(xYourClassNamex.this, "YOU LEFT YOUR APP. MUSIC STOP", Toast.LENGTH_SHORT).show(); 
        } 
       } 
     } 

Эта часть должно быть в onResume каждого вида деятельности в:

Воспроизведения музыка автоматически, когда пользователь резюме АРР,

Public void onResume() 
    { 
     super.onResume(); 
    StartPlayer(); 
    } 

Надеется, что это помогает !! Вы можете проверить my answer в соответствии с этой темой, возможно, это решит вашу проблему.

+0

Благодарим за решение. Я все еще не могу правильно понять, что делает ваш код, но он работает. Вместо StopPlayer() я решил приостановить его и остановить его только тогда, когда активность вызывает onStop() сама по себе. Если у вас есть несколько раз, вы бы потрудились объяснять по очереди ваше решение? Я попытался немного поработать, но я все еще потерян. – pinolo

+0

@ pinolo, здесь я ищу работу на фронте. Если на экране «Мои приложения» нет «Фронта», это означает, что пользователь остался в Моем приложении. Я могу получить это из ActivityManager. Это даст список Running Task. Я могу получить Front Activity из 'taskInfo.get (0) .topActivity'. то я просто сравниваю его с деятельностью моего приложения. Если это не соответствует, приложение закрывается. Надеюсь, ты получишь это! –

2

Вам необходимо вручную остановить службу, используя Context.stopService() или stopSelf(). См. Раздел Сервисный жизненный цикл раздел http://developer.android.com/reference/android/app/Service.html.

Service Lifecycle

Есть две причины, по которым услуга может быть запущена системой. Если кто-то вызывает Context.startService(), тогда система будет получать сервис (создавая его и вызывая его метод onCreate(), если это необходимо), а затем вызывает его метод onStartCommand (Intent, int, int) с аргументами, предоставленными клиентом. Служба в этот момент продолжит работу до вызова Context.stopService() или stopSelf(). Обратите внимание, что несколько вызовов Context.startService() не вложены (хотя они приводят к нескольким соответствующим вызовам onStartCommand()), поэтому независимо от того, сколько раз он запускается, служба будет остановлена ​​после Context.stopService() или stopSelf() называется; однако службы могут использовать метод stopSelf (int), чтобы гарантировать, что служба не будет остановлена ​​до тех пор, пока не будут обработаны начатые намерения.

Я считаю, что вы можете просто поместить playerIstanced.stopSelf() в вызов onStop() каждого действия.

Я понимаю, что служба продолжает работать тихо после того, как приложение прекратилось.Через некоторое время система убивает службу, чтобы освободить ресурсы, а затем через некоторое время, когда ресурсы доступны, она перезапускает сервис. Когда служба перезапускает свою onResume(), вызывается, и музыка начинает воспроизводиться.

+0

Я решил реализовать ваше решение и решение @geet. in onStop() Я реализовал if (mBound) { unbindService (mConnection); mBound = false; } – pinolo

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