java.lang.IllegalStateException: системные службы недоступны для операций до onCreate() при попытке сохранить местоположение пользователя в качестве переменной

Я создал калькулятор расстояний для моего последнего года проекта. Калькулятор должен отображать текущее местоположение пользователя, а затем отображать маркер на карте при нажатии. Расстояние будет отображаться от текущего местоположения пользователя до маркера.

Я получил местоположение пользователя и сохранил его как переменную, которую я использую в своем коде, но меня сбрасывает java.lang.IllegalStateException: System services not available to Activities before onCreate() ошибка. Я пытался разместить свой код с самого начала в onCreate() метод, но это тоже не работает. Любая помощь будет принята с благодарностью. Я пытался часами заставить его работать, но не повезло. Когда я пытаюсь разместить (LocationManager)getSystemService(Context.LOCATION_SERVICE); в onCreate() это требует разрешения, и я попробовал все.

Вот мой код

package com.example.matthewmcnabb.moyola;

import android.Manifest;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.AsyncTask;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.FragmentActivity;
import android.os.Bundle;
import android.support.v4.content.ContextCompat;
import android.view.View;

import com.google.android.gms.common.api.GoogleApiClient;
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.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.maps.model.Polyline;
import com.google.android.gms.maps.model.PolylineOptions;

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

public class MapsActivity extends FragmentActivity {
    // the Google Map object
    private GoogleMap mMap;
    private LocationManager locationManager;
    private Location mCurrentLocation;

    LocationManager lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
    public Location location = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
    private double longitude = location.getLongitude();
    private double latitude = location.getLatitude();
    private LatLng STARTING_MARKER_POSITION =new LatLng(longitude, latitude);
    private LatLng distanceFrom = STARTING_MARKER_POSITION;

    // line will be drawn at the click event
    private Polyline line=null;

    // A Geocoder can transform a pair of latitude/longitude into a street address and viceversa.
    // We'll use it in the listener
    private static Geocoder geocoder=null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // we set the layout for the Activity
        setContentView(R.layout.activity_maps);

        // the geocoder is instantiated for the first time
        geocoder=new Geocoder(this);

        // if there isn't a map, it will be created
        setUpMapIfNeeded();
    }

    private GoogleMap.OnMapClickListener clickListener=new GoogleMap.OnMapClickListener() {
        @Override
        public void onMapClick(final LatLng pos) {

            // this method is called when the user taps the map

            // if a line already appears, it's removed
            if (line!=null)
                line.remove();

            // a new line is created
            line = mMap.addPolyline(new PolylineOptions()
                    .add(distanceFrom, pos)
                    .width(5) // width of the line
                    .color(Color.RED)); // line color

            // call the converter object for geocoding invocation and distance calculation
            new AddressConverter().execute(distanceFrom, pos);

        }
    };

    @Override
    protected void onResume() {
        super.onResume();

        // the availability of the GoogleMap will be checked before the Activity starts interacting with the user
        setUpMapIfNeeded();
    }

    private void setUpMapIfNeeded() {

        // the map is created only it has not been initialized
        if (mMap == null) {

            // the map is located in the layout
            mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMap();

            // if a map exists, we proceed with initialization
            if (mMap != null) {
                setUpMap();
            }
        }
    }

    // Now it's time to configure the map. We can add markers, shapes, event handlers and so on
    private void setUpMap() {

        // the camera will be positioned according to the new coordinates
        mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(STARTING_MARKER_POSITION, 16));

        // we choose the type of the map: Satellite in this case
        mMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE);

        // markerOptions describes the marker we want to place
        MarkerOptions markerOptions=new MarkerOptions()
                .position(STARTING_MARKER_POSITION)
                .draggable(true);
        // the marker has to be draggable as we'll move it

        // the marker is rendered on the map
        mMap.addMarker(markerOptions);

        // we define the object to invoke when the marker is dragged
        mMap.setOnMarkerDragListener(new GoogleMap.OnMarkerDragListener()
        {
            @Override
            public void onMarkerDragStart(Marker arg0)
            {
                // this method is called when the drag starts
                // the operation we need is the cancellation of a preexisting line
                if (line!=null)
                    line.remove();
            }
            @Override
            public void onMarkerDragEnd(final Marker pos)
            {
                // we get the final position of the marker
                distanceFrom=pos.getPosition();

            }

            @Override
            public void onMarkerDrag(Marker arg0)
            {
                // operations performed during the movement. Nothing to do
            }
        });

        // the callback to invoke is set
        mMap.setOnMapClickListener(clickListener);
    }

    // we want to know which address corresponds to this location
    // we use AsyncTask to perform slower operations on a separate thread
    private class AddressConverter extends AsyncTask<LatLng,Void,String>
    {
        // The ProgressDialog window we'll show during the calculation
        private ProgressDialog progress=null;

        // this method is called before the background job starts. It works on the main thread
        @Override
        protected void onPreExecute() {

            // ProgressDialog is shown
            progress= ProgressDialog.show(MapsActivity.this,"Distance calculator","We are calcultating the distance...", true,false);
        }

        // this method works on a separate thread
        // it performs geocoding operations to retrieve the address of the points and calculates the distance in meters between them
        @Override
        protected String doInBackground(LatLng... params) {

            float[] distance=new float[1];
            try {
                // the Location class contains what we need to calculate distances

                Location.distanceBetween(params[0].latitude,params[0].longitude,params[1].latitude,params[1].longitude,distance);

                // geocoding operations
                List<Address> fromResult=geocoder.getFromLocation(params[0].latitude,params[0].longitude,1);
                List<Address> toResult=geocoder.getFromLocation(params[1].latitude,params[1].longitude,1);

                // the message informs the user about the distance from the marker to the point selected with the click
                // if we have got both the addresses, we use them to compose the message, otherwise we show only the distance
                if (fromResult.size()>0 && toResult.size()>0)
                {
                    return "The distance is " + Math.round(distance[0]) + " meters";
                }
                else
                    return "The distance is " + Math.round(distance[0]) + " meters";

            }
            catch (IOException e) {
                return "The distance is " + Math.round(distance[0]) + " meters";
            }
        }

        @Override
        protected void onPostExecute(String message)
        {
            if (progress!=null)
                progress.dismiss();

            // The builder of the window is instantiated
            AlertDialog.Builder builder=new AlertDialog.Builder(MapsActivity.this);
            builder.setTitle("Distance");
            builder.setMessage(message);

            // the Alert dialog appears
            builder.show();
        }
    }

    // this method only formats the message with addresses
    private String getAddressDescription(Address a)
    {
        String city=a.getLocality();
        String address=a.getAddressLine(0);

        return "'"+address+"' ("+city+")";

    }
}

