onLocationChanged仅在我第一次打开应用程序时调用,但如果app变为非活动状态并再次激活,则不再调用

时间:2017-06-22 18:24:39

标签: android gps

我正在尝试使用Android Studio构建GPS应用。它在第一次运行时工作正常,但每当我关闭应用程序并再次打开它或转到桌面并重新进入它时,正如我想到的那样,我的LocationListener不再被调用。

实际上会发生的是它第二次没有按预期显示我的位置。没有错误什么都没有。

这是我的代码,如果您能提供帮助,请提前感谢。我一直在寻找:(

    package com.madnzz.googlemapsstuff;

    import android.*;
    import android.Manifest;
    import android.app.Activity;
    import android.content.Context;
    import android.content.pm.PackageManager;
    import android.graphics.Camera;
    import android.graphics.drawable.BitmapDrawable;
    import android.location.Location;
    import android.location.LocationListener;
    import android.location.LocationManager;
    import android.os.Build;
    import android.support.annotation.NonNull;
    import android.support.v4.app.ActivityCompat;
    import android.support.v4.app.FragmentActivity;
    import android.os.Bundle;
    import android.support.v4.content.ContextCompat;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    import android.widget.ImageButton;
    import android.widget.Toast;

    import com.google.android.gms.common.api.GoogleApiClient;
    import com.google.android.gms.location.LocationRequest;
    import com.google.android.gms.location.LocationServices;
    import com.google.android.gms.maps.CameraUpdateFactory;
    import com.google.android.gms.maps.GoogleMap;
    import com.google.android.gms.maps.MapFragment;
    import com.google.android.gms.maps.OnMapReadyCallback;
    import com.google.android.gms.maps.SupportMapFragment;
    import com.google.android.gms.maps.model.GroundOverlay;
    import com.google.android.gms.maps.model.GroundOverlayOptions;
    import com.google.android.gms.maps.model.LatLng;
    import com.google.android.gms.maps.model.MarkerOptions;

    import java.sql.Time;
    import java.util.Random;


    import com.google.android.gms.appindexing.AndroidAppUri;
    import com.google.android.gms.maps.model.BitmapDescriptor;
    import com.google.android.gms.maps.model.BitmapDescriptorFactory;

    import static com.madnzz.googlemapsstuff.R.id.activity_chooser_view_content;
    import static com.madnzz.googlemapsstuff.R.id.repositionButton;


    /*
    TODO: Replace retard user icon with improved one
            *IMPLEMENT the way the user is facing.  http://android-coding.blogspot.ro/2012/03/create-our-android-compass.html
            *
    TODO: implement GPS routes https://www.youtube.com/watch?v=CCZPUeY94MU      or        http://wptrafficanalyzer.in/blog/drawing-driving-route-directions-between-two-locations-using-google-directions-in-google-map-android-api-v2/
            *REPLACE consumed path with cookie crumb graphic

    TODO: save path and able to share with others.

         TODO later: Battery efficiency https://developer.android.com/guide/topics/location/strategies.html

    */

    public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {

            private GoogleMap mMap;
            LocationManager locationManager;
            LocationListener locationListener;
    ////////////////////////////////////////////////////////////////////////////////////

        @Override
        public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);

            if (requestCode == 1) {

                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                    startListening();

                }

            }

        }


        public void startListening() {

            if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {

                locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);

            }

        }

        Random random=new Random();
        GroundOverlayOptions[] c00kieCrumb=new GroundOverlayOptions[200];
        int i=0;
        ///////////////////////////////////////////////////////////////////////////////
        public void addCrumb(LatLng userLocation){
            int randomCrumbBearing=random.nextInt(36)*10;

            c00kieCrumb[i] = new GroundOverlayOptions()
                    .image(BitmapDescriptorFactory.fromResource(R.drawable.frateeeee))
                    .position(userLocation, 3,3).bearing(randomCrumbBearing);
            c00kieCrumb[i].isVisible();
            i++;
            for (int j = 0; j < i; j++) {
                mMap.addGroundOverlay(c00kieCrumb[j]);
            }
        }//adds new cookie crumb to user location

        public void putCrumbConditions(LatLng userLocation){

            for (int j = 0; j < i; j++) {
                mMap.addGroundOverlay(c00kieCrumb[j]);
            }
            if (i == 0) {
                addCrumb(userLocation);

            } else {
                if (Math.abs((c00kieCrumb[i - 1].getLocation().latitude - userLocation.latitude)) > 0.00003
                        || Math.abs(c00kieCrumb[i - 1].getLocation().longitude - userLocation.longitude) > 0.00003) {
                    addCrumb(userLocation);
                }
            }
        }//adds a new cookie crumb to the user location 4
                                                            // IF THE USER IS 0.00003 UNITS AWAY FROM LAST CRUMB PLACED


        @Override
        protected void onCreate(Bundle savedInstanceState) {
            Log.i("ZiciCinci created shit", "Am ajuns aici");

            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_maps);
            // Obtain the SupportMapFragment and get notified when the map is ready to be used.
            SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                    .findFragmentById(R.id.map);
            mapFragment.getMapAsync(this);

        }

        @Override
        protected void onDestroy(Bundle savedInstanceState){
            super.onDestroy();
        }

        LatLng [] locationCalibrator,savedUserLocation;
        LatLng userLocation,previousUserLocation;
        Boolean gpsCalibrationInProgress,tooClose,firstIteration,mapCenteredOnUserPosition,cameraFollowUserPosition;
        int locationIteration=0,savedUserLocationPos;
        ImageButton repositionButton;



        @Override
        public void onMapReady(GoogleMap googleMap) {

            Log.i("ZiciPatru map is ready","Am ajuns aici");


            mMap = googleMap;
            c00kieCrumb[0] = new GroundOverlayOptions();
            locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
            locationCalibrator = new LatLng[100];
            gpsCalibrationInProgress = true;
            locationIteration = 0;
            i = 0;
            savedUserLocation = new LatLng[3];
            savedUserLocationPos = 0;
            tooClose = true;
            firstIteration = true;
            mapCenteredOnUserPosition = true;
            cameraFollowUserPosition = true;
            previousUserLocation = new LatLng(0, 0);


            locationListener = new LocationListener() {
                @Override
                public void onLocationChanged(Location location) {
                    Log.i("Zici3 gps calibration","Am ajuns aici");

                    userLocation = new LatLng(location.getLatitude(), location.getLongitude());

                        if (!gpsCalibrationInProgress) {

                            if (Math.abs(previousUserLocation.latitude - userLocation.latitude) > 0.000003 ||
                                    Math.abs(previousUserLocation.latitude - userLocation.longitude) > 0.000003) {
                                mMap.clear();
                                mMap.addMarker(new MarkerOptions().position(userLocation).title("Your Location").icon(BitmapDescriptorFactory.fromResource(R.drawable.edytardin64x64)).rotation(0));
                                if (firstIteration) {
                                    mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(userLocation, 15));
                                    firstIteration = false;
                                }

                                LatLng userDestination = new LatLng(44.4187432, 26.1556372);

                                mMap.addMarker(new MarkerOptions().position(userDestination).title("COOOOKIESTUFF").icon(BitmapDescriptorFactory.fromResource(R.drawable.c00ki3_marker_128x128)));

                                putCrumbConditions(userLocation);
                            }
                        } else {
                            Toast.makeText(getApplicationContext(), "Calibrating gps, please stand still", Toast.LENGTH_SHORT).show();
                            locationCalibrator[locationIteration] = userLocation;
                            locationIteration++;
                            if (locationIteration >= 2) {
                                if (Math.abs(locationCalibrator[locationIteration - 1].latitude - userLocation.latitude) < 0.0001
                                        && Math.abs(locationCalibrator[locationIteration - 1].longitude - userLocation.longitude) < 0.0001
                                        && Math.abs(locationCalibrator[locationIteration - 2].latitude - userLocation.latitude) < 0.0001
                                        && Math.abs(locationCalibrator[locationIteration - 2].latitude - userLocation.latitude) < 0.0001) {
                                    gpsCalibrationInProgress = false;
                                }
                            }
                        }

                    previousUserLocation = userLocation;

                    repositionButton = (ImageButton) findViewById(R.id.repositionButton);


                    repositionButton.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            Log.i("rarara","q");
                            mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(userLocation, 15));
                            repositionButton.setBackgroundResource(R.drawable.location_centered);
                            mapCenteredOnUserPosition = true;
                            cameraFollowUserPosition = true;
                        }
                    });

                    if (mapCenteredOnUserPosition) {
                        mMap.setOnCameraMoveStartedListener(new GoogleMap.OnCameraMoveStartedListener() {
                            @Override
                            public void onCameraMoveStarted(int reason) {
                                if (reason == GoogleMap.OnCameraMoveStartedListener.REASON_GESTURE) {
                                    repositionButton.setBackgroundResource(R.drawable.location_not_centered);
                                    mapCenteredOnUserPosition = false;
                                    cameraFollowUserPosition = false;
                                }
                            }
                        });
                    }

                    if (cameraFollowUserPosition) {
                        mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(userLocation, 15));
                        repositionButton.setBackgroundResource(R.drawable.location_centered);
                    }
                LocationServices.FusedLocationApi.removeLocationUpdates(GoogleApiClient,this)
                }

                @Override
                public void onStatusChanged(String s, int i, Bundle bundle) {
                }

                @Override
                public void onProviderEnabled(String s) {
                }

                @Override
                public void onProviderDisabled(String s) {

                    Toast.makeText(getApplicationContext(), "Please activate your location", Toast.LENGTH_SHORT);

                }

            };


            if (Build.VERSION.SDK_INT < 23) {
                startListening();
            } else {

                if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                    ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);

                } else {

                    Location lastKnownLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
                    if (lastKnownLocation != null) {
                        LatLng userLocation = new LatLng(lastKnownLocation.getLatitude(), lastKnownLocation.getLongitude());

                        if (!tooClose) {
                            mMap.clear();
                            mMap.addMarker(new MarkerOptions().position(userLocation).title("Your Location").icon(BitmapDescriptorFactory.fromResource(R.drawable.edytardin64x64)));
                        }
                        tooClose = false;
                    } else {
                        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
                    }
                }
            }
        }
    }

