2

ユーザーの現在の位置を取得し、Google マップを読み込んで、その地域に関心のあるマーカーをプロットするアプリがあります。マシュマロ以下のすべてで問題なく動作します。実行時のアクセス許可チェックを追加しました。プロンプトが表示されると設定されます。同意すると、電話の設定からアプリの詳細にアクセス許可が表示されます。しかし、なぜ場所が返ってこないのか、一生理解できません。

ここにある例を使用しています https://developer.android.com/training/location/retrieve-current.html

マニフェストのタグですべての権限が設定されています。Fragment に LocationListener を実装することさえあります。ただし、onLocationChanged メソッドが呼び出されることはありません。以下のように、Google API Client の onConnected メソッド内で呼び出しています。

@Override
    public void onConnected(@Nullable Bundle bundle) {
        try {
            Log.d("MYAPPTAG","isConnected: " + mGoogleApiClient.isConnected());
            LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
            myLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
        } catch (SecurityException ex) {
            myLocation = null;
        }
    }

ログをコンソールに取得するため、onConnected メソッドが呼び出されます。ただし、 myLocation は常に null です。getLastLocation を呼び出すたびに、コンソールにメッセージが表示されます。

No Location to return for getLastLocation()
GoogleSignatureVerifier: com.myappname.android signature not valid.  Found: LONG KEY HERE

マシュマロで何か特別なことをする必要がありますか?

私の OnLocationChanged メソッド

@Override
    public void onLocationChanged(Location location) {
        myLocation = location;
        Log.d("MYAPPTAG", "LocatinChngListner, loc: " + location.getLatitude() + "," + location.getLongitude());     
    }

AndroidManifest.xml - 権限セクション (ノードの上)

<!--- App permissions -->
    <permission android:name="com.myappname.android.permission.MAPS_RECEIVE" android:protectionLevel="signature"/>
    <uses-permission android:name="com.myappname.android.permission.MAPS_RECEIVE"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.GET_ACCOUNTS"/>
    <uses-permission android:name="android.permission.CALL_PHONE"/>
    <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
    <uses-permission android:name="android.permission.WRITE_CONTACTS" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

    <permission android:name="com.myappname.android.permission.C2D_MESSAGE" android:protectionLevel="signature" />
    <uses-permission android:name="com.myappname.android.permission.C2D_MESSAGE"/>

onCreate メソッド スニペット

createLocationRequest();
        if (mGoogleApiClient == null) {
            mGoogleApiClient = new GoogleApiClient.Builder(getActivity())
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
        }

createLocationRequest メソッド

private void createLocationRequest(){
        mLocationRequest = LocationRequest.create();
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        mLocationRequest.setInterval(5000);
        mLocationRequest.setFastestInterval(1000);
    }

onStart() onStop() メソッド

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

@Override    
public void onStop() {
        if (mGoogleApiClient.isConnected()) mGoogleApiClient.disconnect();
        super.onStop();
    }

Fragment onCreate メソッドの直後に、以下のこのコードを呼び出します

if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1 && (ContextCompat.checkSelfPermission(getActivity(), android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)) {
            requestPermissions(new String[] { Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION }, REQUEST_PERMISSION_USER_LOCATION);
        } else {
            googleMapsLocationPermissionContainer.setVisibility(View.GONE);
            getUserLocationAndInitializeMap();
        }

googleMapsLocationPermissionContainer は、アクセス許可が付与されるまでマップ上にオーバーレイする単なるレイアウトです。

getUserLocationAndInitializeMap()

try {
                MapsInitializer.initialize(getActivity());
                // Set reference for map object
                if (map == null) {
                    mapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.map);
                    mapFragment.getMapAsync(this);
// Here I set the map to invisible then after I plot all the markers I set it to visible again

                    mapFragment.getView().setVisibility(View.INVISIBLE);
                }
            } catch (Exception e) {
                // Show the google maps alert dialog
                showGoogleMapsErrorDialog();
            }
4

1 に答える 1

1

これに対する私のアプローチは次のとおりです。

@Override
public void onResume() {
    super.onResume();
    initGpsTracker();
}

public synchronized void initGpsTracker() {
    if (mMap != null) {
        try {
            checkIfPermissionAllowedForLocation();
        } catch (SecurityException secex) {
            Toast.makeText(getActivity(), "not enabled in manifest", Toast.LENGTH_SHORT).show();
        }
    }
}

/**
 * rule is the following. First we check if the permissions are there. If not, we check if we can enable or not.
 * If the permissions are check if gps is enabled.
 */
private void checkIfPermissionAllowedForLocation() {

    //if permissions are set then we go to else, check for gps
    if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        // Request missing location permission.
        if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION)) {
            askIfToRequestPermissions();
        } else {
            requestPermissions();
        }
    } else {
        // Location permission has been granted, continue as usual.
        if (!isGpsProviderEnabled()) {
            askToEnableGPS();
        } else {
            mMap.setMyLocationEnabled(true);
        }
    }
}


