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);
}
}
非常感谢您提供任何帮助,请让我知道如何更好地为此提供帮助。
答案 0 :(得分:0)
确保在没有调用onLocationChanged()的设备上连接GoogleApiClient(检查日志)。