我的机器人清单:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.madnzz.googlemapsstuff">

    <!--
         The ACCESS_COARSE/FINE_LOCATION permissions are not required to use
         Google Maps Android API v2, but you must specify either coarse or fine
         location permissions for the 'MyLocation' functionality. 
    -->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

    <application
        android:allowBackup="true"
        android:exported="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"


        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <!--
             android:roundIcon="@mipmap/ic_launcher_round"
             -->
        <!--
             The API key for Google Maps-based APIs is defined as a string resource.
             (See the file "res/values/google_maps_api.xml").
             Note that the API key is linked to the encryption key used to sign the APK.
             You need a different API key for each encryption key, including the release key that is used to
             sign the APK for publishing.
             You can define the keys for the debug and release targets in src/debug/ and src/release/. 
        -->
        <meta-data
            android:name="com.google.android.geo.API_KEY"
            android:value="@string/google_maps_key" />

        <activity
            android:name=".MapsActivity"
            android:label="@string/title_activity_maps">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

布局文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MapsActivity" >

    <fragment xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:map="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/map"
        android:name="com.google.android.gms.maps.SupportMapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.madnzz.googlemapsstuff.MapsActivity"
        android:layout_alignParentTop="true"
        android:layout_alignParentStart="true" />

    <ImageButton
        android:id="@+id/repositionButton"
        android:layout_width="70dp"
        android:layout_height="70dp"
        android:layout_alignParentBottom="true"
        android:layout_alignParentEnd="true"
        android:layout_marginBottom="40dp"
        android:layout_marginEnd="30dp"/>
        <!--android:onClick="repositionMap"-->
        android:background="@drawable/location_not_centered" />