private void askToEnableGPS() {
    CustomFragmentDialog customFragmentDialog = CustomFragmentDialog.newInstance(getString(R.string.enable_gps_title),
            getString(R.string.enable_gps_message),
            getString(R.string.ok),
            getString(R.string.cancel),
            callback);
    customFragmentDialog.show(getFragmentManager(), CUSTOM_TAG);
}

private void requestPermissions() {
    ActivityCompat.requestPermissions(getActivity(),
            new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
            REQUEST_CODE_LOCATION);
}

private void enableGPS() {
    if (enableLocationService != null) {
        enableLocationService.askToEnableGps(locationCallback);
    }
}

private GoogleAskToEnableLocationService.GpsCallback locationCallback = new GoogleAskToEnableLocationService.GpsCallback() {
    @Override
    public void onSuccess() {
        initGpsTracker();
    }

    @Override
    public void onResolutionRequired(Status status) {
        try {
            status.startResolutionForResult(getActivity(), CONNECTION_RESOLUTION_CODE);
        } catch (IntentSender.SendIntentException setex) {
            Toast.makeText(getActivity(), "Exception in sending intent:", Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public void onError() {
        Toast.makeText(getActivity(), "Location services unavailable!", Toast.LENGTH_SHORT).show();
    }
};

private void askIfToRequestPermissions() {
    CustomFragmentDialog customFragmentDialog = CustomFragmentDialog.newInstance(getString(R.string.enable_gps_title),
            getString(R.string.enable_permissions_message),
            getString(R.string.ok),
            getString(R.string.cancel),
            callback_permissions);
    customFragmentDialog.show(getFragmentManager(), CUSTOM_TAG);
}

private CustomFragmentDialog.Callback callback = new CustomFragmentDialog.Callback() {
    @Override
    public void onPositiveButtonClicked(Bundle bundle) {
        enableGPS();
    }

    @Override
    public void onNegativeButtonClicked(Bundle bundle) {

    }
};


private CustomFragmentDialog.Callback callback_permissions = new CustomFragmentDialog.Callback() {
    @Override
    public void onPositiveButtonClicked(Bundle bundle) {
        requestPermissions();
    }

    @Override
    public void onNegativeButtonClicked(Bundle bundle) {

    }
};

 private boolean isGpsProviderEnabled() {
    return googleUtils.isGpsProviderEnabled();
 }
 //inside it is a normal check if locationManager  can access
 //the gps provider
  if (locationManager.getProvider(provider) == null) {
      return false;
  }

現在、リクエスト許可のためにいくつかのコールバックがあります:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
        case CONNECTION_RESOLUTION_CODE:
            switch (resultCode) {
                case Activity.RESULT_OK:
                    initGpsTracker();
                    break;
                case Activity.RESULT_CANCELED:
                    Toast.makeText(getContext(), "Gps not enabled:", Toast.LENGTH_SHORT).show();
                    break;
                default:
                    break;
            }
            break;
    }
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    if (requestCode == REQUEST_CODE_LOCATION) {
        if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            initGpsTracker();
        } else {
            Toast.makeText(getActivity(), "Manifest permission, not enabled", Toast.LENGTH_SHORT).show();

        }
    }
}

さて、最後に場所のリクエストを処理するクラスなので、設定に移動する必要はありません:

 public void askToEnableGps(final GpsCallback callback) {
    if (locationClient == null) {
        return;
    }
    mLocationRequestHighAccuracy = LocationRequest.create();
    mLocationRequestHighAccuracy.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    mLocationRequestHighAccuracy.setInterval(30 * 1000);
    mLocationRequestHighAccuracy.setFastestInterval(5 * 1000);
    LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
            .addLocationRequest(mLocationRequestHighAccuracy);
    builder.setAlwaysShow(true);
    PendingResult<LocationSettingsResult> result =
            LocationServices.SettingsApi.checkLocationSettings(locationClient, builder.build());

    result.setResultCallback(getResultCallback(callback));
}

private ResultCallback<LocationSettingsResult> getResultCallback(final GpsCallback callback) {

    return new ResultCallback<LocationSettingsResult>() {
        @Override
        public void onResult(LocationSettingsResult result) {
            if (result != null) {
                final Status status = result.getStatus();
                if (callback != null) {
                    //final LocationSettingsStates statesResult = result.getLocationSettingsStates();
                    switch (status.getStatusCode()) {
                        case LocationSettingsStatusCodes.SUCCESS:
                            // All location settings are satisfied. The client can initialize location
                            // requests here.
                            callback.onSuccess();
                            break;
                        case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                            // Location settings are not satisfied. But could be fixed by showing the user
                            // a dialog.
                            callback.onResolutionRequired(status);
                            break;
                        case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
                            // Location settings are not satisfied. However, we have no way to fix the
                            // settings so we won't show the dialog.
                            callback.onError();
                            break;
                    }
                }
            }
        }
    };
}

public interface GpsCallback {
    /**
     * callback method for when the result it is a success.
     */
    void onSuccess();

    /**
     * callback for when user interaction it is required.
     *
     * @param status the result from the service needed for the resolution.
     */
    void onResolutionRequired(Status status);

    /**
     * Callback for when the change it is not possible.
     */
    void onError();
}
于 2016-07-28T19:00:00.223 に答える