0

在我的应用程序中,我有一个广播接收器,它在接收到一组文本时打开 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)  
4

1 回答 1

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() 向服务发送命令。

于 2010-12-11T23:49:31.413 回答