android - Google Maps android通过在 map 中移动标记来获取经纬度

标签 android google-maps google-maps-api-2 google-geocoder

您好,我正在开发一个 Android 应用程序,我需要用户通过移动帕克来选择一个位置,以便我可以获得我需要的信息 exactly like this但在安卓应用程序中。 我做了一些研究,但我还是新手,所以我找不到任何接近这个的东西。 谁能指出我正确的方向?

我需要做的是在一个简单的谷歌地图中创建一个可以给我 long+lat 数据的移动光标。我所能做的就是在我的 map 中放置一些静态位置。

最佳答案

你看起来像下面的图片吗..

enter image description here

enter image description here

在这里,如果我们在 map 上拖动标记,它会自动更新当前的纬度、经度..

这是带有代码的完整解决方案。

1.) 创建一个类 AppUtils

public class AppUtils {

public class LocationConstants {
    public static final int SUCCESS_RESULT = 0;

    public static final int FAILURE_RESULT = 1;

    public static final String PACKAGE_NAME = "your package name";

    public static final String RECEIVER = PACKAGE_NAME + ".RECEIVER";

    public static final String RESULT_DATA_KEY = PACKAGE_NAME + ".RESULT_DATA_KEY";

    public static final String LOCATION_DATA_EXTRA = PACKAGE_NAME + ".LOCATION_DATA_EXTRA";

    public static final String LOCATION_DATA_AREA = PACKAGE_NAME + ".LOCATION_DATA_AREA";
    public static final String LOCATION_DATA_CITY = PACKAGE_NAME + ".LOCATION_DATA_CITY";
    public static final String LOCATION_DATA_STREET = PACKAGE_NAME + ".LOCATION_DATA_STREET";


}


public static boolean hasLollipop() {
    return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
}

public static boolean isLocationEnabled(Context context) {
    int locationMode = 0;
    String locationProviders;

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        try {
            locationMode = Settings.Secure.getInt(context.getContentResolver(), Settings.Secure.LOCATION_MODE);

        } catch (Settings.SettingNotFoundException e) {
            e.printStackTrace();
        }
        return locationMode != Settings.Secure.LOCATION_MODE_OFF;
    } else {
        locationProviders = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
        return !TextUtils.isEmpty(locationProviders);
    }
}

}

2.) 创建另一个类 FetchAddressIntentService 此类将获取地址并指向用户将要在 Google AutocompleteTextView 上键入的特定位置..

