2012-01-15 18 views
5

Mam klasy działania, w którym mam statycznych flagę, powiedzmyAndroid volatile nie działa?

public static volatile flag = false; 

Następnie w klasie, zaczynam wątek, który sprawdza flagę i robić różne rzeczy.

Posiadam również nadajnik-odbiornik, który ustawia flagę na true lub false.

Chociaż lotny zmusi flagę do najnowszej wartości. Ale widzę, że mój odbiornik ustawił flagę statyczną na prawdziwą, ale mój wątek nadal robi to jako fałszywe.

Czy brakuje tu czegoś podstawowego? Każda pomoc będzie doceniona!

Uproszczony kod (zaktualizowany) - flaga powinna zmienić się na true po minucie. Ale nigdy tak nie było. Ale wiadomość od odbiornika transmisji pokazuje, że został zmiany prawdziwego

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

Powinien działać. Czy możesz opublikować swój kod? –

+0

wersja uproszczona wygląda następująco: – Safecoder

+0

Nie widzę, gdzie zmienia się wartość 'flag'. –

Odpowiedz

7

Myślę, że problem polega na tym, że odbiornik działa we własnym procesie. Od docs dla atrybutu android:process z <receiver>:

Jeśli nazwa przypisana do tego atrybutu zaczyna się dwukropkiem („:”), nowego procesu, prywatny do aplikacji jest tworzony, gdy jest to potrzebne i audycji odbiornik działa w tym procesie.

myślę, że odbiornik jest modyfikowanie wersji procesu lokalnego z TestService.flag, a nie jeden używany przez TestService. Spróbuj usunąć atrybut android:process z tagu <receiver> w manifeście.

+0

Masz rację! Po tym, jak zobaczyłem twoje pytanie o proces obsługi, myślałem o tym samym. Po prostu to wypróbowałem i to działa! Wielkie dzięki! – Safecoder

0

Mam nadzieję, że Twój wątek usługa nie jest to jeden (nie widzę żadnego innego jeden):

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

     } 
    } 

} 

Ponieważ masz while(true) tutaj, nie while(!flag) jak powinno być.

+1

to tylko program testowy, który przygotowałem szybko, aby pokazać problem. Jest to prawda (prawda), ponieważ chcę wyświetlić wartość flagi, aby sprawdzić, czy jest zmieniana przez odbiornik transmisji. ale logcat pokazuje, że pozostaje jako "Flaga jest fałszywa", nawet gdy widzę "flagę zmieniono na true" z nadawcy odbiorczego. – Safecoder

+0

Uruchom, a zobaczysz, co mam na myśli. Musisz ustawić filtr dla "flaga zostanie zmieniona na prawdziwą", ponieważ komunikat "Flaga jest fałszywa" będzie dalej drukowany w pętli while. – Safecoder

+0

@Howard Li: czy jesteś pewien, że onReceive, w którym ustawiasz wartość false, jest wykonywane? – Tudor