1

我試圖在應用啓動時獲取用戶的地理位置,即在啓動畫面期間。在啓動畫面中獲取用戶的地理位置

我的方法是在主要活動中使用asynctask從單獨的類中獲取地理位置。我是android新手,所以我可能會錯過某些東西。下面是我寫來獲取用戶的地理位置的示例代碼:

SplashScreenActivity.java(獲取地理位置無意向性服務)

package work.office; 

import work.office.GeoLocationFinder.LocationResult; 
import android.app.Activity; 
import android.app.ProgressDialog; 
import android.content.Context; 
import android.content.Intent; 
import android.location.Location; 
import android.os.AsyncTask; 
import android.os.Bundle; 
import android.os.Handler; 
import android.util.Log; 
import android.view.Menu; 

public class SplashScreenActivity extends Activity { 

    private static final String TAG = "SplashScreenActivity"; 
    private ProgressDialog pd = null; 
    private Object data = null; 
    LocationResult locationResult; 
    Location newLocation = null; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_splash_screen); 

     new GetGeoLocationAsyncTask(getApplicationContext()).execute(); 
    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     // Inflate the menu; this adds items to the action bar if it is present. 
     getMenuInflater().inflate(R.menu.splash_screen, menu); 
     return true; 
    } 

    private class GetGeoLocationAsyncTask extends 
      AsyncTask<Void, Integer, Location> { 

     private static final String TAG = "GetGeoLocationAsyncTask"; 
     private Context ctx = null; 

     public GetGeoLocationAsyncTask(Context applicationContext) { 
      this.ctx = applicationContext; 
     } 

     @Override 
     protected void onPreExecute() { 
      pd = new ProgressDialog(SplashScreenActivity.this); 
      pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); 
      pd.setTitle("Loading..."); 
      pd.setMessage("Finding your geo location... Please wait"); 
      pd.setCancelable(Boolean.FALSE); 
      pd.setIndeterminate(Boolean.TRUE); 
      pd.setMax(100); 
      pd.setProgress(0); 
      pd.show(); 
      super.onPreExecute(); 
     } 

     @Override 
     protected Location doInBackground(Void... params) { 

        LocationResult locationResult = new LocationResult() { 

         @Override 
         public void gotLocation(Location location) { 
          if (location != null) { 

           newLocation = new Location(location); 
           newLocation.set(location); 
          } else { 
           Log.d(TAG, "Location received is null"); 
          } 

         } 

        }; 
        GeoLocationFinder geoLocationFinder = new GeoLocationFinder(); 
        geoLocationFinder.getLocation(this.ctx, 
          locationResult); 

      return newLocation; 
     } 

     @Override 
     protected void onPostExecute(Location result) { 
      super.onPostExecute(result); 
      if (result != null) { 
       Log.d(TAG, 
         "Got coordinates, congratulations. Longitude = " 
           + result.getLongitude() + " Latitude = " 
           + result.getLatitude()); 
      } else { 
       Log.d(TAG, "Coordinates are null :("); 
      } 
      pd.dismiss(); 
     } 

    } 

} 

GeoLocationFinder.java

package work.office; 

import java.util.Timer; 
import java.util.TimerTask; 

import android.content.Context; 
import android.location.Location; 
import android.location.LocationListener; 
import android.location.LocationManager; 
import android.os.Bundle; 
import android.util.Log; 

public class GeoLocationFinder { 
    private static final String TAG = "GeoLocationFinder"; 
    Timer locationTimer; 
    LocationManager locationManager; 
    Location location; 
    private static final int min_update_time = 20000; // in msec 
    private static final int min_distance_for_update = 10; // in meters 
    LocationResult locationResult; 
    boolean gps_enabled = Boolean.FALSE; 
    boolean network_enabled = Boolean.FALSE; 

    public boolean getLocation(Context ctx, LocationResult result) { 
     locationResult = result; 

     if (locationManager == null) { 
      locationManager = (LocationManager) ctx 
        .getSystemService(Context.LOCATION_SERVICE); 
     } 

     try { 
      gps_enabled = locationManager 
        .isProviderEnabled(LocationManager.GPS_PROVIDER); 
     } catch (Exception e) { 
      Log.d(TAG, "GPS enabled exception: " + e.getMessage()); 
     } 

     try { 
      network_enabled = locationManager 
        .isProviderEnabled(LocationManager.NETWORK_PROVIDER); 
     } catch (Exception e) { 
      Log.d(TAG, "Network enabled exception: " + e.getMessage()); 
     } 

     if (!gps_enabled && !network_enabled) { 
      Log.d(TAG, "You are doomed boy!!"); 
      return Boolean.FALSE; 
     } 

     if (gps_enabled) { 
      locationManager.requestLocationUpdates(
        LocationManager.GPS_PROVIDER, min_update_time, 
        min_distance_for_update, locationListenerGps); 
     } 

     if (network_enabled) { 
      locationManager.requestLocationUpdates(
        LocationManager.NETWORK_PROVIDER, min_update_time, 
        min_distance_for_update, locationListenerNetwork); 
     } 

     locationTimer = new Timer(); 
     locationTimer.schedule(new GetLastLocation(), 20000); 
     return Boolean.TRUE; 
    } 

