1

最終年度のプロジェクト用に距離計算機を作成しました。電卓はユーザーの現在地を表示し、押すと地図上にマーカーを表示する必要があります。ユーザーの現在地からマーカーまでの距離が表示されます。

ユーザーの場所を取得し、コードで使用する変数として保存しましたが、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) 
4

2 に答える 2

5

java.lang.IllegalStateException: System services not available to Activities before onCreate() エラーがスローされます。

これは、フィールド初期化子からActivity、 などから継承されたメソッドを呼び出そうとしているためです。getSystemService()これは機能しません。のようなメソッドを呼び出す前に、onCreate()まで、通常は後まで待つ必要があります。super.onCreate()getSystemService()

コードを最初から onCreate() メソッドに配置しようとしましたが、これも機能しません。

このサンプル アプリでは、フラグメントのLocationManagerinを取得します。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_LOCATIONGPS_PROVIDERNETWORK_PROVIDER

Android 6.0+ でtargetSdkVersion23 以上の場合、これらのパーミッションは であるため、ランタイム パーミッションを実装する必要がありますdangerous

于 2016-03-22T15:42:26.423 に答える
0

コンストラクターでコンテキストとサービスを取得しようとします。これは間違っています。コンストラクターは、オブジェクトが作成されたとき、Android フレームワークにアタッチされる前に実行されます。

メンバーの初期化をonCreate()に移動するだけです。

于 2016-03-22T15:42:24.497 に答える