2012-01-15 44 views
5

que tienen una tipo de actividad, en la que tengo una bandera estática, digamosAndroid volátil no funciona?

public static volatile flag = false; 

Luego, en la clase, iniciar un hilo, que comprueba la bandera y hacer cosas diferentes.

También tengo un receptor de difusión, que establece la bandera a verdadero o falso.

Pensé que volátil forzaría la bandera al valor más reciente. Pero puedo ver que mi receptor de difusión establece la bandera estática en verdadero, pero mi hilo todavía lo está obteniendo como falso.

¿Me falta algo básico aquí? ¡Cualquier ayuda sería apreciada!

Código simplificado (actualizado): por lo tanto, se supone que la bandera cambia a verdadera después de un minuto. Pero nunca lo hizo. Pero el mensaje del receptor de radiodifusión muestra se ha producido un cambio de verdad

TestappActivity.java:

package com.test; 

import java.util.Calendar; 

import android.app.Activity; 
import android.app.AlarmManager; 
import android.app.PendingIntent; 
import android.content.Intent; 
import android.os.Bundle; 

public class TestappActivity extends Activity { 
    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     Intent intent0 = new Intent(this, TestService.class); 
     this.startService(intent0); 

     Intent intent = new Intent(this, TestReceiver.class); 
     AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE); 
     PendingIntent sender = PendingIntent.getBroadcast(this, 
       1, intent, 
       PendingIntent.FLAG_UPDATE_CURRENT); 
     Calendar slot = Calendar.getInstance(); 
     int min = slot.get(Calendar.MINUTE); 
     slot.set(Calendar.MINUTE, min+1); 
     am.set(AlarmManager.RTC_WAKEUP, slot.getTimeInMillis(), sender); 
    } 
} 

TestService.java:

package com.test; 

import android.app.Service; 
import android.content.Intent; 
import android.os.IBinder; 
import android.util.Log; 

public class TestService extends Service { 

    private static final String TAG = "TestService"; 

    public static volatile boolean flag = false; 

    private MyTopThread mTopThread; 

    public TestService() { 
    } 

    @Override 
    public IBinder onBind(Intent intent) { 
     return null; 
    } 


    @Override 
    public void onCreate() { 

    } 

    @Override 
    public void onDestroy() { 

    } 

    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 
     protect(); 

     // We want this service to continue running until it is explicitly 
     // stopped, so return sticky. 
     return START_STICKY; 
    } 


    /** 
    * Run protection 
    * 
    */ 
    private void protect() { 

     mTopThread = new MyTopThread(); 
     mTopThread.start(); 
    } 


    private class MyTopThread extends Thread { 

     @Override 
     public void run() { 
      while (true) { 
       try { 
        Thread.sleep(150); 
        Log.d(TAG, "Flag is " + TestService.flag); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 

      } 
     } 

    } 
} 

TestReceiver.java:

package com.test; 

import android.content.BroadcastReceiver; 
import android.content.Context; 
import android.content.Intent; 
import android.util.Log; 

public class TestReceiver extends BroadcastReceiver { 
    final static private String TAG = "TestReceiver"; 

    @Override 
    public void onReceive(Context context, Intent intent) { 
     Log.d(TAG, "onReceive is triggered ..."); 
     TestService.flag = true; 
     Log.d(TAG, "flag is changed to " + TestService.flag); 

    } 
} 

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="com.test" 
    android:versionCode="1" 
    android:versionName="1.0" > 

    <uses-sdk android:minSdkVersion="8" /> 

    <application 
     android:icon="@drawable/ic_launcher" 
     android:label="@string/app_name" > 
     <activity 
      android:name=".TestappActivity" 
      android:label="@string/app_name" > 
      <intent-filter> 
       <action android:name="android.intent.action.MAIN" /> 

       <category android:name="android.intent.category.LAUNCHER" /> 
      </intent-filter> 
     </activity> 

     <service android:name=".TestService" /> 

     <receiver 
      android:name=".TestReceiver" 
      android:process=":remote" > 
     </receiver> 
    </application> 

</manifest> 
+0

Debería estar funcionando. ¿Puedes publicar tu código? –

+0

versión simplificada se ve así: – Safecoder

+0

No veo dónde se cambia el valor de 'flag'. –

Respuesta

7

Creo que el problema es que está ejecutando el receptor en su propio proceso. A partir de la documentación para el atributo android:process de <receiver>:

Si el nombre asignado a este atributo comienza con dos puntos (':'), un nuevo proceso, privado de la aplicación, se crea cuando se necesita y la emisión el receptor se ejecuta en ese proceso.

creo que el receptor está modificando una versión local del proceso de TestService.flag, no el que está siendo utilizado por TestService. Intente eliminar el atributo android:process de la etiqueta <receiver> en su manifiesto.

+0

¡Tienes razón! Después de ver su pregunta sobre el proceso de servicio, estaba pensando en lo mismo. ¡Lo probé y funciona! ¡Muchas gracias! – Safecoder

0

realmente espero el hilo servicio no es este (no veo ninguna otra):

private class MyTopThread extends Thread { 

    @Override 
    public void run() { 
     while (true) { 
      try { 
       Thread.sleep(150); 
       Log.d(TAG, "Flag is " + TestService.flag); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 

     } 
    } 

} 

Debido a que tiene while(true) aquí, no while(!flag) como debe ser.

+1

, este es solo un programa de prueba que armé rápidamente para mostrar el problema. Es while (verdadero) porque quiero mostrar el valor del indicador para ver si el receptor de difusión lo cambia. pero Logcat muestra que se mantiene como "Bandera es falsa", incluso después de ver "flag is changed to true" de broadcastreceiver. – Safecoder

+0

Ejecútalo y verás a qué me refiero. Debe configurar un filtro para "el indicador se cambia a verdadero", ya que el mensaje "Marcar como falso" continúa imprimiéndose en el ciclo while. – Safecoder

+0

@Howard Li: ¿está seguro de que se ejecuta onReceive donde lo está configurando en falso? – Tudor