2012-05-06 14 views
9

Sto creando un'app per Android. Sto facendo un servizio che viene eseguito in background tutto il tempo in cui l'utente controlla un checkbox e dovrebbe fermarsi quando l'utente unckeck esso. Quindi funziona quando seleziono la casella e mostra anche "Avvio servizio" Toast ma quando I uncheck il checkbox mostra il Toast che dice "Servizio fermo" ma non smette di riprodurre il suono che è iniziato quando il servizio è stato avviato . L'unico modo per fermare quel suono è spegnere il mio cellulare e poi accenderlo.Il servizio è trapelato IntentReceiver in Android

Ecco il mio codice java per avviare e arrestare il servizio

public int onStartCommand(Intent intent, int flags, int startId) { 
    Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show(); 

    this.registerReceiver(this.batteryInfoReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); 

    return START_STICKY; 
} 
public void onDestroy() { 
    super.onDestroy(); 
    Toast.makeText(this, "Service Stopped", Toast.LENGTH_LONG).show(); 
} 

Ecco il mio file xml

<CheckBoxPreference 
    android:title="Enable/Disable Alarm" 
    android:defaultValue="true" 
    android:key="cbAlarm" 
    android:summary="Enable or disable alarm" /> 

ed è il mio logcat

05-06 09:13:53.230: D/dalvikvm(5351): GC_EXTERNAL_ALLOC freed 39K, 50% free 2725K/5379K, external 0K/0K, paused 124ms 
05-06 09:13:53.355: D/dalvikvm(5351): GC_EXTERNAL_ALLOC freed 21K, 49% free 2779K/5379K, external 504K/518K, paused 18ms 
05-06 09:13:53.420: D/CLIPBOARD(5351): Hide Clipboard dialog at Starting input: finished by someone else... ! 
05-06 09:13:57.975: I/MediaPlayer(5351): uri is:content://media/internal/audio/media/44 
05-06 09:13:57.975: I/MediaPlayer(5351): inside getAudioFilePath: content://media/internal/audio/media/44 
05-06 09:13:57.980: I/MediaPlayer(5351): The actual path is:/system/media/audio/ringtones/S_A_cricket_chirps.ogg 
05-06 09:13:57.980: I/MediaPlayer(5351): path is: /system/media/audio/ringtones/S_A_cricket_chirps.ogg 
05-06 09:13:57.980: I/MediaPlayer(5351): file path found for DRM file:path is: /system/media/audio/ringtones/S_A_cricket_chirps.ogg 
05-06 09:13:57.980: E/MediaPlayer-JNI(5351): setDataSource: outside path in JNI is [email protected] 
05-06 09:14:20.525: E/ActivityThread(5351): Service com.zafar.test.BatteryService has leaked IntentReceiver [email protected] that was originally registered here. Are you missing a call to unregisterReceiver()? 
05-06 09:14:20.525: E/ActivityThread(5351): android.app.IntentReceiverLeaked: Service com.zafar.test.BatteryService has leaked IntentReceiver [email protected] that was originally registered here. Are you missing a call to unregisterReceiver()? 
05-06 09:14:20.525: E/ActivityThread(5351):  at android.app.LoadedApk$ReceiverDispatcher.<init>(LoadedApk.java:756) 
05-06 09:14:20.525: E/ActivityThread(5351):  at android.app.LoadedApk.getReceiverDispatcher(LoadedApk.java:551) 
05-06 09:14:20.525: E/ActivityThread(5351):  at android.app.ContextImpl.registerReceiverInternal(ContextImpl.java:866) 
05-06 09:14:20.525: E/ActivityThread(5351):  at android.app.ContextImpl.registerReceiver(ContextImpl.java:853) 
05-06 09:14:20.525: E/ActivityThread(5351):  at android.app.ContextImpl.registerReceiver(ContextImpl.java:847) 
05-06 09:14:20.525: E/ActivityThread(5351):  at android.content.ContextWrapper.registerReceiver(ContextWrapper.java:318) 
05-06 09:14:20.525: E/ActivityThread(5351):  at com.zafar.test.BatteryService.onStartCommand(BatteryService.java:35) 
05-06 09:14:20.525: E/ActivityThread(5351):  at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2043) 
05-06 09:14:20.525: E/ActivityThread(5351):  at android.app.ActivityThread.access$2800(ActivityThread.java:117) 
05-06 09:14:20.525: E/ActivityThread(5351):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:998) 
05-06 09:14:20.525: E/ActivityThread(5351):  at android.os.Handler.dispatchMessage(Handler.java:99) 
05-06 09:14:20.525: E/ActivityThread(5351):  at android.os.Looper.loop(Looper.java:130) 
05-06 09:14:20.525: E/ActivityThread(5351):  at android.app.ActivityThread.main(ActivityThread.java:3691) 
05-06 09:14:20.525: E/ActivityThread(5351):  at java.lang.reflect.Method.invokeNative(Native Method) 
05-06 09:14:20.525: E/ActivityThread(5351):  at java.lang.reflect.Method.invoke(Method.java:507) 
05-06 09:14:20.525: E/ActivityThread(5351):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:907) 
05-06 09:14:20.525: E/ActivityThread(5351):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:665) 
05-06 09:14:20.525: E/ActivityThread(5351):  at dalvik.system.NativeStart.main(Native Method) 
05-06 09:14:37.810: D/CLIPBOARD(5351): Hide Clipboard dialog at Starting input: finished by someone else... ! 

