package com.alimuzaffar.ramadanalarm.fragments; import android.Manifest; import android.app.Activity; import android.app.Fragment; import android.content.DialogInterface; import android.content.pm.PackageManager; import android.graphics.Color; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.location.Location; import android.os.Bundle; import android.support.v7.app.AlertDialog; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.CheckBox; import android.widget.CompoundButton; import com.alimuzaffar.ramadanalarm.BuildConfig; import com.alimuzaffar.ramadanalarm.Constants; import com.alimuzaffar.ramadanalarm.R; import com.alimuzaffar.ramadanalarm.util.AppSettings; import com.alimuzaffar.ramadanalarm.util.PermissionUtil; import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.GoogleMapOptions; import com.google.android.gms.maps.MapFragment; import com.google.android.gms.maps.OnMapReadyCallback; import com.google.android.gms.maps.model.BitmapDescriptorFactory; import com.google.android.gms.maps.model.CameraPosition; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.MarkerOptions; import com.google.android.gms.maps.model.PolylineOptions; /** * A simple {@link Fragment} subclass. */ public class KaabaLocatorFragment extends Fragment implements Constants, OnMapReadyCallback, SensorEventListener { Location mLastLocation; MapFragment mMapFragment; GoogleMap mMap; // private float currentDegree = 0f; private SensorManager mSensorManager; private float[] mRotationMatrix = new float[16]; private float[] mValues = new float[3]; private boolean mRegistered = false; private static boolean sWriterExternalPermissionDenied; public KaabaLocatorFragment() { // Required empty public constructor } public static KaabaLocatorFragment newInstance(Location location) { KaabaLocatorFragment fragment = new KaabaLocatorFragment(); Bundle args = new Bundle(); args.putParcelable(EXTRA_LAST_LOCATION, location); fragment.setArguments(args); return fragment; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (getArguments() != null) { mLastLocation = (Location) getArguments().getParcelable(EXTRA_LAST_LOCATION); } } @Override public void onAttach(Activity activity) { super.onAttach(activity); mSensorManager = (SensorManager) activity.getSystemService(Activity.SENSOR_SERVICE); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment View view = inflater.inflate(R.layout.fragment_kaaba_locator, container, false); view.findViewById(R.id.grant).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { checkPermissions(); } }); return view; } private boolean checkPermissions() { if (!PermissionUtil.hasSelfPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)) { if (!sWriterExternalPermissionDenied) { requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_WRITE_EXTERNAL); } else { // Perhaps inform the user why they aren't seeing anything. } return false; } return true; } public void showMap() { if (!PermissionUtil.hasSelfPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)) { throw new IllegalStateException("WRITE_EXTERNAL_STORAGE permission should be granted before this method is called."); } if (mMapFragment == null) { mMapFragment = (MapFragment) getFragmentManager().findFragmentByTag("map_fragment"); } if (mMapFragment == null) { GoogleMapOptions options = new GoogleMapOptions() .rotateGesturesEnabled(false) .tiltGesturesEnabled(false) .compassEnabled(true) .zoomControlsEnabled(false) .zoomGesturesEnabled(true) .scrollGesturesEnabled(true); mMapFragment = MapFragment.newInstance(options); } if (mMap == null && !mMapFragment.isAdded()) { ((ViewGroup) getView().findViewById(R.id.map_container)).removeAllViews(); getFragmentManager().beginTransaction().add(R.id.map_container, mMapFragment, "map_fragment").commit(); mMapFragment.getMapAsync(this); showOrientationDialog(); } else { registerRotationListener(); } } public void hideMap() { unregisterRotationListener(); } @Override public void onMapReady(GoogleMap map) { mMap = map; if (mLastLocation != null) { initMap(); } } private void initMap() { if (mMap == null && mLastLocation == null) { Log.w("KabaaLocatorFragment", "Ignoring since mMap or mLastLocation is null"); return; } registerRotationListener(); LatLng startPosition = new LatLng(mLastLocation.getLatitude(), mLastLocation.getLongitude()); //21.4224698,39.8262066 LatLng kaaba = new LatLng(21.4224698, 39.8262066); mMap.setMyLocationEnabled(true); mMap.getUiSettings().setMyLocationButtonEnabled(true); mMap.getUiSettings().setCompassEnabled(false); mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(startPosition, 13)); //mMap.getUiSettings().setRotateGesturesEnabled(false); mMap.clear(); mMap.addMarker(new MarkerOptions() .title(getString(R.string.kaaba)) .position(kaaba)); mMap.addMarker(new MarkerOptions() .icon(BitmapDescriptorFactory.fromResource(R.drawable.compass)) .title(getString(R.string.current_location)) .position(startPosition)); // Polylines are useful for marking paths and routes on the map. mMap.addPolyline(new PolylineOptions().geodesic(true) .add(startPosition) // user position .add(kaaba) .color(Color.RED)); // Kaabah } public void setLocation(Location location) { mLastLocation = location; initMap(); } @Override public void onResume() { super.onResume(); registerRotationListener(); } @Override public void onPause() { super.onPause(); unregisterRotationListener(); } private void registerRotationListener() { if (mMap != null && mLastLocation != null && !mRegistered) { mSensorManager.registerListener(this, mSensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR), SensorManager.SENSOR_DELAY_UI); mRegistered = true; } } private void unregisterRotationListener() { if (mRegistered) { mSensorManager.unregisterListener(this); mRegistered = false; } } @Override public void onSensorChanged(SensorEvent event) { if (mLastLocation == null) { return; } SensorManager.getRotationMatrixFromVector(mRotationMatrix, event.values); SensorManager.getOrientation(mRotationMatrix, mValues); /* if (BuildConfig.DEBUG) { System.out.println("sensorChanged (" + Math.toDegrees(mValues[0]) + ", " + Math.toDegrees(mValues[1]) + ", " + Math.toDegrees(mValues[2]) + ")"); } */ float bearing = 0f; if (mMap != null) { bearing = Double.valueOf(mMap.getCameraPosition().bearing).floatValue(); } // get the angle around the z-axis rotated float degree = Double.valueOf(Math.toDegrees(mValues[0])).floatValue(); if (Math.round(bearing) == Math.round(degree)) { System.out.println("bearing and degrees are the same."); return; } if (BuildConfig.DEBUG) { System.out.println("degrees " + degree + ", bearing " + bearing); } //tvHeading.setText("Heading: " + Float.toString(degree) + " degrees"); CameraPosition cameraPosition = mMap.getCameraPosition(); CameraPosition newPosition = new CameraPosition(cameraPosition.target, cameraPosition.zoom, cameraPosition.tilt, degree); mMap.moveCamera(CameraUpdateFactory.newCameraPosition(newPosition)); // create a rotation animation (reverse turn degree degrees) /* RotateAnimation ra = new RotateAnimation( currentDegree, -degree-180, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); // how long the animation will take place ra.setDuration(210); // set the animation after the end of the reservation status ra.setFillAfter(true); // Start the animation mCompass.startAnimation(ra); currentDegree = -degree-180; */ } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } /** * Callback received when a permissions request has been completed. */ @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { if (requestCode == REQUEST_WRITE_EXTERNAL) { if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { showMap(); } else { Log.i("BaseActivity", "LOCATION permission was NOT granted."); sWriterExternalPermissionDenied = true; } } else { super.onRequestPermissionsResult(requestCode, permissions, grantResults); } } private void showOrientationDialog() { if (!AppSettings.getInstance().getBoolean(AppSettings.Key.SHOW_ORIENATATION_INSTRACTIONS, true)) { return; } View v = getActivity().getLayoutInflater().inflate(R.layout.view_orientation_instructions, null); AlertDialog.Builder alertBuilder = new AlertDialog.Builder(getActivity()); alertBuilder.setView(v) .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); CheckBox doNotShow = (CheckBox) v.findViewById(R.id.checkbox_no_show); doNotShow.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { AppSettings.getInstance().set(AppSettings.Key.SHOW_ORIENATATION_INSTRACTIONS, !isChecked); } }); alertBuilder.create().show(); } }