【问题标题】:getting current location using async task使用异步任务获取当前位置
【发布时间】:2012-10-01 16:57:32
【问题描述】:

我尝试使用异步任务获取当前位置,此代码在没有异步任务的情况下可以正常工作,但是当我尝试使用异步任务时,它显示未找到位置和抱歉未找到地址。这是我的代码,请帮助我提前感谢

public class MainActivity extends Activity {
/** Called when the activity is first created. */
String addressString;    
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
        new Getlocation().execute();    

}

// 开始异步任务

class Getlocation extends AsyncTask<String, String, String> {


    ProgressDialog p;

    @Override
    protected void onPreExecute() {
        // TODO Auto-generated method stub

       p = new ProgressDialog(MainActivity.this);                   
         p.setMessage("Please Wait Retrieving data..");     
         p.setTitle(" ");                                       
         p.setIcon(R.drawable.settings2);                       
         p.show();                                               
    }
    @Override
    protected String doInBackground(String... params) {
        Looper.prepare();

          LocationManager locationManager; 

            String context = Context.LOCATION_SERVICE; 
            locationManager = (LocationManager)getSystemService(context); 

            Criteria crta = new Criteria(); 
            crta.setAccuracy(Criteria.ACCURACY_FINE); 
            crta.setAltitudeRequired(false); 
            crta.setBearingRequired(false); 
            crta.setCostAllowed(true); 
            crta.setPowerRequirement(Criteria.POWER_LOW); 
            String provider = locationManager.getBestProvider(crta, true); 

         //String provider = LocationManager.GPS_PROVIDER; 
            Location location = locationManager.getLastKnownLocation(provider); 
            updateWithNewLocation(location); 
           LocationListener locationListener = new LocationListener() 
         { 

         @Override 
         public void onLocationChanged(Location location) { 
         updateWithNewLocation(location); 
         } 

         @Override 
         public void onProviderDisabled(String provider) { 
         updateWithNewLocation(null); 
         } 

         @Override 
         public void onProviderEnabled(String provider) { 
         } 

         @Override 
         public void onStatusChanged(String provider, int status, Bundle extras) { 
         } 

         };
         locationManager.requestLocationUpdates(provider, 2000, 10, locationListener); 
         Looper.loop();

        return addressString;
    }
     @Override
        protected void onPostExecute(String result) {
            // TODO Auto-generated method stub
            super.onPostExecute(result); 
            p.dismiss();                    

    }   }
 private void updateWithNewLocation(Location location) { 
     String latLong;
     TextView myLocation; 
      addressString = "Sorry  No Address Found"; 
     if(location!=null) { 
    double lat = location.getLatitude(); 
     double lon = location.getLongitude(); 
     latLong = "Lat:" + lat + "\nLong:" + lon; 
     double lattitude = location.getLatitude(); 
     double longitude = location.getLongitude(); 
     Geocoder gc = new Geocoder(this,Locale.getDefault()); 
     try { 
     List<Address> addresses= gc.getFromLocation(lattitude, longitude, 1); 
     StringBuilder sb = new StringBuilder(); 
     if(addresses.size()>0) { 
     Address address=addresses.get(0);
     for(int i=0;i<address.getMaxAddressLineIndex();i++)
     sb.append(address.getAddressLine(i)).append("\n");
     sb.append(address.getLocality()).append("\n"); 
     sb.append(address.getPostalCode()).append("\n"); 
     sb.append(address.getCountryName()); 

     } 
     addressString = sb.toString(); 
     } 
     catch (Exception e) { 
     } 
     } else { 
     latLong = " NO Location Found "; 
     } 
Toast.makeText(getApplicationContext(), "Current Position is :\n"+ latLong + "\n"+  addressString ,Toast.LENGTH_LONG).show();
  //  myLocation.setText("Current Position is :\n"+ latLong + "\n"+  addressString ); 
        }

}

//这是我的日志

    10-01 22:34:13.720: E/WindowManager(2868): Activity com.example.sc.MainActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@411dd3c8 that was originally added here
10-01 22:34:13.720: E/WindowManager(2868): android.view.WindowLeaked: Activity com.example.sc.MainActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@411dd3c8 that was originally added here
10-01 22:34:13.720: E/WindowManager(2868):  at android.view.ViewRootImpl.<init>(ViewRootImpl.java:374)
10-01 22:34:13.720: E/WindowManager(2868):  at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:292)
10-01 22:34:13.720: E/WindowManager(2868):  at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:224)
10-01 22:34:13.720: E/WindowManager(2868):  at android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.java:149)
10-01 22:34:13.720: E/WindowManager(2868):  at android.view.Window$LocalWindowManager.addView(Window.java:547)
10-01 22:34:13.720: E/WindowManager(2868):  at android.app.Dialog.show(Dialog.java:277)
10-01 22:34:13.720: E/WindowManager(2868):  at com.example.sc.MainActivity$Getlocation.onPreExecute(MainActivity.java:68)
10-01 22:34:13.720: E/WindowManager(2868):  at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:586)
10-01 22:34:13.720: E/WindowManager(2868):  at android.os.AsyncTask.execute(AsyncTask.java:534)
10-01 22:34:13.720: E/WindowManager(2868):  at com.example.sc.MainActivity.onCreate(MainActivity.java:51)
10-01 22:34:13.720: E/WindowManager(2868):  at android.app.Activity.performCreate(Activity.java:5008)
10-01 22:34:13.720: E/WindowManager(2868):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
10-01 22:34:13.720: E/WindowManager(2868):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)
10-01 22:34:13.720: E/WindowManager(2868):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
10-01 22:34:13.720: E/WindowManager(2868):  at android.app.ActivityThread.access$600(ActivityThread.java:130)
10-01 22:34:13.720: E/WindowManager(2868):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
10-01 22:34:13.720: E/WindowManager(2868):  at android.os.Handler.dispatchMessage(Handler.java:99)
10-01 22:34:13.720: E/WindowManager(2868):  at android.os.Looper.loop(Looper.java:137)
10-01 22:34:13.720: E/WindowManager(2868):  at android.app.ActivityThread.main(ActivityThread.java:4745)
10-01 22:34:13.720: E/WindowManager(2868):  at java.lang.reflect.Method.invokeNative(Native Method)
10-01 22:34:13.720: E/WindowManager(2868):  at java.lang.reflect.Method.invoke(Method.java:511)
10-01 22:34:13.720: E/WindowManager(2868):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
10-01 22:34:13.720: E/WindowManager(2868):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
10-01 22:34:13.720: E/WindowManager(2868):  at dalvik.system.NativeStart.main(Native Method)

