在我的应用程序中,我有一个广播接收器,在接收到一组文本后打开GPS。在onLocationChanged方法中,我想将GPS数据和我的共享首选项中的值传递给字符串中的线程。
我有线程写入日志,可以看到字符串中的所有GPS值,但我的共享首选项中的最后一个值只显示为'prefPhoneNum',我将字符串初始化为接收器类的开头。我有相同的代码从主类中的共享首选项中读取prefPhoneNum并且它在那里工作,任何人都可以看到我可能做错了吗?
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) { }
}
以下是应用程序关闭时的logcat -
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)
答案 0 :(得分:1)
你在onReceieve()中做得太多了。来自文档http://developer.android.com/reference/android/content/BroadcastReceiver.html#ReceiverLifecycle:
仅限BroadcastReceiver对象 在通话期间有效 onReceive(Context,Intent)。一旦你的 代码从这个函数返回, 系统认为对象是 已完成,不再有效。
这会产生重要影响 你能做些什么 onReceive(Context,Intent) 实施:任何需要的东西 异步操作不是 可用,因为你需要 从函数返回来处理 异步操作,但在那 指出BroadcastReceiver是没有的 更长的活动,因此系统是 在此之前自由地杀死它的过程 异步操作完成。
特别是,你可能不会出示 对话框或绑定到服务 在BroadcastReceiver中。为了 前者,你应该改用 NotificationManager API。为了 后者,你可以使用 Context.startService()发送一个 命令服务。