LocationServices.FusedLocationApi.requestLocationUpdates从不调用onLocationChanged

时间:2017-07-04 20:00:39

标签: android google-maps location

Android新手,所以提前道歉。

我正在尝试使用位置请求检索用户的位置。我正在使用SDK 25,我相信这意味着我必须在运行时请求权限。

模拟器在快速,连接良好的机器上运行时按预期工作(即收集位置信息),但是当我在弱wifi上使用实际设备或较慢的笔记本电脑时,onLocationChanged似乎永远不会被调用。我不清楚为什么。

类似的帖子在我的案例中没有产生有用的见解。

我创建了一个简单的示例,可以重现问题here。我正在使用的仿真器是运行Android 7.1.1的Nexus5X API 25 x86。

我的清单文件如下:

<?xml version="1.0" encoding="utf-8"?>

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />


<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

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

我的gradle文件:

    apply plugin: 'com.android.application'

android {
    compileSdkVersion 25
    buildToolsVersion '25.0.3'
    defaultConfig {
        applicationId "com.epicodus.so_locationtest"
        minSdkVersion 15
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:25.3.1'
    compile 'com.android.support.constraint:constraint-layout:1.0.2'
    testCompile 'junit:junit:4.12'
    compile 'com.google.android.gms:play-services-maps:10.0.0'
    compile 'com.google.android.gms:play-services-location:10.0.0'
    compile 'com.google.android.gms:play-services-auth:10.0.0'
    compile 'com.google.firebase:firebase-auth:10.0.1'
    compile 'com.android.support:design:25.3.1'
    compile 'com.android.support.constraint:constraint-layout:1.0.2'
    compile 'com.jakewharton:butterknife:7.0.1'
    compile 'com.google.firebase:firebase-database:10.0.1'
    compile 'com.firebaseui:firebase-ui-database:0.4.1'
    compile 'com.google.firebase:firebase-messaging:10.0.1'
    testCompile 'junit:junit:4.12'
    compile 'com.squareup.picasso:picasso:2.5.2'
    compile 'com.squareup.okhttp3:okhttp:3.2.0'

}

我的活动(见下文)。想法是在位置服务失败时使用谷歌地图API调用。我知道getCityFromHttpCall是不完整的。我想知道在谷歌地图api呼叫中投入更多精力之前,我可以改进位置服务中的某些内容。我有一堆Log.d语句帮助我追踪到LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);行。我相信onLocationChanged应该是回调,但它似乎永远不会被调用。

package com.epicodus.so_locationtest;

import android.Manifest;
import android.content.IntentSender;
import android.content.pm.PackageManager;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.util.Log;
import android.support.v7.app.AppCompatActivity;
import com.epicodus.so_locationtest.Services.GeoCodingService;
import com.firebase.ui.database.FirebaseRecyclerAdapter;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.database.Query;

import org.json.JSONException;

import java.io.IOException;
import java.util.List;
import java.util.Locale;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;

public class MainActivity extends AppCompatActivity
        implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {

    private final static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;
    private static final int MY_PERMISSIONS_REQUEST_FINE_LOCATION = 111;

    private GoogleApiClient mGoogleApiClient;
    private LocationRequest mLocationRequest;
    private String city;
    private Query swarmReportQuery;
    private FirebaseRecyclerAdapter mFirebaseAdapter;
    private Double currenLatitude;
    private Double currentLongitude;
    private String userName;
    private String userId;
    private FirebaseAuth auth;
    private FirebaseAuth.AuthStateListener authListener;

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

        setUpBlankAdapter();

        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
        mLocationRequest = LocationRequest.create()
                .setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY)
                .setInterval(10 * 1000)
                .setFastestInterval(1 * 1000);
    }

    @Override
    public void onConnected(@Nullable Bundle bundle) {
        Log.d("personal", "got into onConnected");
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, MY_PERMISSIONS_REQUEST_FINE_LOCATION);
            return;
        }
        Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
        if (location == null) {
            Log.d("personal", "location null");
            LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
        } else {
            Log.d("personal", "location not null");
            handleNewLocation(location);
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        Log.d("personal", "got into permissionResults");
        Log.d("personal", "request code is " + Integer.toString(requestCode) );
        switch (requestCode) {
            case MY_PERMISSIONS_REQUEST_FINE_LOCATION: {
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    Log.d("personal", "permission was granted");
                    Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
                    if (location == null) {
                        Log.d("personal", "location is null inside permission");
                        LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
                    } else {
                        Log.d("personal", "about to call new location");
                        handleNewLocation(location);
                    }
                }
            }
        }
    }

    private void handleNewLocation(Location location) {
        Log.d("personal", "got to new location");
        currenLatitude = location.getLatitude();
        currentLongitude = location.getLongitude();

        Geocoder gcd = new Geocoder(MainActivity.this, Locale.getDefault());
        try {
            List<Address> addresses = gcd.getFromLocation(currenLatitude, currentLongitude, 1);
            if (addresses.size() > 0) {
                city = addresses.get(0).getLocality() + ", " + addresses.get(0).getAdminArea();

                if (currenLatitude != null && currentLongitude != null) {
                    Log.d("personal", "Got lat and long");
                    setUpFirebaseAdapter(city);
                }
            } else {
                city = "unknown";
                Log.d("personal", "couldnt' get an address from the location");
            }
        } catch (IOException e) {
            Log.d("personal", "getFromLocation didn't work");
            e.printStackTrace();
            getCityFromHttpCall();

        }

    }

    public void getCityFromHttpCall() {
        if (currenLatitude != null && currentLongitude != null) {
            final GeoCodingService geoCodingService = new GeoCodingService();
            geoCodingService.getCity(Double.toString(currenLatitude), Double.toString(currentLongitude), new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    e.printStackTrace();
                }

                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    try {
                        String jsonData = response.body().string();
                        Log.d("personal", jsonData);
                        if (response.isSuccessful()) {
                            city = GeoCodingService.processResults(jsonData);
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                        Log.d("personal", "IO exception");
                        city = "all";
                    } catch (JSONException e) {
                        Log.d("personal", "JSON exception");
                        city = "all";
                    }
                    setUpFirebaseAdapter(city);
                }
            });
        }
    }


    private void setUpFirebaseAdapter(final String city) {
        Log.d("personal", "got to setUpFirebaseAdapter");
    }

    private void setUpBlankAdapter() {
        Log.d("personal", "setUpBlankAdapter done");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mFirebaseAdapter != null) {
            mFirebaseAdapter.cleanup();
        }

    }

    @Override
    public void onConnectionSuspended(int i) {
        Log.d("personal", "Location services suspended. Please reconnect");

    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
        if (connectionResult.hasResolution()) {
            try {
                connectionResult.startResolutionForResult(this, CONNECTION_FAILURE_RESOLUTION_REQUEST);
            } catch (IntentSender.SendIntentException e) {
                e.printStackTrace();
            }
        } else {
            Log.d("personal", "Location services failed with code " + connectionResult.getErrorCode());
        }
    }


    @Override
    public void onStart() {
        super.onStart();
        mGoogleApiClient.connect();
    }

    @Override
    public void onStop() {
        super.onStop();
        if (mGoogleApiClient.isConnected()) {
            LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
            mGoogleApiClient.disconnect();
        }
    }

    @Override
    public void onLocationChanged(Location location) {
        Log.d("personal", "location changed");
        handleNewLocation(location);
    }

}

非常感谢您提供任何帮助,请让我知道如何更好地为此提供帮助。

1 个答案:

答案 0 :(得分:0)

确保在没有调用onLocationChanged()的设备上连接GoogleApiClient(检查日志)。