您好,我正在开发一个 Android 应用程序,我需要用户通过移动帕克来选择一个位置,以便我可以获得我需要的信息 exactly like this但在安卓应用程序中。 我做了一些研究,但我还是新手,所以我找不到任何接近这个的东西。 谁能指出我正确的方向?
我需要做的是在一个简单的谷歌地图中创建一个可以给我 long+lat 数据的移动光标。我所能做的就是在我的 map 中放置一些静态位置。
最佳答案
你看起来像下面的图片吗..
在这里,如果我们在 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/