2012-05-06 11 views
9

Estoy haciendo una aplicación para Android. Estoy haciendo un servicio que se ejecuta en segundo plano todo el tiempo cuando el usuario comprueba un checkbox y debe detenerse cuando el usuario lo unckeck. Así que funciona cuando marque la casilla y también muestra "Inicio de servicio" Toast, pero cuando hago uncheck el checkbox, muestra el Toast que dice "Servicio detenido", pero no detiene el sonido que comenzó cuando se inició el servicio. . La única manera de detener ese sonido es apagar mi móvil y luego encenderlo.Servicio se ha filtrado IntentReceiver en android

Aquí está mi código java para iniciar y detener el servicio

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(); 
} 

Aquí está mi archivo xml

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

y aquí está mi 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... ! 

Ayuda por favor. ¿Dónde estoy cometiendo un error?

Editar

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

En mi teléfono, los sonidos reproducidos continuarán reproduciéndose incluso después de que la aplicación se cierre por completo. Tal vez es solo una cosa de Android. ¿Has intentado detener el sonido del servicio? – Hassan

+0

Hassan No entiendo tu punto "¿Has intentado detener el sonido del servicio?" ¿Podrías por favor elaborar un poco? – 2619

+0

Es decir, en el código que realmente reproduce el sonido, ¿cómo pausar/detener el sonido? ¿Pausa/paras? – Hassan

Respuesta

6

Asegúrese de llamar antes de las unregisterReceiveronDestroy acabados. Después de onDestroy, el contexto del Servicio no es válido, por lo que todos los receptores de intención registrados dejarán de funcionar. Android te advierte con la excepción "Receptor de intención filtrada" que tu aplicación se está portando mal.

La música no se detiene porque el receptor no se llama más. Debe asegurarse de que se llama a mMediaPlayer.stop antes de la devolución de onDestroy. Le sugiero que extraiga toda esta funcionalidad en métodos separados, por lo que será mucho más fácil componer su aplicación.

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

Además, tenga cuidado para no escaparse del mMusicPlayer si debido a un error que recibe dos enchufado == 2 intentos consecutivos. Siempre es mejor escribir su código de una manera defensiva, en lugar de confiar en el conocimiento adicional del invocador.

El manejo de excepciones también es bastante peligroso en su código. Si el inicio de la música falló, puede ocurrir que obtenga una excepción de puntero nulo cuando quiera detener la música.

Espero que esto ayude.

+0

Gracias allprog.Esto ayuda y proporcionó buena información. Como soy nuevo en Android, es por eso que mi código no es como profesionales. ¿Podría decirme dónde y cómo en mi código puedo anular el registro de mi receptor? – 2619

+0

Utilicé este "this.unregisterReceiver (this.batteryInfoReceiver);" en el método onDestroy() pero no funciona. – 2619

+0

Diría que esta es la peor parte de Android. Las API que necesita usar aquí son muy ambiguas y debe comprender el funcionamiento interno de Services y BroadcastReceivers para ver cómo se debe hacer. ¿Ha intentado poner la llamada anularRecibir registro antes de super.onDestroy()? ¿Qué error obtienes? – allprog

1

Tal vez se ha perdido la anotación @ Override

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

Puede ser un poco tarde, pero parece que hay que llamar unregisterReceiver() justo antes de que el método OnDestroy() se llama. Esto resolvió mi problema.

Cuestiones relacionadas