public class FetchAddressIntentService extends IntentService {
private static final String TAG = "FetchAddressIS";

/**
 * The receiver where results are forwarded from this service.
 */
protected ResultReceiver mReceiver;

/**
 * This constructor is required, and calls the super IntentService(String)
 * constructor with the name for a worker thread.
 */
public FetchAddressIntentService() {
    // Use the TAG to name the worker thread.
    super(TAG);
}

/**
 * Tries to get the location address using a Geocoder. If successful, sends an address to a
 * result receiver. If unsuccessful, sends an error message instead.
 * Note: We define a {@link ResultReceiver} in * MainActivity to process content
 * sent from this service.
 * <p>
 * This service calls this method from the default worker thread with the intent that started
 * the service. When this method returns, the service automatically stops.
 */
@Override
protected void onHandleIntent(Intent intent) {
    String errorMessage = "";

    mReceiver = intent.getParcelableExtra(AppUtils.LocationConstants.RECEIVER);

    // Check if receiver was properly registered.
    if (mReceiver == null) {
        Log.wtf(TAG, "No receiver received. There is nowhere to send the results.");
        return;
    }
    // Get the location passed to this service through an extra.
    Location location = intent.getParcelableExtra(AppUtils.LocationConstants.LOCATION_DATA_EXTRA);

    // Make sure that the location data was really sent over through an extra. If it wasn't,
    // send an error error message and return.
    if (location == null) {
        errorMessage = getString(R.string.no_location_data_provided);
        Log.wtf(TAG, errorMessage);
        deliverResultToReceiver(AppUtils.LocationConstants.FAILURE_RESULT, errorMessage, null);
        return;
    }

    // Errors could still arise from using the Geocoder (for example, if there is no
    // connectivity, or if the Geocoder is given illegal location data). Or, the Geocoder may
    // simply not have an address for a location. In all these cases, we communicate with the
    // receiver using a resultCode indicating failure. If an address is found, we use a
    // resultCode indicating success.

    // The Geocoder used in this sample. The Geocoder's responses are localized for the given
    // Locale, which represents a specific geographical or linguistic region. Locales are used
    // to alter the presentation of information such as numbers or dates to suit the conventions
    // in the region they describe.
    Geocoder geocoder = new Geocoder(this, Locale.getDefault());

    // Address found using the Geocoder.
    List<Address> addresses = null;

    try {
        // Using getFromLocation() returns an array of Addresses for the area immediately
        // surrounding the given latitude and longitude. The results are a best guess and are
        // not guaranteed to be accurate.
        addresses = geocoder.getFromLocation(
                location.getLatitude(),
                location.getLongitude(),
                // In this sample, we get just a single address.
                1);
    } catch (IOException ioException) {
        // Catch network or other I/O problems.
        errorMessage = getString(R.string.service_not_available);
        Log.e(TAG, errorMessage, ioException);
    } catch (IllegalArgumentException illegalArgumentException) {
        // Catch invalid latitude or longitude values.
        errorMessage = getString(R.string.invalid_lat_long_used);
        Log.e(TAG, errorMessage + ". " +
                "Latitude = " + location.getLatitude() +
                ", Longitude = " + location.getLongitude(), illegalArgumentException);
    }

    // Handle case where no address was found.
    if (addresses == null || addresses.size() == 0) {
        if (errorMessage.isEmpty()) {
            errorMessage = getString(R.string.no_address_found);
            Log.e(TAG, errorMessage);
        }
        deliverResultToReceiver(AppUtils.LocationConstants.FAILURE_RESULT, errorMessage, null);
    } else {
        Address address = addresses.get(0);
        ArrayList<String> addressFragments = new ArrayList<String>();

        for (int i = 0; i < address.getMaxAddressLineIndex(); i++) {
            addressFragments.add(address.getAddressLine(i));

        }
        deliverResultToReceiver(AppUtils.LocationConstants.SUCCESS_RESULT,
                TextUtils.join(System.getProperty("line.separator"), addressFragments), address);
        //TextUtils.split(TextUtils.join(System.getProperty("line.separator"), addressFragments), System.getProperty("line.separator"));

    }
}

/**
 * Sends a resultCode and message to the receiver.
 */
private void deliverResultToReceiver(int resultCode, String message, Address address) {
    try {
        Bundle bundle = new Bundle();
        bundle.putString(AppUtils.LocationConstants.RESULT_DATA_KEY, message);

        bundle.putString(AppUtils.LocationConstants.LOCATION_DATA_AREA, address.getSubLocality());

        bundle.putString(AppUtils.LocationConstants.LOCATION_DATA_CITY, address.getLocality());
        bundle.putString(AppUtils.LocationConstants.LOCATION_DATA_STREET, address.getAddressLine(0));

        mReceiver.send(resultCode, bundle);
    } catch (Exception e) {
        e.printStackTrace();
    }
}


}

3.) 创建您的MapActivity,我们将在其中显示我们的 map

public class MapsActivity extends AppCompatActivity implements OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, com.google.android.gms.location.LocationListener {

private GoogleMap mMap;
private GoogleApiClient mGoogleApiClient;
private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
private static String TAG = "MAP LOCATION";
Context mContext;
TextView mLocationMarkerText;
public LatLng mCenterLatLong;


/**
 * Receiver registered with this activity to get the response from FetchAddressIntentService.
 */
private AddressResultReceiver mResultReceiver;
/**
 * The formatted location address.
 */
protected String mAddressOutput;
protected String mAreaOutput;
protected String mCityOutput;
protected String mStateOutput;
EditText mLocationAddress;
TextView mLocationText;
private static final int REQUEST_CODE_AUTOCOMPLETE = 1;
Toolbar mToolbar;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_maps);
    mContext = this;
    // Obtain the SupportMapFragment and get notified when the map is ready to be used.
    SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
            .findFragmentById(R.id.map);

    mLocationMarkerText = (TextView) findViewById(R.id.locationMarkertext);
    mLocationAddress = (EditText) findViewById(R.id.Address);  //sss
    mLocationText = (TextView) findViewById(R.id.Locality);    //sss
    mToolbar = (Toolbar) findViewById(R.id.toolbar);           //sss
    setSupportActionBar(mToolbar);
    getSupportActionBar().setDisplayShowHomeEnabled(true);

    getSupportActionBar().setTitle(getResources().getString(R.string.app_name));


    mLocationText.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

            openAutocompleteActivity();

        }


    });
    mapFragment.getMapAsync(this);
    mResultReceiver = new AddressResultReceiver(new Handler());

    if (checkPlayServices()) {

        if (!AppUtils.isLocationEnabled(mContext)) {
            // notify user
            AlertDialog.Builder dialog = new AlertDialog.Builder(mContext);
            dialog.setMessage("Location not enabled!");
            dialog.setPositiveButton("Open location settings", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface paramDialogInterface, int paramInt) {
                    Intent myIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                    startActivity(myIntent);
                }
            });
            dialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {

                @Override
                public void onClick(DialogInterface paramDialogInterface, int paramInt) {
                    // TODO Auto-generated method stub

                }
            });
            dialog.show();
        }
        buildGoogleApiClient();
    } else {
        Toast.makeText(mContext, "Location not supported in this device", Toast.LENGTH_SHORT).show();
    }

}