【问题讨论】:

  • 您需要发布 LogCat 错误,以便任何人能够帮助您。我的第一个猜测是你没有在你的android清单xml中添加使用位置的权限
  • @PaulD'Ambra 请查看我编辑的总问题
  • @RaghavSood 请查看我编辑的总问题
  • 我认为列出的错误与错误使用 ProgressBar 有关(至少我从未见过 ProgressBar 以这种方式声明)。当您尝试显示实际上不在屏幕上的 ProgressBar 时,Android 会抱怨。

标签: android location


【解决方案1】:

这看起来像经典的“在非Looper 线程中创建处理程序”异常。基本上,您正在创建一个 Handler 来接收位置消息到您的 LocationListener 对象,该对象是在它自己的线程中创建的。一旦方法返回,运行doInBackground() 的线程就会死掉。因此,LocationManager 正在向死线程中的死对象发送数据,您会得到一个异常。

Loopers 的一个很好的示例在这里:

What is the purpose of Looper and how to use it?

如果将Looper.prepare() 放在doInBackground() 的顶部,将Looper.loop() 放在底部,则可以继续使用AsyncTask。 Looper.loop() 只是一个空的 while 循环,它将让你的线程永远打开。

为了让它死掉,你必须在你的线程中调用 Looper.myLooper().quit() 来杀死它。最简单的方法是在Looper.prepare()之后立即执行,保存Looper 通过调用 Looper.myLoop()。然后在要停止更新时调用的方法中将其杀死。

class LooperAsyncTask extends AsyncTask<Void, Void, Void> {

    private mThreadLooper;

    @Override
    protected String doInBackground(String... params) {
      Looper.prepare();
      mThreadLooper = Looper.myLooper();
      **setup code**
      Looper.loop();
    }

    public void stopUpdates() {
      **cleanup code**
      if(mThreadLooper != null)
        mThreadLooper.quit();
    }
}

【讨论】:

  • 我认为将 AsynTask 更改为 Service 或 IntentService 以强制更新 Location 会更好。您仍然可以使用上面的代码来获取 getLastKnownLocation,如果任何位置提供者与您的条件不匹配,您还必须添加非空检查。
  • 我没有得到请发布所需修改的代码请查看我的新更新问题
  • 我正在检查 if(location!=null)
  • 可能还有其他问题。我才注意到这个。您将不得不寻找 Logcat 吐出的异常。在那里。我保证。 @Anis:如果你从一个活动跳到另一个活动,或者你希望它在应用程序暂停时继续更新,你真的只需要一个服务。如果他只是坐在主 Activity 中,那么一个普通的线程就可以了。
  • @Deev ,我有使用 GPS_PROVIDER 的位置更新问题。我的链接是stackoverflow.com/questions/20112140/…。这与我使用其他活动而不是主要活动的原因相同吗??
【解决方案2】:

您的 LocationManager 和 LocationListener 不需要在 AsyncTask 中。它们应该在 Activity 中(如果您想在 Activity 之间共享它们,则应该在 Activity 引用的其他类中)。

在 AsyncTask 中注册 LocationListener 不是正确的方法,因为该侦听器与 AsyncTask 一起死亡,因此不会在附近侦听更新。

顺便说一句,您的 updateWithNewLocation() 方法正在创建一个它没有使用的 TextView。

通过在 updateWithNewLocation() 中调用 Toast,您实际上是在 doInBackground 中调用它,它不在 UI 线程上运行,因此 Toast 设置起来会很时髦,除非您在实例化 AsyncTask 时传入上下文。

如果这是一个缓慢的过程,那么当您的 Activity 捕获位置更改时,您可以在 AsyncTask 中反向地理编码,然后通过将 doInBackground 反向地理编码的结果传递给 onPostExecute 来显示 Toast(或更新 TextView)在 UI 线程上运行,因此可以安全轻松地更新视图并显示 Toast。

class ReverseGeocodeAsyncTask extends AsyncTask<Void, Void, Void> {

    private Location location;

    public ReverseGeocodeAsyncTask(Location l) { location = l; }

    @Override
    protected String doInBackground(String... params) {
     //do reverse geocoding and return the result
    }

     @Override
     protected void onPostExecute(String result) {
        // update the UI with the result of the reverse geocoding                   
    }
}

【讨论】:

  • 对不起,我没有收到您,请您发布所需修改的代码 thnaku
猜你喜欢
  • 2023-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-30
  • 1970-01-01
  • 2016-12-01
  • 2015-11-15
相关资源
最近更新 更多