在启动画面期间获取用户的地理位置

Posted

技术标签:

【中文标题】在启动画面期间获取用户的地理位置【英文标题】:Fetching geo location of a user during splashscreen 【发布时间】:2013-05-02 08:40:09 【问题描述】:

我正在尝试在应用启动时(即在启动画面期间)获取用户的地理位置。

我的方法是在主要活动中使用 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:无法在未调用 Looper.prepare() 的线程内创建处理程序(在后台时位于 SplashScreenActivity.java线程我尝试获取位置)

This question 也提到了错误,但在我的上下文中我无法链接它。可能是因为我在后台线程中使用了 SplashScreenActivity 上下文。但是如何纠正呢?此外,在启动画面期间查找地理位置的最佳方法是什么?请帮忙。

【问题讨论】:

【参考方案1】:

你做得太过分了。在这种情况下,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);
    

【讨论】:

我还没有尝试过这种方法。但出于好奇,我也使用网络作为提供者之一。因此,如果一个人没有打开他的 GPS 但连接到 wi-fi,在这种情况下,主活动线程将调用网络操作,现在不允许这样做(应用程序将因主 Activity 上的网络原因而崩溃线)。我为此编写了 asynctask。 通常您使用 LocationManager.requestLocationUpdates() 方法设置 LocationListener。它会异步为您提供位置更新。

以上是关于在启动画面期间获取用户的地理位置的主要内容,如果未能解决你的问题,请参考以下文章

MainActivity 应在启动画面期间加载

在 Flutter 的启动画面期间加载数据

Worklight Cordova 应用程序启动画面在应用程序启动期间旋转

如何在 iOS 7 和 iOS 6 中出现动画启动画面期间隐藏状态栏?

5.4 设置应用程序启动画面

如何在 Flutter 中获取原生启动画面?