I have a strange problem and really dont know where to start debug. I have 2 activities one that holds a googlemap view and when the user taps the marker on the view i start a new activity that shows a detailed description of that marker. If i hit the back buttton on my detalied activity it returns me to the map activity, so far so good. BUT if i tap a new (or same) marker i get to the detailed activity again (all fine) if i try to hit the back button again i get returned to the detailed activity that i tapped the very first time, and i can hit back once more and finaly get to the map activity again.
if i keep debugggin i can get up to 10 activities that i have to push back on before i finaly get to the map activity again
what the heck is going on ? does android forget history or something due to i implement the map activity instead of activity ?
anyone that has an idea of where to start looking for the problem
Here comes a lot of code:
map activity
public class SpotGuideMapActivity extends MapActivity
{
protected MapView mapView;
protected MapController mapController;
protected List<Overlay> mapOverlays;
protected Drawable overlayIcon;
protected SpotGuideOverlay spotsOverlay;
protected MyLocationOverlay myLocOverlay;
protected ArrayList<SpotItem> _spots;
protected Button ButtonHome;
protected Button ButtonPreferences;
protected Intent _intent = null;
private SpotGuideDbAdapter _spotDbAdapter;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.spot_map);
_intent = getIntent();
ActivityHelper.createInstance(this).setTopBarTitle("Spot kortet");
ButtonPreferences = (Button)findViewById(R.id.btnPreferences);
ButtonPreferences.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
startActivity(new Intent(getApplicationContext(), GlobalPreferencesActivity.class));
overridePendingTransition(R.anim.slide_right_in,R.anim.slide_right_out);
}
});
ButtonHome = (Button)findViewById(R.id.btnHome);
ButtonHome.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
startActivity(new Intent(getApplicationContext(), HomeActivity.class));
overridePendingTransition(R.anim.slide_left_in,R.anim.slide_left_out);
}
});
//mapView.invalidate();
}
#Override
protected void onResume()
{
super.onResume();
if(_intent.hasExtra("latitude") && _intent.hasExtra("longitude"))
{
String latitude = _intent.getStringExtra("latitude");
String longitude = _intent.getStringExtra("longitude");
double lat = Double.parseDouble(latitude);
double lon = Double.parseDouble(longitude);
GeoPoint point = new GeoPoint((int)(lat * 1E6) , (int)(lon * 1E6));
initMapView(point);
}
else
{
initMapView(null);
}
drawSpotMarkers();
}
#Override
protected void onPause()
{
super.onPause();
myLocOverlay.disableCompass();
myLocOverlay.disableMyLocation();
}
protected void initMapView(GeoPoint centerPoint)
{
mapView = (MapView)findViewById(R.id.spotGuideMap);
mapView.setBuiltInZoomControls(true);
mapController = mapView.getController();
//current location overlayer
myLocOverlay = new MyLocationOverlay(this, mapView);
myLocOverlay.enableCompass();
myLocOverlay.enableMyLocation();
mapView.getOverlays().add(myLocOverlay);
GeoPoint point = null;
if(centerPoint == null)
{
point = myLocOverlay.getMyLocation();
if(point == null)
{
point = new GeoPoint((int)(55.5616508394963 * 1E6) , (int)(12.563638687133789 * 1E6));
}
}
else
{
point = centerPoint;
}
//get the last know location, be fresh so use last fix
//Location location = myLocOverlay.getLastFix();
//GeoPoint locationPoint;
//locationPoint = new GeoPoint((int)(location.getLatitude() * 1E6) , (int)(location.getLongitude() * 1E6));
mapController.animateTo(point);
mapController.setZoom(10);
}
protected void drawSpotMarkers()
{
mapOverlays = mapView.getOverlays();
overlayIcon = getResources().getDrawable(R.drawable.map_icon_pink);
spotsOverlay = new SpotGuideOverlay(overlayIcon, this);
_spotDbAdapter = new SpotGuideDbAdapter(this).Open();
_spots = _spotDbAdapter.getAllSpots();
for (SpotItem spot : _spots)
{
double lat = Double.parseDouble(spot.getLatitude());
double lon = Double.parseDouble(spot.getLongitude());
GeoPoint point = new GeoPoint((int)(lat * 1E6) , (int)(lon * 1E6));
OverlayItem overlayitem = new OverlayItem(point, spot.getSpotTitle(), Integer.toString(spot.getId()));
spotsOverlay.addOverlay(overlayitem);
}
mapOverlays.add(spotsOverlay);
}
#Override
protected boolean isRouteDisplayed()
{
return false;
}
}
detailed activity
public class SpotGuideDescriptionActivity extends BaseActivity
{
private SpotGuideDbAdapter _spotDbAdapter;
protected Button ButtonHome;
protected Button ButtonPreferences;
protected Button ButtonBacktoMap;
protected TextView tvSpotTitle;
protected TextView tvSpotType;
protected TextView tvWindDirection;
protected TextView tvContent;
protected Intent _intent = null;
protected SpotItem item;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.spot_description);
_intent = getIntent();
this.getActivityHelper().setTopBarTitle("Spot beskrivelse");
tvSpotTitle = (TextView)findViewById(R.id.spotDescTitle);
tvSpotType = (TextView)findViewById(R.id.spotDescType);
tvWindDirection = (TextView)findViewById(R.id.spotDescWind);
tvContent = (TextView)findViewById(R.id.spotDescContent);
ButtonBacktoMap = (Button)findViewById(R.id.btnBackToMap);
ButtonBacktoMap.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
Intent intent = new Intent(getApplicationContext(), SpotGuideMapActivity.class);
intent.putExtra("latitude", item.getLatitude());
intent.putExtra("longitude", item.getLongitude());
startActivity(intent);
overridePendingTransition(R.anim.slide_left_in,R.anim.slide_left_out);
}
});
ButtonPreferences = (Button)findViewById(R.id.btnPreferences);
ButtonPreferences.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
startActivity(new Intent(getApplicationContext(), GlobalPreferencesActivity.class));
overridePendingTransition(R.anim.slide_right_in,R.anim.slide_right_out);
}
});
ButtonHome = (Button)findViewById(R.id.btnHome);
ButtonHome.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
startActivity(new Intent(getApplicationContext(), HomeActivity.class));
overridePendingTransition(R.anim.slide_left_in,R.anim.slide_left_out);
}
});
init();
}
private void init()
{
if(_intent.hasExtra("spot_id"))
{
int id = _intent.getIntExtra("spot_id", 0);
_spotDbAdapter = new SpotGuideDbAdapter(this).Open();
item = _spotDbAdapter.getSpot(id);
tvSpotTitle.setText(item.getSpotTitle());
tvSpotType.setText(item.getSpotType());
tvWindDirection.setText(item.getWindDirections());
tvContent.setText(item.getSpotDescription());
}
}
}
And i init the tap in my OverlayItem like this
public boolean onTap(int index)
{
OverlayItem item = mOverlays.get(index);
Intent descIntent = new Intent(currentContext.getApplicationContext(), SpotGuideDescriptionActivity.class);
descIntent.putExtra("spot_id", item.getSnippet());
currentContext.startActivity(descIntent);
return false;
}
it is not the BackToMap button that i use, it is the back button on all phones
I haven't worked with maps, so I may be off my rocker. But the fact that you are calling initMapView() in OnResume() might be creating two markers one on top of the other (and again, every time you go back). So when you think you are taping on one marker, you are actually taping on multiple markers.
That's just off the top of my head, and can be total malarkey.
A quick solution would be to #Override onBackPressed() to open the map activity back up. This might lead to you having to do it to navigate the entire app, though. If it's just that map page and the overlay with more info, you can easily just have this on the page that is duplicating:
#Override
onBackPressed(){
Intent i = new Intent(this, Activity.class);
startActivity(i);
}
then on the activity with the mapview
#Override
onBackPressed(){
moveTaskToBack(true);
}
Related
I have a button in this view which also has map class but somehow I cant set a listener to this button:
fileBtn.setOnClickListener(this);
I am not sure this is because this is a map class/fragment or any other reason.
The full class here:
/**
* This shows how to listen to some {#link GoogleMap} events.
*/
public class MapsActivity extends AppCompatActivity
implements OnMapClickListener, OnMapLongClickListener,
OnMapReadyCallback, OnClickListener {
private TextView mTapTextView;
private Button fileBtn;
private static final int REQUEST_PICK_FILE = 1;
private File selectedFile;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
mTapTextView = (TextView) findViewById(R.id.tap_text);
mTapTextView.setText("Loaded");
SupportMapFragment mapFragment =
(SupportMapFragment) getSupportFragmentManager().findFragmentById(map);
mapFragment.getMapAsync(this);
}
Button fileBtn = (Button) findViewById(R.id.loadfile);
fileBtn.setOnClickListener(this);
public void onClick(View v) {
switch(v.getId()) {
case R.id.loadfile:
Intent intent = new Intent(this, FilePicker.class);
startActivityForResult(intent, REQUEST_PICK_FILE);
break;
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(resultCode == RESULT_OK) {
switch(requestCode) {
case REQUEST_PICK_FILE:
if(data.hasExtra(FilePicker.EXTRA_FILE_PATH)) {
selectedFile = new File
(data.getStringExtra(FilePicker.EXTRA_FILE_PATH));
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_SUBJECT, "Test single attachment");
intent.putExtra(Intent.EXTRA_EMAIL, new String[]{"amirfarazmand#gmail.com"});
intent.putExtra(Intent.EXTRA_TEXT, "Mail with an attachment");
intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(data.getStringExtra(FilePicker.EXTRA_FILE_PATH))));
intent.setType("application/pdf");
startActivity(Intent.createChooser(intent, "Send mail"));
}
break;
}
}
}
private GoogleMap googleMap;
#Override
public void onMapReady(GoogleMap map) {
map.setOnMapClickListener(this);
map.setOnMapLongClickListener(this);
googleMap = map;
enableMyLocation();
}
/* private static final LatLng MELBOURNE = new LatLng(-37.81319, 144.96298);
private static final LatLng ADELAIDE = new LatLng(-34.92873, 138.59995);
private static final LatLng PERTH = new LatLng(-31.95285, 115.85734); */
public int i=0;
public Polygon polygon;
public Polyline polyline;
List<LatLng> coordinates=new ArrayList<LatLng>();
public void onMapClick(LatLng point) {
mTapTextView.setText("tapped, point=" + point);
if (i==0){
i=1;
coordinates.add(point);
googleMap.addMarker(new MarkerOptions()
.position(point)
.title(String.valueOf(point.latitude))
.snippet(String.valueOf(point.latitude))
.rotation((float) -15.0)
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_ORANGE))
);
} else if (i==1) {
i=i+1;
coordinates.add(point);
polyline = googleMap.addPolyline((new PolylineOptions())
.add(coordinates.get(0), coordinates.get(1)));
}else if (i>1){
coordinates.add(point);
polyline.remove();
if (i>2){polygon.remove();};
polygon = googleMap.addPolygon(new PolygonOptions()
.addAll(coordinates)
.strokeColor(Color.BLACK)
.strokeWidth(10));
//polygon = googleMap.addPolygon((new PolygonOptions())
// .add(coordinates.get(0), coordinates.get(1),coordinates.get(2)));
i=i+1;
}/*else{
List<LatLng> polygonList = polygon.getPoints();
Toast.makeText(getBaseContext(), polygonList.toString(), Toast.LENGTH_LONG).show();
polygonList.add(point);
polygon.remove();
polygon = googleMap.addPolygon((new PolygonOptions()));
polygon.setPoints(polygonList);
i=i+1;
}*/
}
public boolean mapView = true;
#Override
public void onMapLongClick(LatLng point) {
if(mapView) {
mTapTextView.setText("long pressed, point=" + point);
googleMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
mapView=!mapView;
}else{
googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
mapView=!mapView;
}
}
//Load coorodinates from file
private static final int LOCATION_PERMISSION_REQUEST_CODE = 1;
private void enableMyLocation() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// Permission to access the location is missing.
PermissionUtils.requestPermission(this, LOCATION_PERMISSION_REQUEST_CODE,
Manifest.permission.ACCESS_FINE_LOCATION, true);
} else if (googleMap != null) {
// Access to the location has been granted to the app.
googleMap.setMyLocationEnabled(true);
googleMap.setTrafficEnabled(true);
}
}
/**
* Displays a dialog with error message explaining that the location permission is missing.
*/
private void showMissingPermissionError() {
PermissionUtils.PermissionDeniedDialog
.newInstance(true).show(getSupportFragmentManager(), "dialog");
}
}
I think you need to declare button and click listner in onCreate() method rather than outside
of it.Like:
oncreate()
{
b1=(Button)findviewbyId(R.id.abc);
b1.setOnclicklistener(this);
}
when You implement View.Onclicklistener...You will get override method onClick
....Inside that based on id you implement your logic.
You should add listener inside onCreate. Then override method for onClick.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
mTapTextView = (TextView) findViewById(R.id.tap_text);
mTapTextView.setText("Loaded");
SupportMapFragment mapFragment =
(SupportMapFragment) getSupportFragmentManager().findFragmentById(map);
mapFragment.getMapAsync(this);
Button fileBtn = (Button) findViewById(R.id.loadfile);
fileBtn.setOnClickListener(this);
}
Override method.
#Override
public void onClick(View v) {
switch(v.getId()) {
case R.id.loadfile:
Intent intent = new Intent(this, FilePicker.class);
startActivityForResult(intent, REQUEST_PICK_FILE);
break;
}
}
Why these line
Button fileBtn = (Button) findViewById(R.id.loadfile);
fileBtn.setOnClickListener(this);
are outside onCreate() method ?
The Reason is that because ur Class implements OnClickListener instead of View.OnClickListener
Button fileBtn = (Button) findViewById(R.id.loadfile);
fileBtn.setOnClickListener(this);
Your code is dizzy, what I understood is you need to put this code inside onCreate.
I have a strange problem with a com.google.android.gms.maps.MapView.
To check if my App crashes after the garbage collector is doing his job i force my HTC One (4.2.2) to allow only 1 running app in background. If I leave my app(home button) while showing a MapView, start any other app and resume to my app, my MapView is still showing up...but I can not move or zoom the map, it's not responding at all. Other activities are working fine. I really have no clue where the problem might be.
Hope that someone can help me out?
Here is the sourcecode of my fragment that shows the MapView
public class FragmentAdvertlistMap extends Fragment {
com.google.android.gms.maps.MapView m;
GoogleMap mMap;
ArrayList<Advert> ads;
HashMap<Marker, String> myMarker;
public final LatLngBounds.Builder builder= new LatLngBounds.Builder();
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
try {
MapsInitializer.initialize(getActivity());
} catch (GooglePlayServicesNotAvailableException e) {
// TODO handle this situation
}
View inflatedView = inflater.inflate(R.layout.activity_advert_tab2, container, false);
m = (com.google.android.gms.maps.MapView)inflatedView.findViewById(R.id.map_tab);
m.onCreate(savedInstanceState);
myMarker = new HashMap<Marker, String>();
ads= AdvertListActivity.getAdverts();
setUpMapIfNeeded(inflatedView);
mMap.setOnInfoWindowClickListener(new OnInfoWindowClickListener() {
#Override
public void onInfoWindowClick(Marker arg0) {
Intent myIntent = new Intent(getActivity(), AdvertLocationActivity.class);
Advert putadvert = DefaultApplication.dbc.getAdvertForAdvertID(Integer.parseInt(myMarker.get(arg0)));
myIntent.putExtra("advert", putadvert);
startActivity(myIntent);
}
});
return inflatedView;
}
private void setUpMapIfNeeded(View inflatedView) {
if (mMap == null) {
mMap = ((com.google.android.gms.maps.MapView) inflatedView.findViewById(R.id.map_tab)).getMap();
if (mMap != null) {
this.initMarker();
}
}
}
public void initMarker(){
for(int i=0;i<ads.size();i++){
Advert tempAd = ads.get(i);
LatLng tlalo = new LatLng(tempAd.mainLocation.latitude,tempAd.mainLocation.longitude);
builder.include(tlalo);
String address = "";
if(tempAd.mainLocation.contact_street != null){
address = address + tempAd.mainLocation.contact_street;
}
if(tempAd.mainLocation.contact_street_number != null){
address = address + " " + tempAd.mainLocation.contact_street_number;
}
Marker marker = mMap.addMarker(new MarkerOptions()
.position(tlalo)
.anchor(0.5f, 0.5f)
.title(tempAd.name)
.snippet(address)
.icon(BitmapDescriptorFactory.fromResource(R.drawable.androidpin)));
myMarker.put(marker,String.valueOf(tempAd.myid));
}
mMap.setOnCameraChangeListener(new OnCameraChangeListener() {
#Override
public void onCameraChange(CameraPosition arg0) {
mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(builder.build(), 100));
mMap.setOnCameraChangeListener(null);
}
});
}
#Override
public void onResume() {
super.onResume();
m.onResume();
}
#Override
public void onPause() {
super.onPause();
m.onPause();
}
#Override
public void onDestroy() {
super.onDestroy();
m.onDestroy();
}
#Override
public void onLowMemory() {
super.onLowMemory();
m.onLowMemory();
}
}
try add this in onCreateView()
container.removeAllViews();
I found it in another similar question to yours but I lost the original link of the answer...
I want to display multiple markers on google map v2 and also on tap animate marker with a jump animation.
/**
* This shows how to place markers on a map.
*/
public class Map extends FragmentActivity implements
OnMarkerClickListener,
OnInfoWindowClickListener,
OnMarkerDragListener {
static LatLng[] GEOPOINTS;
Map con;
ArrayList<Article> mArticles;
DBHelper helper;
Drawable marker;
Button search, cancel;
EditText search_value;
Button clear_search;
int activity_flag=0;
double slat, vlong;
/**
* Demonstrates customizing the info window and/or its contents.
*/
class CustomInfoWindowAdapter implements InfoWindowAdapter {
private final RadioGroup mOptions;
// These a both viewgroups containing an ImageView with id "badge" and two TextViews with id
// "title" and "snippet".
private final View mWindow;
private final View mContents;
CustomInfoWindowAdapter() {
mWindow = getLayoutInflater().inflate(R.layout.custom_info_window, null);
mContents = getLayoutInflater().inflate(R.layout.custom_info_contents, null);
mOptions = (RadioGroup) findViewById(R.id.custom_info_window_options);
}
#Override
public View getInfoWindow(Marker marker) {
if (mOptions.getCheckedRadioButtonId() != R.id.custom_info_window) {
// This means that getInfoContents will be called.
return null;
}
render(marker, mWindow);
return mWindow;
}
#Override
public View getInfoContents(Marker marker) {
if (mOptions.getCheckedRadioButtonId() != R.id.custom_info_contents) {
// This means that the default info contents will be used.
return null;
}
render(marker, mContents);
return mContents;
}
private void render(Marker marker, View view) {
int badge;
badge = R.drawable.badge_qld;
((ImageView) view.findViewById(R.id.badge)).setImageResource(badge);
String title = marker.getTitle();
TextView titleUi = ((TextView) view.findViewById(R.id.title));
if (title != null) {
// Spannable string allows us to edit the formatting of the text.
SpannableString titleText = new SpannableString(title);
titleText.setSpan(new ForegroundColorSpan(Color.RED), 0, titleText.length(), 0);
titleUi.setText(titleText);
} else {
titleUi.setText("");
}
String snippet = marker.getSnippet();
TextView snippetUi = ((TextView) view.findViewById(R.id.snippet));
if (snippet != null && snippet.length() > 12) {
SpannableString snippetText = new SpannableString(snippet);
snippetText.setSpan(new ForegroundColorSpan(Color.MAGENTA), 0, 10, 0);
snippetText.setSpan(new ForegroundColorSpan(Color.BLUE), 12, snippet.length(), 0);
snippetUi.setText(snippetText);
} else {
snippetUi.setText("");
}
}
}
private GoogleMap mMap;
private Marker[] marks;
private TextView mTopText;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.marker_demo);
con=this;
mTopText = (TextView) findViewById(R.id.top_text);
new loadingTask().execute();
}
#Override
protected void onResume() {
super.onResume();
setUpMapIfNeeded();
}
private void setUpMapIfNeeded() {
// Do a null check to confirm that we have not already instantiated the map.
if (mMap == null) {
// Try to obtain the map wrap the SupportMapFragment.
mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getPolarisMap();
// Check if we were successful in obtaining the map.
if (mMap != null) {
setUpMap();
}
}
}
private void setUpMap() {
// Hide the zoom controls as the button panel will cover it.
mMap.getUiSettings().setZoomControlsEnabled(false);
// Add lots of markers to the map.
addMarkersToMap();
// Setting an info window adapter allows us to change the both the contents and look of the
// info window.
mMap.setInfoWindowAdapter(new CustomInfoWindowAdapter());
// Set listeners for marker events. See the bottom of this class for their behavior.
mMap.setOnMarkerClickListener(this);
mMap.setOnInfoWindowClickListener(this);
mMap.setOnMarkerDragListener(this);
// Pan to see all markers in view.
// Cannot zoom to bounds until the map has a size.
final View mapView = getSupportFragmentManager().findFragmentById(R.id.map).getView();
if (mapView.getViewTreeObserver().isAlive()) {
mapView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#SuppressWarnings("deprecation") // We use the new method when supported
#SuppressLint("NewApi") // We check which build version we are using.
#Override
public void onGlobalLayout() {
LatLngBounds bounds = new LatLngBounds.Builder().include(GEOPOINTS[0]).build();
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
mapView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
} else {
mapView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 50));
}
});
}
}
private void addMarkersToMap() {
// Uses a colored icon.
for (int i=0;i<mArticles.size();i++){
String latt=mArticles.get(i).latitude.trim().replace(",","");
String lonn=mArticles.get(i).longitude.trim();
//set latitude and longitude
GEOPOINTS[i] = new LatLng(Double.valueOf(latt), Double.valueOf(lonn));
marks[i] = mMap.addMarker(new MarkerOptions()
.position(GEOPOINTS[i])
.title(mArticles.get(i).enseigne)
.snippet(mArticles.get(i).type)
.icon(BitmapDescriptorFactory.fromResource(R.drawable.arrow)));
}
}
private boolean checkReady() {
if (mMap == null) {
Toast.makeText(this, R.string.map_not_ready, Toast.LENGTH_SHORT).show();
return false;
}
return true;
}
/**
* Called when the Clear button is clicked.
*/
public void onClearMap(View view) {
if (!checkReady()) {
return;
}
mMap.clear();
}
/**
* Called when the Reset button is clicked.
*/
public void onResetMap(View view) {
if (!checkReady()) {
return;
}
// Clear the map because we don't want duplicates of the markers.
mMap.clear();
addMarkersToMap();
}
//
// Marker related listeners.
//
#Override
public boolean onMarkerClick(final Marker marker) {
// This causes the marker at Perth to bounce into position when it is clicked.
final Handler handler = new Handler();
final long start = SystemClock.uptimeMillis();
Projection proj = mMap.getProjection();
Point startPoint = proj.toScreenLocation(GEOPOINTS[0]);
startPoint.offset(0, -100);
final LatLng startLatLng = proj.fromScreenLocation(startPoint);
final long duration = 1500;
final Interpolator interpolator = new BounceInterpolator();
handler.post(new Runnable() {
#Override
public void run() {
long elapsed = SystemClock.uptimeMillis() - start;
float t = interpolator.getInterpolation((float) elapsed / duration);
double lng = t * GEOPOINTS[0].longitude + (1 - t) * startLatLng.longitude;
double lat = t * GEOPOINTS[0].latitude + (1 - t) * startLatLng.latitude;
marker.setPosition(new LatLng(lat, lng));
if (t < 1.0) {
// Post again 16ms later.
handler.postDelayed(this, 16);
}
}
});
// We return false to indicate that we have not consumed the event and that we wish
// for the default behavior to occur (which is for the camera to move such that the
// marker is centered and for the marker's info window to open, if it has one).
return false;
}
#Override
public void onInfoWindowClick(Marker marker) {
Toast.makeText(getBaseContext(), "Click Info Window", Toast.LENGTH_SHORT).show();
}
#Override
public void onMarkerDragStart(Marker marker) {
mTopText.setText("onMarkerDragStart");
}
#Override
public void onMarkerDragEnd(Marker marker) {
mTopText.setText("onMarkerDragEnd");
}
#Override
public void onMarkerDrag(Marker marker) {
mTopText.setText("onMarkerDrag. Current Position: " + marker.getPosition());
}
class loadingTask extends AsyncTask<Void, Void,Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
setUpMapIfNeeded();
}
#Override
protected Void doInBackground(Void... params) {
helper = DBHelper.getInstance(con);
mArticles = helper.getArticlesList();
System.out.println(mArticles.toString());
return null;
}
}
}
But my log shows the following error.
java.lang.RuntimeException: Unable to resume activity
{com.example.test/com.example.test.Map}: java.lang.NullPointerException
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2698)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2726)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2212)
at android.app.ActivityThread.access$600(ActivityThread.java:139)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1205)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4899)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:558)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at com.example.test.Map.addMarkersToMap(Map.java:233)
at com.example.test.Map.setUpMap(Map.java:197)
at com.example.test.Map.setUpMapIfNeeded(Map.java:187)
at com.example.test.Map.onResume(Map.java:177)
at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1184)
at android.app.Activity.performResume(Activity.java:5082)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2688)
... 12 more
I have two problems, the first one is to display multiple geopoints and the second is to make each marker to jump on tap. can anyone help me.
Update: New Logs after changing onResume()
java.lang.NullPointerException
at com.example.test.Map$1.onGlobalLayout(Map.java:217)
at android.view.ViewTreeObserver.dispatchOnGlobalLayout(ViewTreeObserver.java:646)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1726)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1000)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4214)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:725)
at android.view.Choreographer.doCallbacks(Choreographer.java:555)
at android.view.Choreographer.doFrame(Choreographer.java:525)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:711)
at android.os.Handler.handleCallback(Handler.java:615)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4899)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:558)
at dalvik.system.NativeStart.main(Native Method)
Where line 217 is
LatLngBounds bounds = new LatLngBounds.Builder().include(GEOPOINTS[0]).build();
you are getting NullPointerException because mArticles is null when you call setUpMapIfNeeded(); in onResume()
So
Change
#Override
protected void onResume() {
super.onResume();
setUpMapIfNeeded();
}
to
#Override
protected void onResume() {
super.onResume();
new loadingTask().execute();
}
Edit :
your GEOPOINTS[0] is null at line no 217
LatLngBounds bounds = new LatLngBounds.Builder().include(GEOPOINTS[0]).build();
Reason
you have problem inside private void addMarkersToMap(), you are not initializing GEOPOINTS, so initialize GEOPOINT before for loop, for this use : GEOPOINTS=new LatLng[mArticles.size()];
So it Should look like :
GEOPOINTS=new LatLng[mArticles.size()];
for (int i=0;i<mArticles.size();i++){
String latt=mArticles.get(i).latitude.trim().replace(",","");
String lonn=mArticles.get(i).longitude.trim();
//set latitude and longitude
GEOPOINTS[i] = new LatLng(Double.valueOf(latt), Double.valueOf(lonn));
I am currently doing a MapView with mapquest and require adding overlays to locations. Currently my MapView is working however the overlay does not appear. Any ideas as to how it can be solved? Also is it possible to create an onClick on the overlay to bring me to a ListView?? Thanks is advance!! my main activity
public class QMapsActivity extends MapActivity {
protected MapView map;
AnnotationView annot;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getLayoutId());
init();
annot = new AnnotationView(map);
}
protected void init() {
// TODO Auto-generated method stub
this.setupMapView();
}
protected void setupMapView() {
// set the zoom level, center point and enable the default zoom controls
map = (MapView) findViewById(R.id.map);
map.getController().setZoom(16);
map.getController().setCenter(new GeoPoint(1.309503,103.777793));
map.setBuiltInZoomControls(true);
}
protected int getLayoutId() {
return R.layout.main;
}
#Override
protected boolean isRouteDisplayed() {
// TODO Auto-generated method stub
return false;
}
}
And my Overlay class
public class QPoiOverlay extends QMapsActivity{
protected void init() {
super.init();
setupMapView();
}
protected void addPoiOverlay() {
// TODO Auto-generated method stub
Drawable icon = getResources().getDrawable(R.drawable.location_marker);
final DefaultItemizedOverlay poiOverlay = new DefaultItemizedOverlay(icon);
OverlayItem loc1 = new OverlayItem(new GeoPoint (1.308763,103.777321), "area","area");
poiOverlay.addItem(loc1);
OverlayItem loc2 = new OverlayItem(new GeoPoint (1.309498,103.777101), "area","area");
poiOverlay.addItem(loc2);
OverlayItem loc3 = new OverlayItem(new GeoPoint (1.311531,103.778318), "area","area");
poiOverlay.addItem(loc3);
OverlayItem loc4 = new OverlayItem(new GeoPoint (1.308071,103.77841), "area","area");
poiOverlay.addItem(loc4);
poiOverlay.setOnFocusChangeListener(new ItemizedOverlay.OnFocusChangeListener() {
#Override
public void onFocusChanged(ItemizedOverlay Overlay, OverlayItem newFocus) {
// when focused item changes, recenter map and show info
map.getController().animateTo(newFocus.getPoint());
Toast.makeText(map.getContext().getApplicationContext(), newFocus.getTitle() + ": " +
newFocus.getSnippet(), Toast.LENGTH_SHORT).show();
int lastTouchedIndex = poiOverlay.getLastFocusedIndex();
if(lastTouchedIndex>-1){
OverlayItem tapped = poiOverlay.getItem(lastTouchedIndex);
annot.showAnnotationView(tapped);
}
}
});
map.getOverlays().add(poiOverlay);
map.invalidate();
}
}
On my application i receive coordinates from a remote server and i want to mark the location on the coordinates on a map, this happens on demand inside onClick method. The problem is that when i update the location i end up with multiple markers on the map instead of just one, the current location. is there any way to remove the previous marker before adding the next one?
I followed the steps in this tutorial : http://developer.android.com/resources/tutorials/views/hello-mapview.html
And my code goes like this :
public class AppTwoAndroid extends MapActivity {
private Button refreshButton;
double lat, lon;
ConnectionHandler conhandler;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
MapView mapView = (MapView) findViewById(R.id.mapview);
mapView.setBuiltInZoomControls(true);
Log.i("AppTwo", "making connectionhandler object");
conhandler = new ConnectionHandler();
conhandler.execute();
Log.i("AppTwo", "making button");
this.refreshButton = (Button)this.findViewById(R.id.close);
final List<Overlay> mapOverlays = mapView.getOverlays();
Drawable drawable = this.getResources().getDrawable(R.drawable.androidmarker);
final AppTwoAndroidItemizedOverlay itemizedoverlay = new AppTwoAndroidItemizedOverlay(drawable);
refreshButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Log.i("AppTwo", "inside onclick");
if (mapOverlays.contains(itemizedoverlay) == true) {
mapOverlays.remove(itemizedoverlay);
}
conhandler.write();
lat = conhandler.retLat();
lon = conhandler.retLon();
lat = lat * 1e6;
lon = lon * 1e6;
int ilat = (int) lat;
int ilon = (int) lon;
GeoPoint point = new GeoPoint(ilat ,ilon);
OverlayItem overlayitem = new OverlayItem(point, null, "AppOne");
itemizedoverlay.addOverlay(overlayitem);
mapOverlays.add(itemizedoverlay);
Toast.makeText(getBaseContext(), "lat is: " + lat + " lon is: " + lon
, Toast.LENGTH_SHORT).show();
}
});
}
#Override
protected boolean isRouteDisplayed() {
// TODO Auto-generated method stub
return false;
}
}
and my AppTwoAndroidItemizedOverlay class is :
public class AppTwoAndroidItemizedOverlay extends ItemizedOverlay {
private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>();
Context mContext;
public AppTwoAndroidItemizedOverlay(Drawable defaultMarker) {
super(boundCenterBottom(defaultMarker));
// TODO Auto-generated constructor stub
}
#Override
protected boolean onTap(int index) {
OverlayItem item = mOverlays.get(index);
AlertDialog.Builder dialog = new AlertDialog.Builder(mContext);
dialog.setTitle(item.getTitle());
dialog.setMessage(item.getSnippet());
dialog.show();
return true;
}
public AppTwoAndroidItemizedOverlay(Drawable defaultMarker, Context context) {
super(defaultMarker);
mContext = context;
}
public void addOverlay(OverlayItem overlay) {
mOverlays.add(overlay);
populate();
}
#Override
protected OverlayItem createItem(int i) {
return mOverlays.get(i);
}
#Override
public int size() {
return mOverlays.size();
}
}
In the onClick method just give
mapOverlays.clear();
this should clear any existing markers.
Hope this works :)
In this part of code:
if (mapOverlays.contains(itemizedoverlay) == true) {
mapOverlays.remove(itemizedoverlay);
}
When your removing the Overlay from the mapOverlay structure you are not really clearing the overlay, so when you add other item and re-add it to the mapOverlay there will be 2 markers.
If you just want a single marker do an Overlay that has setOverlayItem instead of a list with an 'adding' logic. (meaning do a overlay with just an item that when you add another, just replaces the old one)
Hope it helped! :D
Add this statement before the code....
mMap.clear();
mMap.clear();
LatLng latLng = new LatLng(gps.getLatitude(), gps.getLongitude());
mMap.animateCamera(CameraUpdateFactory.newLatLng(latLng));
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new
LatLng(gps.getLatitude(), gps.getLongitude()), 15));
mMap.addMarker(new MarkerOptions().position(latLng).title(""));
mMap.setMapType(GoogleMap.MAP_TYPE_TERRAIN);