</RelativeLayout>

1 个答案:

答案 0 :(得分:0)

Location lastKnownLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);

if (lastKnownLocation != null) {
    LatLng userLocation = new LatLng(lastKnownLocation.getLatitude(), 
    lastKnownLocation.getLongitude());

    if (!tooClose) {
        mMap.clear();
        mMap.addMarker(new MarkerOptions().position(userLocation).title("Your Location").icon(BitmapDescriptorFactory.fromResource(R.drawable.edytardin64x64)));
    }

    tooClose = false;
} else {
  locationManager.requestLocationUpdates(
        LocationManager.GPS_PROVIDER, 0, 0, locationListener);
}

代码中存在问题的部分(以及场景),

如果lastKnownLocation为空,您确实发出了位置请求。一次收到新位置(onLocationChanged)后,getLastKnownLocation将不会返回null,并且不会调用位置请求以便以后启动(启动除外)

因此,onLocationChanged只调用了一次。

getLastKnownLocation将为您提供从给定提供商处获得的最新位置。它可能为空。您刚刚使用了GPS_PROVIDER,但也可以尝试NETWORK_PROVIDER

mGpsLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
mNetworkLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

通过这种方式,您可以增加获得位置的机会。如果它们都为null然后创建位置请求提供者(抱歉没有魔法,你必须像其他人一样)