BroadcastReceiver not reading stored value from SharedPreferences
In my app I have a broadcast receiver that turns on GPS upon receiving a set string of text. In the onLocationChanged method, I want to pass the GPS data and a value from my shared preferences to a thread in a string.
I have the thread writing to log and can see all the GPS values in the string but the last value from my shared preferences is just showing up as 'prefPhoneNum' which I initialised the string to at the beginning of the receiver class. I have the same code to read the prefPhoneNum from shared preferences in the main class and it works there, can anyone see what I might be doing wrong?public class SmsReceiver extends BroadcastReceiver implements LocationListener
{
LocationMana开发者_运维技巧ger 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) { }
}
Here is the logcat for when the application shuts -
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)
You're doing WAY too much in our onReceieve(). From the docs http://developer.android.com/reference/android/content/BroadcastReceiver.html#ReceiverLifecycle :
A BroadcastReceiver object is only valid for the duration of the call to onReceive(Context, Intent). Once your code returns from this function, the system considers the object to be finished and no longer active.
This has important repercussions to what you can do in an onReceive(Context, Intent) implementation: anything that requires asynchronous operation is not available, because you will need to return from the function to handle the asynchronous operation, but at that point the BroadcastReceiver is no longer active and thus the system is free to kill its process before the asynchronous operation completes.
In particular, you may not show a dialog or bind to a service from within a BroadcastReceiver. For the former, you should instead use the NotificationManager API. For the latter, you can use Context.startService() to send a command to the service.
精彩评论