I'm trying to implement google map in a fragment, I have succeeded adding the map and markers on it, but now I need to show current users location and when it updates. I've tried following answers on this, but all answers were not giving any results only closing application instantly or giving error without even starting application. I've followed many guides on setting users location in activity, but failed to transfer that knowledge to fragment. Please keep in mind I've just started coding with android studio and I might not understand all the information.
MainActivity
public class MainActivity extends AppCompatActivity{
private Button btn1, btn2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn1 = (Button) findViewById(R.id.btn1);
btn2 = (Button) findViewById(R.id.btn2);
btn1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
addFragment(new OneFragment(), false, "one");
}
});
btn2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
addFragment(new MapFragment(), false, "one");
}
});
}
public void addFragment(Fragment fragment, boolean addToBackStack, String tag) {
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction ft = manager.beginTransaction();
if (addToBackStack) {
ft.addToBackStack(tag);
}
ft.replace(R.id.container_frame_back, fragment, tag);
ft.commitAllowingStateLoss();
}
}
MapFragment
public class MapFragment extends Fragment implements OnMapReadyCallback, LocationListener {
LocationManager locationManager;
MarkerOptions mo;
final static String[] PERMISSIONS = {
Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION};
final static int PERMISSION_ALL = 1;
private GoogleMap mMap;
LatLng myCoordinates;
Marker marker;
public MapFragment() {
// Required empty public constructor
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
locationManager = (LocationManager) getLayoutInflater().getContext().getSystemService(Context.LOCATION_SERVICE);
mo = new MarkerOptions().position(new LatLng(54.687157, 25.279652)).title("My current location");
if (Build.VERSION.SDK_INT >= 23 && !isPermissionGranted()) {
requestPermissions(PERMISSIONS, PERMISSION_ALL);
} else requestLocation();
if (!isLocationEnabled()) {
showAlert(1);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.fragment_map, container, false);
SupportMapFragment mapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.frg); //use SuppoprtMapFragment for using in fragment instead of activity MapFragment = activity SupportMapFragment = fragment
mapFragment.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(GoogleMap mMap) {
mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
mMap.clear(); //clear old markers
CameraPosition googlePlex = CameraPosition.builder()
.target(new LatLng(37.4219999,-122.0862462))
.zoom(10)
.bearing(0)
.tilt(45)
.build();
mMap.animateCamera(CameraUpdateFactory.newCameraPosition(googlePlex), 10000, null);
mMap.addMarker(new MarkerOptions()
.position(new LatLng(37.4219999, -122.0862462))
.title("Spider Man")
.icon(bitmapDescriptorFromVector(getActivity(),R.drawable.spider)));
mMap.addMarker(new MarkerOptions()
.position(new LatLng(37.4629101,-122.2449094))
.title("Iron Man")
.snippet("His Talent : Plenty of money"));
mMap.addMarker(new MarkerOptions()
.position(new LatLng(37.3092293,-122.1136845))
.title("Captain America"));
}
});
return rootView;
}
private BitmapDescriptor bitmapDescriptorFromVector(Context context, int vectorResId) {
Drawable vectorDrawable = ContextCompat.getDrawable(context, vectorResId);
vectorDrawable.setBounds(0, 0, vectorDrawable.getIntrinsicWidth(), vectorDrawable.getIntrinsicHeight());
Bitmap bitmap = Bitmap.createBitmap(vectorDrawable.getIntrinsicWidth(), vectorDrawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
vectorDrawable.draw(canvas);
return BitmapDescriptorFactory.fromBitmap(bitmap);
}
@Override
public void onLocationChanged(Location location) {
myCoordinates = new LatLng(location.getLatitude(), location.getLongitude());
marker.setPosition(myCoordinates);
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(myCoordinates,16f));
}
@Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
@Override
public void onProviderEnabled(String s) {
}
@Override
public void onProviderDisabled(String s) {
}
@Override
public void onMapReady(GoogleMap googleMap) {
}
private boolean isPermissionGranted(){
if(getLayoutInflater().getContext().checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED
||getLayoutInflater().getContext().checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
Log.v("mylog","Permission is granted");
return true;
}
else
{
Log.v("mylog", "Permission not granted");
return false;
}
}
private boolean isLocationEnabled(){
return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) | locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
}
private void showAlert(final int status){
String message, title, btnText;
if (status == 1) {
message = "Your Locations Settings is set to 'Off'.\nPlease Enable Location to " +
"use this app";
title = "Enable Location";
btnText = "Location Settings";
} else {
message = "Please allow this app to access location!";
title = "Permission access";
btnText = "Grant";
}
final AlertDialog.Builder dialog = new AlertDialog.Builder(getLayoutInflater().getContext());
dialog.setCancelable(false);
dialog.setTitle(title)
.setMessage(message)
.setPositiveButton(btnText, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface paramDialogInterface, int paramInt) {
if (status == 1) {
Intent myIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(myIntent);
} else
requestPermissions(PERMISSIONS, PERMISSION_ALL);
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface paramDialogInterface, int paramInt) {
getActivity().finish();
}
});
dialog.show();
}
private void requestLocation() {
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
criteria.setPowerRequirement(Criteria.POWER_HIGH);
String provider = locationManager.getBestProvider(criteria, true);
if (getLayoutInflater().getContext().checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&getLayoutInflater().getContext().checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// Activity#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for Activity#requestPermissions for more details.
return;
}
locationManager.requestLocationUpdates(provider, 5000, 10, this);
}
}
MapsActivity
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback, LocationListener {
final static int PERMISSION_ALL = 1;
final static String[] PERMISSIONS = {
Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION};
private GoogleMap mMap;
MarkerOptions mo;
Marker marker;
LocationManager locationManager;
Circle userCircle;
LatLng myCoordinates;
Marker marker1;
Marker marker2;
Marker marker3;
Marker marker4;
MarkerOptions mo1;
MarkerOptions mo2;
MarkerOptions mo3;
MarkerOptions mo4;
static boolean marker1Visibility = false;
static boolean marker2Visibility = false;
static boolean marker3Visibility = false;
static boolean marker4Visibility = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
mo = new MarkerOptions().position(new LatLng(54.687157, 25.279652)).title("My current location")
.icon(vectorToBitmap(R.drawable.ic_user,Color.parseColor("#4287f5")));
if (Build.VERSION.SDK_INT >= 23 && !isPermissionGranted()) {
requestPermissions(PERMISSIONS, PERMISSION_ALL);
} else requestLocation();
if (!isLocationEnabled()) {
showAlert(1);
}
}
@Override
public void onMapReady(GoogleMap googleMap) {
setMarker();
mMap = googleMap;
marker = mMap.addMarker(mo);
marker1 = mMap.addMarker(mo1);
marker1.setVisible(marker1Visibility);
marker2 = mMap.addMarker(mo2);
marker2.setVisible(marker2Visibility);
marker3 = mMap.addMarker(mo3);
marker3.setVisible(marker3Visibility);
marker4 = mMap.addMarker(mo4);
marker4.setVisible(marker4Visibility);
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(mo.getPosition(),14f));
}
@Override
protected void onResume() {
super.onResume();
}
@Override
public void onLocationChanged(Location location) {
myCoordinates = new LatLng(location.getLatitude(), location.getLongitude());
marker.setPosition(myCoordinates);
checkMarker();
if(userCircle != null)
{
userCircle.remove();
}
mMap.getUiSettings().setMapToolbarEnabled(true);
userCircle = mMap.addCircle( new CircleOptions()
.center(myCoordinates)
.radius(100)
.strokeWidth(3f)
.strokeColor(Color.BLUE)
.fillColor(Color.argb(70,135,206,250)));
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(myCoordinates,16f));
}
@Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
@Override
public void onProviderEnabled(String s) {
}
@Override
public void onProviderDisabled(String s) {
}
private void requestLocation() {
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
criteria.setPowerRequirement(Criteria.POWER_HIGH);
String provider = locationManager.getBestProvider(criteria, true);
if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// Activity#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for Activity#requestPermissions for more details.
return;
}
locationManager.requestLocationUpdates(provider, 5000, 10, this);
}
private boolean isLocationEnabled(){
return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) | locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
}
private boolean isPermissionGranted(){
if(checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED
|| checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
Log.v("mylog","Permission is granted");
return true;
}
else
{
Log.v("mylog", "Permission not granted");
return false;
}
}
private void showAlert(final int status){
String message, title, btnText;
if (status == 1) {
message = "Your Locations Settings is set to 'Off'.\nPlease Enable Location to " +
"use this app";
title = "Enable Location";
btnText = "Location Settings";
} else {
message = "Please allow this app to access location!";
title = "Permission access";
btnText = "Grant";
}
final AlertDialog.Builder dialog = new AlertDialog.Builder(this);
dialog.setCancelable(false);
dialog.setTitle(title)
.setMessage(message)
.setPositiveButton(btnText, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface paramDialogInterface, int paramInt) {
if (status == 1) {
Intent myIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(myIntent);
} else
requestPermissions(PERMISSIONS, PERMISSION_ALL);
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface paramDialogInterface, int paramInt) {
finish();
}
});
dialog.show();
}
private BitmapDescriptor vectorToBitmap(@DrawableRes int id, @ColorInt int color) {
Drawable vectorDrawable = ResourcesCompat.getDrawable(getResources(), id, null);
Bitmap bitmap = Bitmap.createBitmap(vectorDrawable.getIntrinsicWidth(),
vectorDrawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
vectorDrawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
DrawableCompat.setTint(vectorDrawable, color);
vectorDrawable.draw(canvas);
return BitmapDescriptorFactory.fromBitmap(bitmap);
}
private void setMarker()
{
mo1 = new MarkerOptions().position(new LatLng(54.712199,25.302195)).title("Marker1").icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN));
mo2 = new MarkerOptions().position(new LatLng(54.7230324,25.2958683)).title("Marker2").icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN));
mo3 = new MarkerOptions().position(new LatLng(54.7190283,25.3034968)).title("Marker3").icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN));
mo4 = new MarkerOptions().position(new LatLng(54.7057832,25.2972182)).title("Express Pica").icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN));
}
private void checkMarker()
{
if(distanceBetween(mo1.getPosition().latitude,mo1.getPosition().longitude,myCoordinates.latitude,myCoordinates.longitude) <= 70)
{
marker1.setVisible(true);
marker1Visibility = true;
}
if(distanceBetween(mo2.getPosition().latitude,mo2.getPosition().longitude,myCoordinates.latitude,myCoordinates.longitude) <= 70)
{
marker2.setVisible(true);
marker2Visibility = true;
}
if(distanceBetween(mo3.getPosition().latitude,mo3.getPosition().longitude,myCoordinates.latitude,myCoordinates.longitude) <= 70)
{
marker3.setVisible(true);
marker3Visibility = true;
}
if(distanceBetween(mo4.getPosition().latitude,mo4.getPosition().longitude,myCoordinates.latitude,myCoordinates.longitude) <= 70)
{
marker4.setVisible(true);
marker4Visibility = true;
}
}
private double distanceBetween(double lat1, double lon1, double lat2, double lon2) {
double theta = lon1 - lon2;
double dist = Math.sin(deg2rad(lat1))
* Math.sin(deg2rad(lat2))
+ Math.cos(deg2rad(lat1))
* Math.cos(deg2rad(lat2))
* Math.cos(deg2rad(theta));
dist = Math.acos(dist);
dist = dist * 180.0 / Math.PI;
dist = dist * 60 * 1.1515*1000;
return (dist);
}
private double deg2rad(double deg) {
return (deg * Math.PI / 180.0);
}
}
Gradle.build app
apply plugin: 'com.android.application'
android {
compileSdkVersion 29
buildToolsVersion "29.0.2"
defaultConfig {
applicationId "This Does Not Matter"
minSdkVersion 23
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
implementation 'com.google.android.material:material:1.0.0'
implementation 'com.google.android.gms:play-services:12.0.1'
}
Current error message
2019-11-17 13:59:17.932 30953-30993/com.eif.petrasbukelis.twiftoffun E/AndroidRuntime: FATAL EXCEPTION: Thread-3
Process: com.eif.petrasbukelis.twiftoffun, PID: 30953
java.lang.NoClassDefFoundError: Failed resolution of: Lorg/apache/http/ProtocolVersion;
at bs.b(:com.google.android.gms.dynamite_mapsdynamite@19629065@19.6.29 (100400-0):2)
at br.a(:com.google.android.gms.dynamite_mapsdynamite@19629065@19.6.29 (100400-0):3)
at bt.a(:com.google.android.gms.dynamite_mapsdynamite@19629065@19.6.29 (100400-0):20)
at com.google.maps.api.android.lib6.drd.ak.a(:com.google.android.gms.dynamite_mapsdynamite@19629065@19.6.29 (100400-0):6)
at ax.a(:com.google.android.gms.dynamite_mapsdynamite@19629065@19.6.29 (100400-0):13)
at ax.run(:com.google.android.gms.dynamite_mapsdynamite@19629065@19.6.29 (100400-0):49)
Caused by: java.lang.ClassNotFoundException: Didn't find class "org.apache.http.ProtocolVersion" on path: DexPathList[[zip file "/data/user_de/0/com.google.android.gms/app_chimera/m/000000fd/MapsDynamite.apk"],nativeLibraryDirectories=[/data/user_de/0/com.google.android.gms/app_chimera/m/000000fd/MapsDynamite.apk!/lib/arm64-v8a, /system/lib64]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:134)
at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
at w.loadClass(:com.google.android.gms.dynamite_dynamiteloader@19629065@19.6.29 (100400-0):16)
at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
at bs.b(:com.google.android.gms.dynamite_mapsdynamite@19629065@19.6.29 (100400-0):2)
at br.a(:com.google.android.gms.dynamite_mapsdynamite@19629065@19.6.29 (100400-0):3)
at bt.a(:com.google.android.gms.dynamite_mapsdynamite@19629065@19.6.29 (100400-0):20)
at com.google.maps.api.android.lib6.drd.ak.a(:com.google.android.gms.dynamite_mapsdynamite@19629065@19.6.29 (100400-0):6)
at ax.a(:com.google.android.gms.dynamite_mapsdynamite@19629065@19.6.29 (100400-0):13)
at ax.run(:com.google.android.gms.dynamite_mapsdynamite@19629065@19.6.29 (100400-0):49)
2019-11-17 13:59:17.977 30953-30953/com.eif.petrasbukelis.twiftoffun E/SchedPolicy: set_timerslack_ns write failed: Operation not permitted
2019-11-17 13:59:18.711 30953-30975/com.eif.petrasbukelis.twiftoffun I/elis.twiftoffu: ProcessProfilingInfo new_methods=12 is saved saved_to_disk=1 resolve_classes_delay=8000
2019-11-17 13:59:19.656 30953-31019/com.eif.petrasbukelis.twiftoffun W/DynamiteModule: Local module descriptor class for com.google.android.gms.googlecertificates not found.
2019-11-17 13:59:19.666 30953-31019/com.eif.petrasbukelis.twiftoffun I/DynamiteModule: Considering local module com.google.android.gms.googlecertificates:0 and remote module com.google.android.gms.googlecertificates:4
2019-11-17 13:59:19.666 30953-31019/com.eif.petrasbukelis.twiftoffun I/DynamiteModule: Selected remote version of com.google.android.gms.googlecertificates, version >= 4
2019-11-17 13:59:19.672 30953-31019/com.eif.petrasbukelis.twiftoffun I/DynamiteLoaderV2: [71] Googlecertificates
2019-11-17 13:59:19.675 30953-31019/com.eif.petrasbukelis.twiftoffun W/elis.twiftoffu: Unsupported class loader