Aiuto qui per favore. Dove sto sbagliando.

Modifica

private BroadcastReceiver batteryInfoReceiver = new BroadcastReceiver() { 
    @Override 
    public void onReceive(Context context, Intent intent) { 
     int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0); 
     int plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0); 

     if(plugged == 2) { 

       SharedPreferences getAlarms = PreferenceManager.getDefaultSharedPreferences(getBaseContext()); 
       String alarms = getAlarms.getString("ringtone", "default ringtone"); 
       //getting uri from MediaStore via filepath i.e. content://media/internal/audio/media/29 
       Uri uri = Uri.parse(alarms); 

       mMediaPlayer = new MediaPlayer(); 
       try { 
        mMediaPlayer.setDataSource(context, uri); 
        final AudioManager audioManager = (AudioManager) context 
          .getSystemService(Context.AUDIO_SERVICE); 
        if (audioManager.getStreamVolume(AudioManager.STREAM_ALARM) != 0) { 
         mMediaPlayer.setAudioStreamType(AudioManager.STREAM_ALARM); 
         mMediaPlayer.prepare(); 
         mMediaPlayer.start(); 
        } 
       } catch (IOException e) { 
        //System.out.println("OOPS"); 
        e.getStackTrace(); 
       } 
     } else if(plugged == 0) { 
      mMediaPlayer.stop(); 
     } 

    } 
}; 
+1

Sul mio telefono, i suoni riprodotti continueranno a suonare anche dopo che l'applicazione si sarà completamente chiusa. Forse è solo una cosa di Android. Hai provato a fermare l'audio dal servizio? – Hassan

+0

Hassan Non ho capito il tuo punto "Hai provato a fermare l'audio dal servizio?" Potresti per favore elaborare un po '? – 2619

+0

Voglio dire, nel codice che riproduce effettivamente il suono, come sospendi/interrompi il suono? Ti fermi/fermalo? – Hassan

risposta

6

Assicurati di chiamare unregisterReceiver prima dei onDestroy finiture. Dopo il onDestroy il contesto del servizio non è valido, quindi tutti i ricevitori di intenzioni registrati smetteranno di funzionare. Android ti avvisa con l'eccezione "Ricevente intento trapelato" che la tua app non funziona correttamente.

La musica non si ferma perché il ricevitore non viene più chiamato. Dovresti assicurarti che mMediaPlayer.stop venga chiamato prima del ritorno da onDestroy. Ti suggerisco di estrarre tutte queste funzionalità in metodi separati, quindi sarà molto più facile comporre la tua applicazione.

private void startMusic(int level); 
private void stopMusic(); 

Inoltre, fare attenzione a non perdere il mMusicPlayer se a causa di errore si riceve due collegati i == 2 intenti di fila. È sempre meglio scrivere il tuo codice in modo difensivo, piuttosto che affidarsi alla conoscenza aggiuntiva del richiedente.

La gestione delle eccezioni è anche piuttosto pericolosa nel codice. Se l'avvio della musica fallisce, può accadere che tu ottenga un'eccezione del puntatore nullo quando vuoi interrompere la musica.

Spero che questo aiuti.

+0

Grazie allprog.Questo aiuta e hai fornito buone informazioni. Dal momento che sono nuovo di Android questo è il motivo per cui il mio codice non è come i professionisti. Potresti dirmi dove e in che modo nel mio codice posso annullare la registrazione del mio ricevitore? – 2619

+0

Ho usato questo "this.unregisterReceiver (this.batteryInfoReceiver);" nel metodo onDestroy() ma non funziona. – 2619

+0

Direi che questa è la parte peggiore di Android. Le API che devi usare qui sono molto ambigue e devi capire il funzionamento interno di Services e BroadcastReceiver per vedere come dovrebbe essere fatto. Hai provato a mettere la chiamata unregisterReceiver prima di super.onDestroy()? Che errore ottieni? – allprog

1

Forse vi siete persi l'annotazione @Override

@Override 
public void onDestroy() { 
    unregisterReceiver(batteryInfoReceiver); 
    super.onDestroy(); 
} 
0

Potrebbe essere un po 'in ritardo, ma sembra si deve chiamare unregisterReceiver() a destra prima il metodo OnDestroy() viene chiamato. Questo ha risolto il mio problema.

Problemi correlati