@Override
public void onMapReady(GoogleMap googleMap) {
    Log.d(TAG, "OnMapReady");
    mMap = googleMap;

    mMap.setOnCameraChangeListener(new GoogleMap.OnCameraChangeListener() {
        @Override
        public void onCameraChange(CameraPosition cameraPosition) {
            Log.d("Camera postion change" + "", cameraPosition + "");
            mCenterLatLong = cameraPosition.target;


            mMap.clear();

            try {

                Location mLocation = new Location("");
                mLocation.setLatitude(mCenterLatLong.latitude);
                mLocation.setLongitude(mCenterLatLong.longitude);

                startIntentService(mLocation);
                mLocationMarkerText.setText("Lat : " + mCenterLatLong.latitude + "," + "Long : " + mCenterLatLong.longitude);

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {

        return;
    }

}

@Override
public void onConnected(Bundle bundle) {
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {

        return;
    }
    Location mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
            mGoogleApiClient);
    if (mLastLocation != null) {
        changeMap(mLastLocation);
        Log.d(TAG, "ON connected");

    } else
        try {
            LocationServices.FusedLocationApi.removeLocationUpdates(
                    mGoogleApiClient, this);

        } catch (Exception e) {
            e.printStackTrace();
        }
    try {
        LocationRequest mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(10000);
        mLocationRequest.setFastestInterval(5000);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        LocationServices.FusedLocationApi.requestLocationUpdates(
                mGoogleApiClient, mLocationRequest, this);

    } catch (Exception e) {
        e.printStackTrace();
    }

}

@Override
public void onConnectionSuspended(int i) {
    Log.i(TAG, "Connection suspended");
    mGoogleApiClient.connect();
}

@Override
public void onLocationChanged(Location location) {
    try {
        if (location != null)
            changeMap(location);
        LocationServices.FusedLocationApi.removeLocationUpdates(
                mGoogleApiClient, this);

    } catch (Exception e) {
        e.printStackTrace();
    }
}

@Override
public void onConnectionFailed(ConnectionResult connectionResult) {

}


protected synchronized void buildGoogleApiClient() {
    mGoogleApiClient = new GoogleApiClient.Builder(this)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .addApi(LocationServices.API)
            .build();
}

@Override
protected void onStart() {
    super.onStart();
    try {
        mGoogleApiClient.connect();

    } catch (Exception e) {
        e.printStackTrace();
    }
}

@Override
protected void onStop() {
    super.onStop();
    try {

    } catch (RuntimeException e) {
        e.printStackTrace();
    }
    if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
        mGoogleApiClient.disconnect();
    }
}

private boolean checkPlayServices() {
    int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
    if (resultCode != ConnectionResult.SUCCESS) {
        if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
            GooglePlayServicesUtil.getErrorDialog(resultCode, this,
                    PLAY_SERVICES_RESOLUTION_REQUEST).show();
        } else {
            //finish();
        }
        return false;
    }
    return true;
}

private void changeMap(Location location) {

    Log.d(TAG, "Reaching map" + mMap);


    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        return;
    }

    // check if map is created successfully or not
    if (mMap != null) {
        mMap.getUiSettings().setZoomControlsEnabled(false);
        LatLng latLong;


        latLong = new LatLng(location.getLatitude(), location.getLongitude());

        CameraPosition cameraPosition = new CameraPosition.Builder()
                .target(latLong).zoom(15).tilt(70).build();

        mMap.setMyLocationEnabled(true);
        mMap.getUiSettings().setMyLocationButtonEnabled(true);
        mMap.animateCamera(CameraUpdateFactory
                .newCameraPosition(cameraPosition));

      mLocationMarkerText.setText("Lat : " + location.getLatitude() + "," + "Long : " + location.getLongitude());
        startIntentService(location);


    } else {
        Toast.makeText(getApplicationContext(),
                "Sorry! unable to create maps", Toast.LENGTH_SHORT)
                .show();
    }

}


/**
 * Receiver for data sent from FetchAddressIntentService.
 */
class AddressResultReceiver extends ResultReceiver {
    public AddressResultReceiver(Handler handler) {
        super(handler);
    }

    /**
     * Receives data sent from
     * FetchAddressIntentService and updates the UI in MainActivity.
     */
    @Override
    protected void onReceiveResult(int resultCode, Bundle resultData) {

        // Display the address string or an error message sent from the intent service.
        mAddressOutput = resultData.getString(AppUtils.LocationConstants.RESULT_DATA_KEY);

        mAreaOutput = resultData.getString(AppUtils.LocationConstants.LOCATION_DATA_AREA);

        mCityOutput = resultData.getString(AppUtils.LocationConstants.LOCATION_DATA_CITY);
        mStateOutput = resultData.getString(AppUtils.LocationConstants.LOCATION_DATA_STREET);

        displayAddressOutput();

        // Show a toast message if an address was found.
        if (resultCode == AppUtils.LocationConstants.SUCCESS_RESULT) {
            //  showToast(getString(R.string.address_found));


        }


    }

}