    LocationListener locationListenerGps = new LocationListener() { 
     public void onLocationChanged(Location location) { 
      locationTimer.cancel(); 
      locationResult.gotLocation(location); 
      locationManager.removeUpdates(this); 
      locationManager.removeUpdates(locationListenerGps); 
     } 

     @Override 
     public void onProviderDisabled(String provider) { 
      Log.d(TAG, "GPS provider disabled" + provider); 

     } 

     @Override 
     public void onProviderEnabled(String provider) { 
      Log.d(TAG, "GPS provider enabled" + provider); 

     } 

     @Override 
     public void onStatusChanged(String provider, int status, Bundle extras) { 
      Log.d(TAG, "GPS status changed"); 

     } 


    }; 

    LocationListener locationListenerNetwork = new LocationListener() { 
     public void onLocationChanged(Location location) { 
      locationTimer.cancel(); 
      locationResult.gotLocation(location); 
      locationManager.removeUpdates(this); 
      locationManager.removeUpdates(locationListenerNetwork); 
     } 

     @Override 
     public void onProviderDisabled(String provider) { 
      Log.d(TAG, "Network provider disabled. " + provider); 

     } 

     @Override 
     public void onProviderEnabled(String provider) { 
      Log.d(TAG, "Network provider enabled. " + provider); 

     } 

     @Override 
     public void onStatusChanged(String provider, int status, Bundle extras) { 
      Log.d(TAG, "Network status changed."); 

     } 
    }; 

    private class GetLastLocation extends TimerTask { 

     @Override 
     public void run() { 
      locationManager.removeUpdates(locationListenerGps); 
      locationManager.removeUpdates(locationListenerNetwork); 
      Location net_loc = null, gps_loc = null; 
      if (gps_enabled) { 
       gps_loc = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); 
      } 
      if (network_enabled) { 
       net_loc = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER); 
      } 
      if (gps_loc != null && net_loc != null) { 
       if (gps_loc.getTime() > net_loc.getTime()) { 
        locationResult.gotLocation(gps_loc); 
       } else { 
        locationResult.gotLocation(net_loc); 
       } 
       return; 
      } 

      if (gps_loc != null) { 
       locationResult.gotLocation(gps_loc); 
       return; 
      } 

      if (net_loc != null) { 
       locationResult.gotLocation(net_loc); 
       return; 
      } 

      locationResult.gotLocation(null); 

     } 

    } 

    public static abstract class LocationResult { 
     public abstract void gotLocation(Location location); 
    } 
} 

當我在手機上安裝這個apk時,我得到這個錯誤:引起:java.lang.RuntimeException:不能在線程內創建沒有調用Loop的處理程序er.prepare()(在SplashScreenActivity.java中,當我在後臺線程中嘗試獲取位置)

This question也提到了錯誤,但在我的上下文中,我無法鏈接它。可能是因爲我在後臺線程中使用了SplashScreenActivity上下文。但如何糾正呢?另外,在啓動畫面期間尋找地理位置的最佳方法是什麼?請幫忙。

回答

3

你正在認真地過度使用它。 AsyncTask在這種情況下不能完成任何事情。這裏是代碼簡化,但仍然異步獲取位置:

package work.office; 
import android.app.Activity; 
import android.app.ProgressDialog; 
import android.content.Context; 
import android.content.Intent; 
import android.location.Location; 
import android.os.AsyncTask; 
import android.os.Bundle; 
import android.os.Handler; 
import android.util.Log; 
import android.view.Menu; 

public class SplashScreenActivity extends Activity { 

    private static final String TAG = "SplashScreenActivity"; 
    private ProgressDialog pd = null; 
    private Object data = null; 
    GeoLocationFinder.LocationResult locationResult; 
    Location newLocation = null; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_splash_screen); 

     setupLocation(); 
    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     // Inflate the menu; this adds items to the action bar if it is present. 
     getMenuInflater().inflate(R.menu.splash_screen, menu); 
     return true; 
    } 

    private void setupLocation() { 
     pd = new ProgressDialog(SplashScreenActivity.this); 
     pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); 
     pd.setTitle("Loading..."); 
     pd.setMessage("Finding your geo location... Please wait"); 
     pd.setCancelable(Boolean.FALSE); 
     pd.setIndeterminate(Boolean.TRUE); 
     pd.setMax(100); 
     pd.setProgress(0); 
     pd.show(); 

     GeoLocationFinder.LocationResult locationResult = new GeoLocationFinder.LocationResult() { 

      @Override 
      public void gotLocation(Location location) { 
       if (location != null) { 

        newLocation = new Location(location); 
        newLocation.set(location); 

        Log.d(TAG, 
          "Got coordinates, congratulations. Longitude = " 
            + newLocation.getLongitude() + " Latitude = " 
            + newLocation.getLatitude()); 
        pd.dismiss(); 
       } else { 
        Log.d(TAG, "Location received is null"); 
       } 

      } 

     }; 
     GeoLocationFinder geoLocationFinder = new GeoLocationFinder(); 
     geoLocationFinder.getLocation(this, 
       locationResult); 
    } 
} 
+0

我還沒有嘗試過這種方法呢。但出於好奇,我使用網絡也作爲提供者之一。所以如果一個人沒有打開他的GPS但連接到Wi-Fi,在這種情況下,主要活動線程將調用網絡操作,現在不允許該操作(應用程序將因主要活動線)。我爲此寫了asynctask。 – 2013-05-09 11:48:21

+0

通常,您使用LocationManager.requestLocationUpdates()方法設置LocationListener。它會異步地爲您提供位置更新。 – mach 2013-05-10 07:38:52

+0

我試過了。有效。謝謝你的幫助。 – 2013-05-10 10:31:39