Reputation: 59
I'm working on a E-com app, and I have to get the location of the user. I was using Google Maps' Places Picker API for the tasks. Things were fine for a while, but now I suddenly receive this error message:
I/Choreographer(691): Skipped 55 frames! The application may be doing too much work on its main thread
The first two activities are working fine and the error message comes only at the starting of the map activity. The map screen starts flashing and app returns to the main activity. The error happens randomly, and doesn't happen all of the time. Sometimes it's working fine and sometimes it's giving issues.
Here I'm putting my whole map code:
public class LocationActivity extends AppCompatActivity implements OnMapReadyCallback,GoogleApiClient.OnConnectionFailedListener{
ArrayList<Products> products_list;
//products_list =
SharedPrefManager.getInstance(getApplicationContext()).GetCart();
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
}
@Override
public void onMapReady(GoogleMap googleMap) {
Log.i(TAG, "onMapReady: Map is ready");
Toast.makeText(this, "Map is Ready", Toast.LENGTH_SHORT).show();
mMap = googleMap;
if (mLocationPermissionGranted) {
getDeviceLocation();
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
mMap.setMyLocationEnabled(true);
mMap.getUiSettings().setMyLocationButtonEnabled(false);
Init();
}
}
private static final String TAG = "MapActivity";
private static final String FINE_LOCATION=Manifest.permission.ACCESS_FINE_LOCATION;
private static final String COARSE_LOCATION=Manifest.permission.ACCESS_COARSE_LOCATION;
private static final int mLocationPermissionRequestCode = 1234;
private static final float DEFAULT_ZOOM = 15f;
protected GeoDataClient mGeoDataClient;
private static final LatLngBounds LAT_LNG_BOUNDS = new LatLngBounds(new LatLng(5,79),new LatLng(10,82));
private static final int PLACE_PICKER_REQUEST = 1;
//widgets
private AutoCompleteTextView mSearch_text;
private ImageView mGps,mPicker;
private Button button;
//vars
private Boolean mLocationPermissionGranted = false;
private GoogleMap mMap;
private FusedLocationProviderClient mFusedLocationProviderClient;
private PlaceAutocompleteAdapter placeAutocompleteAdapter;
private GoogleApiClient mGoogleApiClient;
private LatLng selectedLatLng;
private String selectedname;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_location);
// Construct a GeoDataClient.
mGeoDataClient = Places.getGeoDataClient(this, null);
button=findViewById(R.id.btn_confirm);
mSearch_text = findViewById(R.id.search_text);
mGps = findViewById(R.id.ic_gps);
mPicker = findViewById(R.id.ic_picker);
getPermissionAccess();
}
private void Init(){
Log.i(TAG, "Init: Initializing");
mGoogleApiClient = new GoogleApiClient
.Builder(this)
.addApi(Places.GEO_DATA_API)
.addApi(Places.PLACE_DETECTION_API)
.enableAutoManage(this, this)
.build();
mSearch_text.setOnItemClickListener(mAutocompleteAdapterViewListener);
placeAutocompleteAdapter = new PlaceAutocompleteAdapter(this,mGeoDataClient,LAT_LNG_BOUNDS,null);
mSearch_text.setAdapter(placeAutocompleteAdapter);
mSearch_text.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if(actionId == EditorInfo.IME_ACTION_SEARCH
|| actionId == EditorInfo.IME_ACTION_DONE
|| event.getAction() == event.ACTION_DOWN
|| event.getAction() == event.KEYCODE_ENTER){
//Method for search
geoLocate();
}
return false;
}
});
mGps.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.i(TAG, "onClick: gps icon clicked");
getDeviceLocation();
}
});
mPicker.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
PlacePicker.IntentBuilder builder = new PlacePicker.IntentBuilder();
try {
startActivityForResult(builder.build(LocationActivity.this), PLACE_PICKER_REQUEST);
} catch (GooglePlayServicesRepairableException e) {
e.printStackTrace();
} catch (GooglePlayServicesNotAvailableException e) {
e.printStackTrace();
}
}
});
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
NextActivity();
}
});
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == PLACE_PICKER_REQUEST) {
if (resultCode == RESULT_OK) {
Place place = PlacePicker.getPlace(this,data);
String toastMsg = String.format("Place: %s", place.getName());
Toast.makeText(this, toastMsg, Toast.LENGTH_LONG).show();
PendingResult<PlaceBuffer> placeResult = Places.GeoDataApi.getPlaceById(mGoogleApiClient,place.getId());
placeResult.setResultCallback(mUpdatePlaceDetailsCallback);
}
}
}
private void geoLocate(){
Log.i(TAG, "geoLocate: geolocating");
String searchstring = mSearch_text.getText().toString();
Geocoder geocoder = new Geocoder(LocationActivity.this);
List<Address> list = new ArrayList<>();
try{
list = geocoder.getFromLocationName(searchstring,1);
}catch (IOException e)
{
Log.i(TAG, "geoLocate: IOException"+ e.getMessage());
}
if(list.size()>0){
Address address = list.get(0);
Log.i(TAG, "geoLocate: Found LocationActivity"+ address.toString());
MoveCamera(new LatLng(address.getLatitude(),address.getLongitude()),DEFAULT_ZOOM,
address.getAddressLine(0));
}
}
private void getDeviceLocation(){
Log.i(TAG, "getDeviceLocation: Getting Device LocationActivity");
mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);
try{
if(mLocationPermissionGranted){
Task location =mFusedLocationProviderClient.getLastLocation();
location.addOnCompleteListener(new OnCompleteListener() {
@Override
public void onComplete(@NonNull Task task) {
if(task.isSuccessful()){
Log.i(TAG, "onComplete: LocationActivity Found");
android.location.Location currentLocation = (android.location.Location) task.getResult();
MoveCamera(new LatLng(currentLocation.getLatitude(),currentLocation.getLongitude()),DEFAULT_ZOOM
,"My LocationActivity");
}
else {
Log.i(TAG, "onComplete: LocationActivity Null");
Toast.makeText(LocationActivity.this, "Unable to get LocationActivity", Toast.LENGTH_SHORT).show();
}
}
});
}
} catch (SecurityException e){
Log.i(TAG, "getDeviceLocation: SecurityException: "+e.getMessage());
}
}
private void MoveCamera(LatLng latLng , float zoom, String title){
Log.i(TAG, "MoveCamera: Moving Camera to lat: "+latLng.latitude+" ,lng: "+latLng.longitude);
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng,zoom));
mMap.clear();
if(!title.equals("My LocationActivity")){
MarkerOptions markerOptions = new MarkerOptions()
.position(latLng)
.title(title);
mMap.addMarker(markerOptions);
}
}
private void InitMap(){
Log.i(TAG, "InitMap: Initilizing Map");
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(LocationActivity.this);
}
private void getPermissionAccess(){
Log.i(TAG, "getPermissionAccess: Getting LocationActivity permissions");
String[] permissions = {FINE_LOCATION,COARSE_LOCATION};
if(ContextCompat.checkSelfPermission(this.getApplicationContext(),FINE_LOCATION) == PackageManager.PERMISSION_GRANTED){
if(ContextCompat.checkSelfPermission(this.getApplicationContext(),COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED){
mLocationPermissionGranted = true;
InitMap();
} else {
ActivityCompat.requestPermissions(this,permissions,mLocationPermissionRequestCode);
}
} else {
ActivityCompat.requestPermissions(this,permissions,mLocationPermissionRequestCode);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
Log.i(TAG, "onRequestPermissionsResult: Called");
mLocationPermissionGranted = false;
switch (requestCode){
case mLocationPermissionRequestCode:{
if(grantResults.length>0){
for(int i=0; i<grantResults.length; i++){
if(grantResults[i]!= PackageManager.PERMISSION_GRANTED){
mLocationPermissionGranted=false;
Log.i(TAG, "onRequestPermissionsResult: Permission Denied.");
Log.i(TAG, "onRequestPermissionsResult:"+grantResults[i]);
return;
}
}
mLocationPermissionGranted=true;
Log.i(TAG, "onRequestPermissionsResult: Permission Granted");
//initialization of Map
InitMap();
}
}
}
}
/*
google places api auto complete */
private AdapterView.OnItemClickListener mAutocompleteAdapterViewListener = new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
final AutocompletePrediction item = placeAutocompleteAdapter.getItem(position);
final String placeid = item.getPlaceId();
PendingResult<PlaceBuffer> placeResult = Places.GeoDataApi.getPlaceById(mGoogleApiClient,placeid);
placeResult.setResultCallback(mUpdatePlaceDetailsCallback);
}
};
private ResultCallback<PlaceBuffer> mUpdatePlaceDetailsCallback = new ResultCallback<PlaceBuffer>() {
@Override
public void onResult(@NonNull PlaceBuffer places) {
if(!places.getStatus().isSuccess()){
Log.i(TAG, "onResult: Place query did not complete"+places.getStatus().toString());
places.release();
}
final Place place = places.get(0);
Log.i(TAG, "onResult: Name:"+place.getName());
Log.i(TAG, "onResult: Latitude:"+place.getLatLng().latitude);
Log.i(TAG, "onResult: Longtitude:"+place.getLatLng().longitude);
selectedname=place.getName().toString();
selectedLatLng=place.getLatLng();
MoveCamera(selectedLatLng,DEFAULT_ZOOM,selectedname);
places.release();
Log.i(TAG, "onResult: Name:"+selectedname);
Log.i(TAG, "onResult: Selected LAtLng"+selectedLatLng);
}
};
private void NextActivity(){
if(selectedLatLng!=null && !selectedname.equals("")){
Intent intent = new Intent(getApplicationContext(),CheckoutActivity.class);
SharedPrefManager.getInstance(getApplicationContext()).SaveLocation(selectedname,selectedLatLng);
startActivity(intent);
}
else{
showErrorMsg("Location Cannot be Empty");
}
}
public void showErrorMsg(String message){
new AlertDialog.Builder(this)
.setTitle("Oops")
.setMessage(message)
.setPositiveButton(android.R.string.ok,null)
.show();
}
}
Upvotes: 1
Views: 2062
Reputation: 474
This is where you need to start doing some digging around to find where there is heavy lifting in your activity and make a Thread/AyscTask/Worker do the work instead of your main thread. This is a warning/error because your main thread handles rendering the GUI of your application and your telling it to do a lot of calculations which make the application look like it's frozen.
Once you find where there is a lot of work your main thread is doing you can create something like a Thread and Runnable that the Thread will be running on.
private Thread thread = null;
private final Runnable thread_DoWork = new Runnable() {
@Override public void run() {
// Your code here or call some function to run for the thread
someHeavyLiftingFunction();
}
};
Below is how you create and tell the Thread to start working on the Runnable you gave it.
// Check if already created/started
if (thread == null) {
// Create new thread
thread = new Thread(thread_DoWork);
// Start Thread in background
thread.start();
}
That is pretty much it. Your main Thread will be freed up. There are some other types of workers/threads that have more build in functionality like a callback function that gets called when the thread is done doing work (AsyncTask Android example).
Upvotes: 1