/**
 * Updates the address in the UI.
 */
protected void displayAddressOutput() {
    //  mLocationAddressTextView.setText(mAddressOutput);
    try {
        if (mAreaOutput != null)
           // mLocationText.setText(mAreaOutput+ "");

        mLocationAddress.setText(mAddressOutput);
        //mLocationText.setText(mAreaOutput);

    } catch (Exception e) {
        e.printStackTrace();
    }
}

/**
 * Creates an intent, adds location data to it as an extra, and starts the intent service for
 * fetching an address.
 */
protected void startIntentService(Location mLocation) {
    // Create an intent for passing to the intent service responsible for fetching the address.
    Intent intent = new Intent(this, FetchAddressIntentService.class);

    // Pass the result receiver as an extra to the service.
    intent.putExtra(AppUtils.LocationConstants.RECEIVER, mResultReceiver);

    // Pass the location data as an extra to the service.
    intent.putExtra(AppUtils.LocationConstants.LOCATION_DATA_EXTRA, mLocation);

    // Start the service. If the service isn't already running, it is instantiated and started
    // (creating a process for it if needed); if it is running then it remains running. The
    // service kills itself automatically once all intents are processed.
    startService(intent);
}


private void openAutocompleteActivity() {
    try {
        // The autocomplete activity requires Google Play Services to be available. The intent
        // builder checks this and throws an exception if it is not the case.
        Intent intent = new PlaceAutocomplete.IntentBuilder(PlaceAutocomplete.MODE_FULLSCREEN)
                .build(this);
        startActivityForResult(intent, REQUEST_CODE_AUTOCOMPLETE);
    } catch (GooglePlayServicesRepairableException e) {
        // Indicates that Google Play Services is either not installed or not up to date. Prompt
        // the user to correct the issue.
        GoogleApiAvailability.getInstance().getErrorDialog(this, e.getConnectionStatusCode(),
                0 /* requestCode */).show();
    } catch (GooglePlayServicesNotAvailableException e) {
        // Indicates that Google Play Services is not available and the problem is not easily
        // resolvable.
        String message = "Google Play Services is not available: " +
                GoogleApiAvailability.getInstance().getErrorString(e.errorCode);

        Toast.makeText(mContext, message, Toast.LENGTH_SHORT).show();
    }
}

/**
 * Called after the autocomplete activity has finished to return its result.
 */
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    // Check that the result was from the autocomplete widget.
    if (requestCode == REQUEST_CODE_AUTOCOMPLETE) {
        if (resultCode == RESULT_OK) {
            // Get the user's selected place from the Intent.
            Place place = PlaceAutocomplete.getPlace(mContext, data);

            // TODO call location based filter


            LatLng latLong;


            latLong = place.getLatLng();

            //mLocationText.setText(place.getName() + "");

            CameraPosition cameraPosition = new CameraPosition.Builder()
                    .target(latLong).zoom(15).tilt(70).build();

            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                // TODO: Consider calling

                return;
            }
            mMap.setMyLocationEnabled(true);
            mMap.animateCamera(CameraUpdateFactory
                    .newCameraPosition(cameraPosition));


        }


    } else if (resultCode == PlaceAutocomplete.RESULT_ERROR) {
        Status status = PlaceAutocomplete.getStatus(mContext, data);
    } else if (resultCode == RESULT_CANCELED) {
        // Indicates that the activity closed before a selection was made. For example if
        // the user pressed the back button.
    }
}

4.) list 的变化 提供所有必要的互联网权限。

不要忘记添加这两个东西

    <meta-data
        android:name="com.google.android.geo.API_KEY"
        android:value="Your google map api key" />

和,

      <service
        android:name=".FetchAddressIntentService"
        android:exported="false" />

就是这样,您已经完成了代码部分!! 运行它..

关于android - Google Maps android通过在 map 中移动标记来获取经纬度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23765372/

相关文章:

java - Android Google Maps API v2 的问题(

android - 如何在自定义复选框 View 上保留支持库复选框的样式?

Android:捕获应用程序退出

javascript - 在事件内使用 $scope - 谷歌地图 api

android - Google Maps Android API v2 应用程序崩溃

安卓地理围栏限制

android - android map v2中的自定义信息窗口

android - 如何将媒体查询数据添加到特定填充?

android - 防止 greenDAO 插入重复条目

android - 如何在 Google Maps Android API V2 中将当前位置显示为箭头?