com.piusvelte.mosaic.android.MosaicMap.java Source code

Java tutorial

Introduction

Here is the source code for com.piusvelte.mosaic.android.MosaicMap.java

Source

/*
 * Mosaic - Location Based Messaging
 * Copyright (C) 2013 Bryan Emmanuel
 * 
 * This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *  
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *  
 *  Bryan Emmanuel piusvelte@gmail.com
 */
/*
 * Mosaic - Location Based Messaging
 * Copyright (C) 2013 Bryan Emmanuel
 * 
 * This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *  
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *  
 *  Bryan Emmanuel piusvelte@gmail.com
 */
package com.piusvelte.mosaic.android;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.OnMapLongClickListener;
import com.google.android.gms.maps.GoogleMap.OnMarkerClickListener;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.UiSettings;
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.Polygon;
import com.google.android.gms.maps.model.PolygonOptions;

import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.provider.Settings;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;

public class MosaicMap extends Fragment
        implements ServiceConnection, OnMapLongClickListener, OnMarkerClickListener {

    private Button btnNickname;
    private HashMap<String, Long> messages = new HashMap<String, Long>();
    private HashMap<Long, Marker> markers = new HashMap<Long, Marker>();
    private HashMap<Long, Polygon> polygons = new HashMap<Long, Polygon>();

    private ILocationService iLocationService;
    private GoogleMap map;
    private static final int REQUEST_INSERT_MESSAGE = 0;
    private static final int REQUEST_UPDATE_MESSAGE = 1;
    private static final int REQUEST_VIEW_MESSAGE = 2;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        GooglePlayServicesUtil.getOpenSourceSoftwareLicenseInfo(getActivity());
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.map, container, false);
        btnNickname = ((Button) rootView.findViewById(R.id.nickname));
        btnNickname.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                Activity activity = getActivity();
                final EditText newNickname = new EditText(activity);
                newNickname.setText(btnNickname.getText().toString());
                new AlertDialog.Builder(activity).setTitle("Change nickname").setView(newNickname)
                        .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {

                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                String nickname = newNickname.getText().toString();
                                if (nickname.length() > 0) {
                                    if (!nickname.equals(btnNickname.getText().toString())) {
                                        try {
                                            iLocationService.changeNickname(nickname);
                                        } catch (RemoteException e) {
                                            // TODO Auto-generated catch block
                                            e.printStackTrace();
                                        }
                                    }
                                } else {
                                    //TODO no name
                                }
                            }

                        }).setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {

                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                dialog.cancel();
                            }
                        }).show();
            }

        });
        return rootView;
    }

    @Override
    public void onResume() {
        super.onResume();
        if (map == null)
            map = ((SupportMapFragment) getActivity().getSupportFragmentManager().findFragmentById(R.id.map))
                    .getMap();
        map.setMyLocationEnabled(true);
        map.setOnMapLongClickListener(this);
        UiSettings uiSettings = map.getUiSettings();
        uiSettings.setMyLocationButtonEnabled(false);
        uiSettings.setScrollGesturesEnabled(false);
        uiSettings.setZoomControlsEnabled(false);
        uiSettings.setZoomGesturesEnabled(false);
        map.setOnMarkerClickListener(this);
        getActivity();
        getActivity().bindService(new Intent(getActivity(), MosaicService.class), this, Context.BIND_AUTO_CREATE);
    }

    @Override
    public void onPause() {
        super.onPause();
        if (iLocationService != null) {
            try {
                iLocationService.setCallback(null);
            } catch (RemoteException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        getActivity().unbindService(this);
    }

    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        iLocationService = ILocationService.Stub.asInterface(service);
        try {
            iLocationService.setCallback(iMain);
        } catch (RemoteException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        iLocationService = null;
    }

    private List<LatLng> getMarkerCircle(double lat, double lng, int radius) {
        ArrayList<LatLng> coords = new ArrayList<LatLng>();
        for (int a = 0; a < 360; a++)
            coords.add(new LatLng(getOffsetLatitude(lat, Math.sin(a) * radius),
                    getOffsetLongitude(lat, lng, Math.cos(a) * radius)));
        return coords;
    }

    private double getOffsetLatitude(double lat, double offset) {
        return lat + Math.toDegrees(offset / Mosaic.EARTH_RADIUS);
    }

    private double getOffsetLongitude(double lat, double lng, double offset) {
        return lng + Math.toDegrees(offset / (Mosaic.EARTH_RADIUS * Math.cos(Math.toRadians(lat))));
    }

    @Override
    public boolean onMarkerClick(Marker marker) {
        if (messages.containsKey(marker.getId())) {
            try {
                iLocationService.getMessage(messages.get(marker.getId()));
            } catch (RemoteException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } else
            marker.remove();
        return true;
    }

    @Override
    public void onMapLongClick(LatLng point) {
        startActivityForResult(new Intent(getActivity(), MessageEditor.class)
                .putExtra(Mosaic.EXTRA_LATITUDE, (int) (point.latitude * 1E6))
                .putExtra(Mosaic.EXTRA_LONGITUDE, (int) (point.longitude * 1E6)), REQUEST_INSERT_MESSAGE);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        getActivity();
        if ((requestCode == REQUEST_INSERT_MESSAGE) && (resultCode == Activity.RESULT_OK)) {
            try {
                iLocationService.insertMessage(data.getStringExtra(Mosaic.EXTRA_TITLE),
                        data.getStringExtra(Mosaic.EXTRA_BODY), data.getIntExtra(Mosaic.EXTRA_LATITUDE, 0),
                        data.getIntExtra(Mosaic.EXTRA_LONGITUDE, 0), data.getIntExtra(Mosaic.EXTRA_RADIUS, 0),
                        data.getLongExtra(Mosaic.EXTRA_EXPIRY, Mosaic.NEVER_EXPIRES));
            } catch (RemoteException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } else {
            getActivity();
            if ((requestCode == REQUEST_UPDATE_MESSAGE) && (resultCode == Activity.RESULT_OK)) {
                if (data.hasExtra(Mosaic.EXTRA_TITLE)) {
                    try {
                        iLocationService.updateMessage(data.getLongExtra(Mosaic.EXTRA_ID, Mosaic.INVALID_ID),
                                data.getStringExtra(Mosaic.EXTRA_TITLE), data.getStringExtra(Mosaic.EXTRA_BODY),
                                data.getIntExtra(Mosaic.EXTRA_RADIUS, 0),
                                data.getLongExtra(Mosaic.EXTRA_EXPIRY, Mosaic.NEVER_EXPIRES));
                    } catch (RemoteException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                } else {
                    Long id = data.getLongExtra(Mosaic.EXTRA_ID, Mosaic.INVALID_ID);
                    if (markers.containsKey(id)) {
                        messages.remove(markers.get(id).getId());
                        markers.remove(id).remove();
                    }
                    if (polygons.containsKey(id))
                        polygons.remove(id).remove();
                    try {
                        iLocationService.removeMessage(id);
                    } catch (RemoteException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            } else {
                if ((requestCode == REQUEST_VIEW_MESSAGE) && (resultCode == Activity.RESULT_OK)) {
                    try {
                        iLocationService.reportMessage(data.getLongExtra(Mosaic.EXTRA_ID, Mosaic.INVALID_ID));
                    } catch (RemoteException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    private IMain.Stub iMain = new IMain.Stub() {

        @Override
        public void setCoordinates(double latitude, double longitude) throws RemoteException {
            if (latitude != Integer.MAX_VALUE) {
                if (map != null)
                    map.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(latitude, longitude), 18F));
            } else {
                new AlertDialog.Builder(getActivity()).setTitle("GPS Settings").setMessage("Please enable GPS.")
                        .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {

                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                dialog.cancel();
                                startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
                            }
                        }).setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {

                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                dialog.cancel();
                                getActivity().finish();
                            }
                        }).show();
            }
        }

        @Override
        public void setNickname(String nickname) throws RemoteException {
            if (nickname != null) {
                btnNickname.setEnabled(true);
                btnNickname.setText(nickname);
            } else {
                new AlertDialog.Builder(getActivity()).setTitle("Sign in")
                        .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {

                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                dialog.dismiss();
                                startActivity(new Intent(getActivity(), SignIn.class));
                            }
                        }).setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {

                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                dialog.cancel();
                                getActivity().finish();
                            }
                        }).show();
            }
        }

        @Override
        public void clearMessages() throws RemoteException {
            messages.clear();
            markers.clear();
            polygons.clear();
            map.clear();
        }

        @Override
        public void addMessage(long id, double latitude, double longitude, int radius, String title, String body,
                String nick) throws RemoteException {
            Long idL = (Long) id;
            Marker marker = null;
            if (markers.containsKey(idL))
                marker = markers.get(idL);
            if ((radius != Mosaic.RADIUS_UNCHANGED) && polygons.containsKey(idL))
                polygons.remove(idL).remove();
            if (marker != null) {
                marker.setTitle(title + " -" + nick);
                marker.setSnippet(body);
            } else {
                marker = map.addMarker(new MarkerOptions().position(new LatLng(latitude, longitude))
                        .title(title + " -" + nick).snippet(body).draggable(false));
                //            .icon(getMarkerIcon(latitude, longitude, radius)));
                markers.put(idL, marker);
                messages.put(marker.getId(), idL);
            }
            if (radius > 0)
                polygons.put(idL,
                        map.addPolygon(new PolygonOptions().addAll(getMarkerCircle(latitude, longitude, radius))
                                .fillColor(getResources().getColor(R.color.radius_fill))
                                .strokeColor(getResources().getColor(R.color.radius_stroke)).strokeWidth(1)));
            marker.showInfoWindow();
        }

        @Override
        public void editMessage(long id, String title, String body, int radius, long expiry)
                throws RemoteException {
            startActivityForResult(
                    new Intent(getActivity(), MessageEditor.class).putExtra(Mosaic.EXTRA_ID, id)
                            .putExtra(Mosaic.EXTRA_TITLE, title).putExtra(Mosaic.EXTRA_BODY, body)
                            .putExtra(Mosaic.EXTRA_RADIUS, radius).putExtra(Mosaic.EXTRA_EXPIRY, expiry),
                    REQUEST_UPDATE_MESSAGE);
        }

        @Override
        public void viewMessage(long id, String title, String body, String nick) throws RemoteException {
            startActivityForResult(
                    new Intent(getActivity(), MessageViewer.class).putExtra(Mosaic.EXTRA_ID, id)
                            .putExtra(Mosaic.EXTRA_TITLE, title + " -" + nick).putExtra(Mosaic.EXTRA_BODY, body),
                    REQUEST_VIEW_MESSAGE);
        }

        @Override
        public void removeMarker(long id) throws RemoteException {
            Long idL = (Long) id;
            if (markers.containsKey(idL)) {
                messages.remove(markers.get(idL).getId());
                markers.remove(idL).remove();
            }
            if (polygons.containsKey(idL))
                polygons.remove(idL).remove();
        }
    };

}