BroadcastReceiver ne pas lire la valeur stockée à partir SharedPreferences
-
08-10-2019 - |
Question
Dans mon application j'ai un récepteur de radiodiffusion qui tourne sur GPS lors de la réception d'une chaîne de jeu de texte. Dans la méthode OnLocationChanged, je veux transmettre les données GPS et une valeur de mes préférences partagées à un fil dans une chaîne.
Je l'écriture de fil pour se connecter et peut voir toutes les valeurs GPS dans la chaîne, mais la dernière valeur de mes préférences partagées montre juste comme « prefPhoneNum » que j'initialisés la chaîne au début de la classe de récepteur. J'ai le même code pour lire le prefPhoneNum des préférences partagées dans la classe principale et il fonctionne là-bas, peut-on voir ce que je pourrais faire mal?
public class SmsReceiver extends BroadcastReceiver implements LocationListener
{
LocationManager lm;
LocationListener loc;
public SharedPreferences sharedpreferences;
public static final String US = "usersettings";
public String prefPhoneNum = "prefPhoneNum";
@Override
public void onReceive(Context context, Intent intent)
{
sharedpreferences = context.getSharedPreferences(US, Context.MODE_PRIVATE);
prefPhoneNum = sharedpreferences.getString("prefPhoneNum" , "");
lm = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
loc = new SmsReceiver();
//---get the SMS message passed in---
Bundle bundle = intent.getExtras();
SmsMessage[] msgs = null;
String str = "";
if (bundle != null)
{
//---retrieve the SMS message received---
Object[] pdus = (Object[]) bundle.get("pdus");
msgs = new SmsMessage[pdus.length];
for (int i=0; i<msgs.length; i++)
{
msgs[i] = SmsMessage.createFromPdu((byte[])pdus[i]);
str += msgs[i].getMessageBody().toString() + "\n";
}
Toast.makeText(context, str, Toast.LENGTH_SHORT).show(); //Display SMS
if ((msgs[0].getMessageBody().toString().equals("Enable")) ||
(msgs[0].getMessageBody().toString().equals("enable")))
{
enableGPS();
}
else { /* Do Nothing*/ }
}
}
public void enableGPS() {
//new CountDownTimer(10000, 1000) { //10 seconds
new CountDownTimer(300000, 1000) { //300 secs = 5 mins
public void onTick(long millisUntilFinished)
{
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, loc);
}
public void onFinish()
{
lm.removeUpdates(loc);
}
}.start();
}
@Override
public void onLocationChanged(Location location) {
String s = "";
s += location.getLatitude() + "\n";
s += location.getLongitude() + "\n";
s += location.getAltitude() + "\n";
s += location.getAccuracy() + "\n" + prefPhoneNum;
Thread cThread = new Thread(new SocketsClient(s));
cThread.start();
}
@Override
public void onProviderDisabled(String provider) { }
@Override
public void onProviderEnabled(String provider) { }
@Override
public void onStatusChanged(String provider, int status, Bundle extras) { }
}
Voici le logcat lorsque les applications se ferme -
D/LocationManager( 3912): requestLocationUpdates: provider = gps, listener = accel.working.TrackGPS@4628bce0
D/GpsLocationProvider( 96): setMinTime 0
D/GpsLocationProvider( 96): startNavigating
D/GpsLocationProvider( 96): TTFF: 3227
D/AndroidRuntime( 3912): Shutting down VM
W/dalvikvm( 3912): threadid=1: thread exiting with uncaught exception (group=0x400259f8)
E/AndroidRuntime( 3912): FATAL EXCEPTION: main
E/AndroidRuntime( 3912): java.lang.NullPointerException
E/AndroidRuntime( 3912): at android.content.ContextWrapper.getSharedPreferences(ContextWrapper.java:146)
E/AndroidRuntime( 3912): at accel.working.TrackGPS.onLocationChanged(TrackGPS.java:63)
E/AndroidRuntime( 3912): at android.location.LocationManager$ListenerTransport._handleMessage(LocationManager.java:191)
E/AndroidRuntime( 3912): at android.location.LocationManager$ListenerTransport.access$000(LocationManager.java:124)
E/AndroidRuntime( 3912): at android.location.LocationManager$ListenerTransport$1.handleMessage(LocationManager.java:140)
E/AndroidRuntime( 3912): at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime( 3912): at android.os.Looper.loop(Looper.java:144)
E/AndroidRuntime( 3912): at android.app.ActivityThread.main(ActivityThread.java:4937)
E/AndroidRuntime( 3912): at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime( 3912): at java.lang.reflect.Method.invoke(Method.java:521)
E/AndroidRuntime( 3912): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
E/AndroidRuntime( 3912): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
E/AndroidRuntime( 3912): at dalvik.system.NativeStart.main(Native Method)
La solution
Vous faites beaucoup trop dans notre onReceieve (). De la documentation http://developer.android.com/reference/android/ contenu / BroadcastReceiver.html # ReceiverLifecycle :
Un objet est seulement BroadcastReceiver valable pour la durée de l'appel à OnReceive (contexte, intention). Une fois que votre retourne le code de cette fonction, le système considère l'objet à fini et ne sont plus actifs.
Cela a des répercussions importantes à ce que vous pouvez faire dans un OnReceive (contexte, intention) la mise en œuvre: tout ce qui exige opération asynchrone n'est pas disponible, parce que vous devrez revenir de la fonction à traiter la opération asynchrone, mais à ce point le BroadcastReceiver est pas plus active et donc le système est libre de tuer son processus avant la finalise l'opération asynchrone.
ne peut en particulier montrer un dialogue ou se lient à un service de dans un BroadcastReceiver. Pour le ancien, vous devriez plutôt utiliser le API NotificationManager. Pour le celui-ci, vous pouvez utiliser Context.startService () pour envoyer un commande au service.