Ошибка брошена

FATAL EXCEPTION: main
  Process: com.example.matthewmcnabb.moyola, PID: 27349
  java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.example.matthewmcnabb.moyola/com.example.matthewmcnabb.moyola.MapsActivity}: java.lang.IllegalStateException: System services not available to Activities before onCreate()
      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2515)
      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2723)
      at android.app.ActivityThread.access$900(ActivityThread.java:172)
      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1422)
      at android.os.Handler.dispatchMessage(Handler.java:102)
      at android.os.Looper.loop(Looper.java:145)
      at android.app.ActivityThread.main(ActivityThread.java:5832)
      at java.lang.reflect.Method.invoke(Native Method)
      at java.lang.reflect.Method.invoke(Method.java:372)
      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
   Caused by: java.lang.IllegalStateException: System services not available to Activities before onCreate()
      at android.app.Activity.getSystemService(Activity.java:5259)
      at com.example.matthewmcnabb.moyola.MapsActivity.<init>(MapsActivity.java:51)
      at java.lang.reflect.Constructor.newInstance(Native Method)
      at java.lang.Class.newInstance(Class.java:1650)
      at android.app.Instrumentation.newActivity(Instrumentation.java:1079)
      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2505)
      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2723) 
      at android.app.ActivityThread.access$900(ActivityThread.java:172) 
      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1422) 
      at android.os.Handler.dispatchMessage(Handler.java:102) 
      at android.os.Looper.loop(Looper.java:145) 
      at android.app.ActivityThread.main(ActivityThread.java:5832) 
      at java.lang.reflect.Method.invoke(Native Method) 
      at java.lang.reflect.Method.invoke(Method.java:372) 
      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399) 
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194) 

2 ответа

Я получаю с java.lang.IllegalStateException: системные службы не доступны для операций до ошибки onCreate().

Это потому, что вы пытаетесь вызвать методы, унаследованные от Activity, лайк getSystemService()из поля инициализатора. Это не будет работать. Вам нужно подождать, пока onCreate()и обычно до super.onCreate()перед вызовом таких методов, как getSystemService(),

Я пытался поместить свой код с самого начала в метод onCreate(), но это тоже не работает.

В этом примере приложения я получаю LocationManager в onCreate() фрагмента:

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setRetainInstance(true);

    template=getActivity().getString(R.string.url);
    mgr=
        (LocationManager)getActivity().getSystemService(Context.LOCATION_SERVICE);
  }

Тот же принцип будет onCreate() деятельности.

Когда я пытаюсь разместить (LocationManager)getSystemService(Context.LOCATION_SERVICE); в onCreate() требуется разрешение

Вам нужно иметь <uses-permission> элемент в манифесте для ACCESS_FINE_LOCATION или же ACCESS_COARSE_LOCATIONв зависимости от того, планируете ли вы использовать GPS_PROVIDER или же NETWORK_PROVIDER,

На Android 6.0+, если ваш targetSdkVersion 23 или выше, вам нужно реализовать разрешения во время выполнения, так как эти разрешения dangerous,

Вы пытаетесь получить контексты и сервисы в конструкторе. Это не верно. Конструктор выполняется при создании объекта до его присоединения к платформе Android.

Просто переместите инициализацию члена в onCreate ().

Другие вопросы по тегам