2017-07-04 16 views
0

Androidに新しく、事前にお詫び申し上げます。LocationServices.FusedLocationApi.requestLocationUpdatesはonLocationChangedを一度も呼び出しません。

ロケーションリクエストを使用してユーザーのロケーションを取得しようとしています。私はSDK25を使用しています。これは、実行時に許可を要求する必要があると考えています。

エミュレータは、高速で接続されたマシン上で実行されているときに期待どおりに動作します(つまり、位置情報を収集します)が、実際のデバイスを使用しているときに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' 

} 

そして、私の活動(下記参照します)。ロケーションサービスが失敗した場合、GoogleマップAPIコールを使用するというアイディアでした。私はgetCityFromHttpCallが不完全であることを認識しています。私は、位置情報サービスにGoogle MAP API呼び出しでより多くのエネルギーを投入する前に改善できるものがあるかどうかを確認したいと思います。私には、LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);という行をトレースするのに役立つLog.d文がたくさんあります。私は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

Wi-Fiとモバイルネットワークロケーションを有効にする必要があります。 – rafsanahmad007

+0

PRIORITY_HIGH_ACCURACYを使用すると、そうではありませんか? – Atticus29

+0

は[Docs](https://developers.google.com/android/reference/com/google/android/gms/location/LocationRequest#PRIORITY_HIGH_ACCURACY) – rafsanahmad007

答えて

0

onLocationChanged()が呼び出されていない(ログを確認する)デバイスにGoogleApiClientが接続されていることを確認してください。 `PRIORITY_BALANCED_POWER_ACCURACY`のために

関連する問題