Geocoder freez application for 3 or 4 seconds when try to search by place name - performance

i create app for location base data i'm using geocoder to fetch places data but its hang for 3 or 4 seconds but after loads data correctly
its android studio java based for getting city name or district from geocoder
after freez its gets results correctly
public void getLocation(String type) {
List<String> items = new ArrayList<>();
Dialog dialog = new Dialog(buyersetting.this, android.R.style.Theme_Light);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(R.layout.location_dialog);
dialog.show();
ListView listView = (ListView) dialog.findViewById(R.id.listview);
EditText etsearch = dialog.findViewById(R.id.searcchloc);
etsearch.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
Geocoder geocoder = new Geocoder(buyersetting.this, Locale.getDefault());
try {
List<Address> result = geocoder.getFromLocationName(s.toString(), 10);
if ((result == null) || (result.isEmpty())) {
} else {
items.clear();
for (int i = 0; i < result.size(); i++) {
items.add(result.get(i).getLocality());
}
MyArrayAdapter adapter = new MyArrayAdapter(buyersetting.this, android.R.layout.simple_list_item_1, items);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (type == "city")
bind.city.setText(parent.getItemAtPosition(position).toString());
if (type == "dist") {
bind.dist.setText(parent.getItemAtPosition(position).toString());
}
dialog.dismiss();
}
});
}
} catch (IOException e) {
e.printStackTrace();
}
}
});
dialog.show();
}

Related

It takes a long time to load large data in recyclerview

I have 11 text files each containing 50-60 lines. I have read all the files and showed in the recyclerview. I used asynctask to track the progress through the progress bar. I have used log too to see the read lines. I have found that reading is taking short time but after reading, it takes 5-6 seconds to show data in the recyclerview. Why is this causing? What should i do to handle this? Why should i do if there are thousands of text files?
Codes reading files and binding
AsyncTask<Void,Void,Void> task = new AsyncTask<Void, Void, Void>() {
ProgressDialog progressDialog;
#Override
protected void onPreExecute() {
progressDialog = ProgressDialog.show(GrammerDetails.this,
"Loading", "Please Wait for a while");
}
#Override
protected Void doInBackground(Void... voids) {
getFromFilesbagdhara(id,realm);
SharedPreferences.Editor editor = preferences.edit();
editor.putBoolean("first_bagdhara",false);
editor.apply();
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
inflateData(listGrammerItem);
progressDialog.dismiss();
}
}.execute();
private void getFromFilesbagdhara(String id, Realm realm) {
String directory = "Grammer/Bagdhara";
AssetManager man = getAssets();
BufferedReader reader = null;
try {
String[] files = man.list(directory);
for (int i =0;i<files.length;i++){
String fileName = files[i];
reader = new BufferedReader(
new InputStreamReader(getAssets().open(directory+"/" + fileName),
"UTF-8"));
String line;
Log.e("File",files[i]);
while ((line = reader.readLine()) != null) {
Log.e("line",line);
// String[] text = line.split(" ");
String a = line.substring(0,line.indexOf("(")-1);
String b = line.substring(line.indexOf("(")+1,line.indexOf(")"));
String wordOne = a;
// String dummyTwo = text[1];
String wordTwo = b; //dummyTwo.substring(1,dummyTwo.length()-1);
final ClassGrammerItem classGrammerItem = new ClassGrammerItem(wordOne,wordTwo,id);
listGrammerItem.add(classGrammerItem);
}
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
//log the exception
}
}
}
}
private void inflateData(RealmList<ClassGrammerItem> listGrammerItem) {
AdapterGrammerItem adapter = new AdapterGrammerItem(listGrammerItem, GrammerDetails.this);
recyclerView.setAdapter(adapter);
}
Adapter:
public class AdapterGrammerItem extends RecyclerView.Adapter<AdapterGrammerItem
.ViewHolderAdapterRecycler> {
RealmList<ClassGrammerItem> activityList = new RealmList<ClassGrammerItem>();
Context context;
private LayoutInflater layoutInflater;
public AdapterGrammerItem(RealmList<ClassGrammerItem> activityList, Context context) {
this.activityList = activityList;
this.context = context;
layoutInflater = LayoutInflater.from(context);
}
#Override
public AdapterGrammerItem.ViewHolderAdapterRecycler onCreateViewHolder(ViewGroup parent, int viewType) {
View view = layoutInflater.inflate(R.layout.recycler_grammer_item, parent, false);
AdapterGrammerItem.ViewHolderAdapterRecycler viewHolder = new AdapterGrammerItem.ViewHolderAdapterRecycler(view);
return viewHolder;
}
#Override
public void onBindViewHolder(AdapterGrammerItem.ViewHolderAdapterRecycler holder, int position) {
ClassGrammerItem currentItem = activityList.get(position);
holder.wordOne.setText(currentItem.getWordOne());
holder.wordTwo.setText(currentItem.getWordTwo());
}
#Override
public int getItemCount() {
return activityList.size();
}
public class ViewHolderAdapterRecycler extends RecyclerView.ViewHolder {
MyTextView wordOne, wordTwo;
public ViewHolderAdapterRecycler(View itemView) {
super(itemView);
wordOne = (MyTextView) itemView.findViewById(R.id.wordOne);
wordTwo = (MyTextView) itemView.findViewById(R.id.wordTwo);
}
}
}

Android - Xamarin - Fused Location

I am trying to implement a custom activity that initialises the Fused Location services in Xamarin c# so I can reuse this activity whenever the Fused Location is needed. The problem that I am having is that the map is being loaded before the location services. This way, I cannot animate the camera to zoom in at the user's location since the location is still null.
Here is the custom activity:
using System;
using Android.App;
using Android.Gms.Common;
using Android.Gms.Common.Apis;
using Android.Gms.Maps.Model;
using Android.Locations;
using Android.OS;
using Android.Gms.Location;
using Android.Widget;
namespace Maps.Droid.LocationService {
public class LocationTrackerActivity : Activity, GoogleApiClient.IConnectionCallbacks, GoogleApiClient.IOnConnectionFailedListener, Android.Gms.Location.ILocationListener {
// Static Fields
public static long MIN_DISTANCE_CHANGE_FOR_UPDATES = 5; // 5 meters
public static long MIN_TIME_BW_UPDATES = 1000 * 10; // 10 seconds
private Location currentLocation;
private Activity activity;
private bool hasGooglePlayServices;
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
private bool locationAvailable = false;
protected override void OnCreate(Bundle savedInstanceState) {
base.OnCreate(savedInstanceState);
this.activity = this;
hasGooglePlayServices = checkPlayServices();
if (hasGooglePlayServices) {
initFusedLocation();
} else {
initAndroidLocation();
}
}
private void initFusedLocation() {
mLocationRequest = new LocationRequest();
mLocationRequest.SetInterval(LocationTrackerActivity.MIN_TIME_BW_UPDATES);
mLocationRequest.SetFastestInterval(LocationTrackerActivity.MIN_TIME_BW_UPDATES / 2);
mLocationRequest.SetSmallestDisplacement(LocationTrackerActivity.MIN_DISTANCE_CHANGE_FOR_UPDATES);
mLocationRequest.SetPriority(LocationRequest.PriorityHighAccuracy);
mGoogleApiClient = new GoogleApiClient.Builder(Application.Context)
.AddConnectionCallbacks(this)
.AddOnConnectionFailedListener(this)
.AddApi(LocationServices.API)
.Build();
}
protected override void OnResume() {
base.OnResume();
if (mGoogleApiClient.IsConnected) {
LocationServices.FusedLocationApi.RequestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
}
protected override void OnPause() {
base.OnPause();
// Stop location updates to save battery, but don't disconnect the GoogleApiClient object.
if (mGoogleApiClient.IsConnected) {
LocationServices.FusedLocationApi.RemoveLocationUpdates(mGoogleApiClient, this);
}
}
protected override void OnStart() {
base.OnStart();
mGoogleApiClient.Connect();
}
protected override void OnStop() {
base.OnStop();
// only stop if it's connected, otherwise we crash
if (mGoogleApiClient != null) {
mGoogleApiClient.Disconnect();
}
}
private void initAndroidLocation() {
}
private bool checkPlayServices() {
GoogleApiAvailability apiAvailability = GoogleApiAvailability.Instance;
int resultCode = apiAvailability.IsGooglePlayServicesAvailable(activity);
if (resultCode != ConnectionResult.Success) {
// In case we want to tell the user to install or update Google Play Services
//if (apiAvailability.IsUserResolvableError(resultCode)) {
// apiAvailability.GetErrorDialog(activity, resultCode, PLAY_SERVICES_RESOLUTION_REQUEST).Show();
//} else {
// Toast.MakeText(activity, "This device is not supported", ToastLength.Long).Show();
//}
return false;
}
return true; // has google play services installed
}
public double getLatitude() {
return currentLocation == null ? 0.0 : currentLocation.Latitude;
}
public double getLongitude() {
return currentLocation == null ? 0.0 : currentLocation.Longitude;
}
public bool canGetLocation() {
return locationAvailable;
}
public LatLng getLatLng() {
return new LatLng(currentLocation.Latitude, currentLocation.Longitude);
}
public void OnConnected(Bundle connectionHint) {
// Get last known recent location. If the user launches the activity,
// moves to a new location, and then changes the device orientation, the original location
// is displayed as the activity is re-created.
if (currentLocation == null && mGoogleApiClient.IsConnected) {
currentLocation = LocationServices.FusedLocationApi.GetLastLocation(mGoogleApiClient);
}
Console.WriteLine("location is about to be set to true");
locationAvailable = true;
LocationServices.FusedLocationApi.RequestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
public void OnConnectionSuspended(int cause) {
// GoogleApiClient will automatically attempt to restore the connection.
// Applications should disable UI components that require the service, and wait for a call to onConnected(Bundle) to re-enable them
if (cause == GoogleApiClient.ConnectionCallbacks.CauseServiceDisconnected) {
Toast.MakeText(activity, "Location Services disconnected. Please re-connect.", ToastLength.Long).Show();
} else if (cause == GoogleApiClient.ConnectionCallbacks.CauseNetworkLost) {
Toast.MakeText(activity, "Network lost. Please re-connect.", ToastLength.Long).Show();
}
}
public void OnConnectionFailed(ConnectionResult result) {
Console.WriteLine("Connection failed: " + result.ToString());
}
public void OnLocationChanged(Location location) {
currentLocation = location;
}
}
}
Here is the class that inherit the custom class:
using Android.App;
using Android.OS;
using Maps.Droid.LocationService;
namespace Maps.Droid {
[Activity(Label = "Map Activity")]
public class MapActivity : LocationTrackerActivity {
// Properties
protected override void OnCreate(Bundle savedInstanceState) {
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.map_activity);
var mapFrag = new MapViewFragment();
var ft = FragmentManager.BeginTransaction();
ft.Add(Resource.Id.map_container, mapFrag);
ft.Commit();
}
}
}
Here is the fragment in the inherited activity:
using System;
using Android.App;
using Android.OS;
using Android.Views;
using Android.Gms.Maps;
namespace Maps.Droid {
public class MapViewFragment : Fragment, IOnMapReadyCallback {
// private Activity activity;
private GoogleMap map;
private MapActivity parent;
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.Inflate(Resource.Layout.map_fragment, null);
parent = ((MapActivity)Activity);
MapFragment frag = this.FragmentManager.FindFragmentById<MapFragment>(Resource.Id.map);
frag.GetMapAsync(this);
return view;
}
public void OnMapReady(GoogleMap googleMap) {
if (googleMap != null) {
map = googleMap;
var zoomVariance = 0.2;
var defaultZoom = 16f;
var currentZoomLevel = map.CameraPosition.Zoom;
map.MapType = GoogleMap.MapTypeNormal;
map.MyLocationEnabled = true;
map.CameraChange += delegate (object sender, GoogleMap.CameraChangeEventArgs e) {
if (Math.Abs(e.Position.Zoom - currentZoomLevel) < zoomVariance) {
return;
}
currentZoomLevel = e.Position.Zoom;
Console.WriteLine("Zooming " + currentZoomLevel);
};
map.UiSettings.ZoomControlsEnabled = true;
map.UiSettings.CompassEnabled = true;
map.UiSettings.SetAllGesturesEnabled(true); // Zoom, Tilt, Scroll, Rotate
if (parent.canGetLocation()) {
// ***** PROBLEM HERE ******* canGetLocation is set to true just afterwards.
map.AnimateCamera(CameraUpdateFactory.NewLatLngZoom(parent.getLatLng(), defaultZoom)); // Mosaic coordinates
}
}
}
}
}
I was thinking of implementing a call back to LocationTrackerActivity. So when the location services become available the class MapActivity then would be able to load the MapViewFragment within that custom callback. This way the location services would be loaded before the map. Therefore, this part of the code would always execute :
if (parent.canGetLocation()) {
// ***** PROBLEM HERE ******* canGetLocation is set to true just afterwards.
map.AnimateCamera(CameraUpdateFactory.NewLatLngZoom(parent.getLatLng(), defaultZoom)); // Mosaic coordinates
}
However I have no idea how to customise a callback. Maybe there are better solutions to this problem?
The problem can be because of OnConnected method. That's my OnConnected method for FusedLocationProvider in Xamarin. You can take a look on it.
public async void OnConnected(Bundle bundle)
{
Location location = LocationServices.FusedLocationApi.GetLastLocation(apiClient);
if (location != null)
{
latitude = location.Latitude;
longitude = location.Longitude;
locRequest.SetPriority(100);
locRequest.SetFastestInterval(500);
locRequest.SetInterval(1000);
await LocationServices.FusedLocationApi.RequestLocationUpdates(apiClient, locRequest, this);
}
}
When it is connected, i set the latitude and longitude values. Then in my onMapReady method, i create a new LatLng variable with these latitude and longitude variables.
void IOnMapReadyCallback.OnMapReady(GoogleMap myMap)
{
this.myMap = myMap;
myMarker = new MarkerOptions();
locCoordinates = new LatLng(latitude, longitude);
myMap.MapType = GoogleMap.MapTypeNormal;
myMap.UiSettings.ZoomControlsEnabled = true;
myMap.AnimateCamera(CameraUpdateFactory.NewLatLngZoom(locCoordinates, 10));
}
UPDATE:
I have managed to find a solution. If the user has google play services then use FusedLocation Services, if the user does not then we use Android Location Services. Then we only have to interact with one object of the type LocationTracker and everything is done by this interface:
namespace Maps.Droid.LocationService {
public interface LocationInterface {
void startLocationServices();
void stopLocationServices();
void pauseLocationServices();
void resumeLocationServices();
double getLatitude();
double getLongitude();
bool canGetLocation();
}
}
using System;
using Android.App;
using Android.Gms.Location;
using Android.Gms.Common.Apis;
using Android.OS;
using Android.Gms.Maps.Model;
using Android.Widget;
using Android.Locations;
using Android.Gms.Common;
using Android.Gms.Maps;
namespace Maps.Droid.LocationService {
public class FusedLocation : Java.Lang.Object, GoogleApiClient.IConnectionCallbacks, GoogleApiClient.IOnConnectionFailedListener, Android.Gms.Location.ILocationListener {
private Activity activity;
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
private Location currentLocation;
private bool locationAvailable = false;
private GoogleMap map;
public FusedLocation(Activity activity) {
this.activity = activity;
mLocationRequest = new LocationRequest();
mLocationRequest.SetInterval(LocationTracker.MIN_TIME_BW_UPDATES);
mLocationRequest.SetFastestInterval(LocationTracker.MIN_TIME_BW_UPDATES / 2);
mLocationRequest.SetSmallestDisplacement(LocationTracker.MIN_DISTANCE_CHANGE_FOR_UPDATES);
mLocationRequest.SetPriority(LocationRequest.PriorityHighAccuracy);
mGoogleApiClient = new GoogleApiClient.Builder(Application.Context)
.AddConnectionCallbacks(this)
.AddOnConnectionFailedListener(this)
.AddApi(LocationServices.API)
.Build();
}
public Location getCurrentLocation() {
return currentLocation;
}
public void setMap(GoogleMap map) {
this.map = map;
}
public double getLatitude() {
return currentLocation.Latitude;
}
public double getLongitude() {
return currentLocation.Longitude;
}
public void OnResume() {
if (mGoogleApiClient.IsConnected) {
LocationServices.FusedLocationApi.RequestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
}
public void OnPause() {
// Stop location updates to save battery, but don't disconnect the GoogleApiClient object.
if (mGoogleApiClient.IsConnected) {
LocationServices.FusedLocationApi.RemoveLocationUpdates(mGoogleApiClient, this);
}
}
public void OnStart() {
mGoogleApiClient?.Connect();
}
public void OnStop() {
// only stop if it's connected, otherwise we crash
if (mGoogleApiClient.IsConnected) {
mGoogleApiClient?.Disconnect();
}
}
public LatLng getLatLng() {
return new LatLng(currentLocation.Latitude, currentLocation.Longitude);
}
public bool canGetLocation() {
return locationAvailable && currentLocation != null;
}
public void OnConnected(Bundle connectionHint) {
// Get last known recent location. If the user launches the activity,
// moves to a new location, and then changes the device orientation, the original location
// is displayed as the activity is re-created.
currentLocation = LocationServices.FusedLocationApi.GetLastLocation(mGoogleApiClient);
if (currentLocation != null) {
locationAvailable = true;
LocationServices.FusedLocationApi.RequestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
if (map != null) {
map.AnimateCamera(CameraUpdateFactory.NewLatLngZoom(getLatLng(), LocationTracker.DEFAULT_ZOOM));
}
}
}
public void OnConnectionSuspended(int cause) {
// GoogleApiClient will automatically attempt to restore the connection.
// Applications should disable UI components that require the service, and wait for a call to onConnected(Bundle) to re-enable them
if (cause == GoogleApiClient.ConnectionCallbacks.CauseServiceDisconnected) {
Toast.MakeText(activity, "Location Services disconnected. Please re-connect.", ToastLength.Long).Show();
} else if (cause == GoogleApiClient.ConnectionCallbacks.CauseNetworkLost) {
Toast.MakeText(activity, "Network lost. Please re-connect.", ToastLength.Long).Show();
}
}
public void OnLocationChanged(Location location) {
currentLocation = location;
}
public void OnConnectionFailed(ConnectionResult result) {
Console.WriteLine("Connection failed: " + result.ToString());
}
}
}
using System;
using Android.OS;
using Android.Locations;
using Android.Runtime;
using Android.App;
using Android.Content;
using Android.Widget;
using Android.Gms.Maps.Model;
using Java.Util.Concurrent;
namespace Maps.Droid.LocationService {
public class AndroidLocation : Java.Lang.Object, ILocationListener {
// Properties
private LocationManager locMgr;
private Activity activity;
private Location locationGPS, locationNetwork/*, locationPassive*/, currentLocation;
private bool locationAvailable = false;
private Android.Gms.Maps.GoogleMap map;
// UNCOMMNET
// private bool isPassiveEnabled = false; // Gets location from other apps that uses Location Services
// Initializer method (Constructor). Call this method onCreate
public AndroidLocation(Activity activity) {
this.activity = activity;
getLocation();
}
public Location getCurrentLocation() {
return currentLocation;
}
public void setMap(Android.Gms.Maps.GoogleMap map) {
this.map = map;
}
private Location getLocation() {
// Use Standard Android Location Service Provider
try {
locMgr = activity.GetSystemService(Context.LocationService) as LocationManager;
bool isGPSEnabled = locMgr.IsProviderEnabled(LocationManager.GpsProvider);
// Varying precision, Less power consuming. Combination of WiFi and Cellular data
bool isNetworkEnabled = locMgr.IsProviderEnabled(LocationManager.NetworkProvider);
// UNCOMMENT
// bool isPassiveEnabled = locMgr.IsProviderEnabled(LocationManager.GpsProvider);
// UNCOMMNET
//if (isPassiveEnabled) {
// locMgr.RequestLocationUpdates(LocationManager.PassiveProvider, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
// locationPassive = locMgr.GetLastKnownLocation(LocationManager.PassiveProvider);
//}
if (isGPSEnabled) {
locMgr.RequestLocationUpdates(LocationManager.GpsProvider, LocationTracker.MIN_TIME_BW_UPDATES, LocationTracker.MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
locationGPS = locMgr?.GetLastKnownLocation(LocationManager.GpsProvider);
}
if (isNetworkEnabled) {
locMgr.RequestLocationUpdates(LocationManager.NetworkProvider, LocationTracker.MIN_TIME_BW_UPDATES, LocationTracker.MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
locationNetwork = locMgr?.GetLastKnownLocation(LocationManager.NetworkProvider);
}
// UNCOMMENT - Method must be implement if PassiveLocation is to be used
// currentLocation = getBestLocation(locationGPS, locationNetwork, locationPassive);
currentLocation = getBestLocation(locationNetwork, locationGPS);
if (currentLocation != null) {
locationAvailable = true;
if (map != null) {
map.AnimateCamera(Android.Gms.Maps.CameraUpdateFactory.NewLatLngZoom(getLatLng(), LocationTracker.DEFAULT_ZOOM));
}
}
} catch (Exception e) {
Console.WriteLine("ERROR: getLocation() " + e.ToString());
}
return currentLocation;
}
// Determines the most recent and/or most accurate location
private Location getBestLocation(Location loc1, Location loc2) {
if (loc1 == null || loc2 == null) {
return loc1 ?? loc2; // If either location is null then return the not null location
}
long time1 = TimeUnit.Milliseconds.ToSeconds(loc1.Time);
long time2 = TimeUnit.Milliseconds.ToSeconds(loc2.Time);
long twiceUpdate = (LocationTracker.MIN_TIME_BW_UPDATES / 1000) * 2;
if (Math.Abs(time1 - time2) > twiceUpdate) { // If location times are more than twiceUpdate apart
if (time1 > time2) { // More time value, most current time
return loc1;
} else {
return loc2;
}
} else {
float accuracy1 = loc1.Accuracy;
float accuracy2 = loc2.Accuracy;
// Smaller the value (meters), the greater the accuracy
if (accuracy1 < accuracy2) {
return loc1;
} else {
return loc2;
}
}
}
public void OnStop() {
locMgr = null;
}
public void OnPause() {
locMgr?.RemoveUpdates(this);
}
public void OnStart() {
}
public void OnResume() {
if (locMgr == null || currentLocation == null) {
getLocation();
}
}
public bool canGetLocation() {
return locationAvailable;
}
public LatLng getLatLng() {
return new LatLng(currentLocation.Latitude, currentLocation.Longitude);
}
public double getLatitude() {
return currentLocation.Latitude;
}
public double getLongitude() {
return currentLocation.Longitude;
}
public void OnLocationChanged(Location location) {
currentLocation = getBestLocation(currentLocation, location);
}
// User disabled a provider
public void OnProviderDisabled(string provider) {
getLocation(); // Check if all providers are disabled and pop up alertDialog if they are so
}
// User enabled a provider
public void OnProviderEnabled(string provider) {
getLocation(); // Update all available providers for getting the best provider available
}
public void OnStatusChanged(string provider, [GeneratedEnum] Availability status, Bundle extras) {
}
}
}
using Android.App;
using Android.Gms.Common;
using Android.Gms.Common.Apis;
using Android.Gms.Maps.Model;
using Android.Gms.Maps;
using Android.Locations;
using Android.Content;
using Android.Widget;
namespace Maps.Droid.LocationService {
public class LocationTracker {
public static long MIN_DISTANCE_CHANGE_FOR_UPDATES = 5; // 5 meters
public static long MIN_TIME_BW_UPDATES = 1000 * 15; // 15 seconds ok, 5 seconds really fast, 30s slow
public static float DEFAULT_ZOOM = 16f;
private bool hasGooglePlayServices;
public GoogleApiClient mGoogleApiClient;
private FusedLocation fusedLocation;
private AndroidLocation androidLocation;
private bool locationIsDisabled;
public LocationTracker(Activity activity) {
if (locationIsDisabled = isLocationDisabled(activity)) {
showSettingsAlert(activity);
} else {
hasGooglePlayServices = checkPlayServices(activity);
if (hasGooglePlayServices) {
fusedLocation = new FusedLocation(activity);
} else {
androidLocation = new AndroidLocation(activity);
}
}
}
private void showSettingsAlert(Activity activity) {
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.SetTitle("Location Services Not Active");
builder.SetMessage("Please enable Location Services and GPS");
builder.SetPositiveButton("OK", delegate {
// Show location settings when the user acknowledges the alert dialog
var intent = new Intent(Android.Provider.Settings.ActionLocationSourceSettings);
activity.StartActivity(intent);
});
builder.SetNegativeButton("Cancel", delegate {
Toast.MakeText(activity, "Location disabled by user", ToastLength.Short).Show();
});
AlertDialog alertDialog = builder.Create();
alertDialog.SetCanceledOnTouchOutside(false);
alertDialog.Show();
}
private bool isLocationDisabled(Activity activity) {
LocationManager locMgr = activity.GetSystemService(Context.LocationService) as LocationManager;
// More precise, More power consuming
bool isGPSEnabled = locMgr.IsProviderEnabled(LocationManager.GpsProvider);
// Varying precision, Less power consuming. Combination of WiFi and Cellular data
bool isNetworkEnabled = locMgr.IsProviderEnabled(LocationManager.NetworkProvider);
// UNCOMMENT
// bool isPassiveEnabled = locMgr.IsProviderEnabled(LocationManager.PassiveProvider);
// UNCOMMENT
// return !isGPSEnabled && !isNetworkEnabled && !isPassiveEnabled; // True only when the 3 location services are disabled
return !isGPSEnabled && !isNetworkEnabled; // True only when both location services are disabled
}
// Call this method at OnMapReady callback if initial zooming/animation on user's location is desired
public void setMap(GoogleMap map) {
if (locationIsDisabled) {
return;
}
if (hasGooglePlayServices) {
fusedLocation.setMap(map);
} else {
androidLocation.setMap(map);
}
}
public void OnResume() {
if (locationIsDisabled) {
return;
}
if (hasGooglePlayServices) {
fusedLocation.OnResume();
} else {
androidLocation.OnResume();
}
}
public void OnPause() {
if (locationIsDisabled) {
return;
}
if (hasGooglePlayServices) {
fusedLocation.OnPause();
} else {
androidLocation.OnPause();
}
}
public void OnStart() {
if (locationIsDisabled) {
return;
}
if (hasGooglePlayServices) {
fusedLocation.OnStart();
} else {
androidLocation.OnStart();
}
}
public void OnStop() {
if (locationIsDisabled) {
return;
}
if (hasGooglePlayServices) {
fusedLocation.OnStop();
} else {
androidLocation.OnStop();
}
}
private bool checkPlayServices(Activity activity) {
GoogleApiAvailability apiAvailability = GoogleApiAvailability.Instance;
int resultCode = apiAvailability.IsGooglePlayServicesAvailable(activity);
if (resultCode == ConnectionResult.Success) {
return true;
}
return false;
}
public double getLatitude() {
if (locationIsDisabled) {
return 0;
}
if (hasGooglePlayServices) {
return fusedLocation.getCurrentLocation() == null ? 0.0 : fusedLocation.getLatitude();
} else {
return androidLocation.getCurrentLocation() == null ? 0.0 : androidLocation.getLatitude();
}
}
public double getLongitude() {
if (locationIsDisabled) {
return 0;
}
if (hasGooglePlayServices) {
return fusedLocation.getCurrentLocation() == null ? 0.0 : fusedLocation.getLongitude();
} else {
return androidLocation.getCurrentLocation() == null ? 0.0 : androidLocation.getLongitude();
}
}
public bool canGetLocation() {
if (locationIsDisabled) {
return false;
}
if (hasGooglePlayServices) {
return fusedLocation.canGetLocation();
} else {
return androidLocation.canGetLocation();
}
}
public LatLng getLatLng() {
if (locationIsDisabled) {
return null;
}
LatLng latlng;
if (hasGooglePlayServices) {
latlng = fusedLocation.getLatLng();
} else {
latlng = androidLocation.getLatLng();
}
return latlng;
}
public Location getCurrentLocation() {
if (hasGooglePlayServices) {
return fusedLocation.getCurrentLocation();
} else {
return androidLocation.getCurrentLocation();
}
}
}
}
Then to use it on your fragment or activity:
Initialise it at OnCreate:
Location tracker = new LocationTracker(this.Activity);
make a referent for the life cycles:
public override void OnResume() {
base.OnResume();
tracker.OnResume();
}
public override void OnPause() {
base.OnPause();
tracker.OnPause();
}
public override void OnStart() {
base.OnStart();
tracker.OnStart();
}
public override void OnStop() {
base.OnStop();
tracker.OnStop();
}
if you want the animation to zoom at the users location in the beginning, then you have to add this line of code when you have the googlemap:
tracker.setMap(googleMap); // Invoke this method if zooming/animating to the user's location is desired
Spent many days on this solution. Hope it can help somebody!

Recycler View with Header and Edit Text

I have a recyclerview with a header achieved by using two different element types. In my header there is an edit text which I want to use for filtering the nonheader elements of the list. Below is my current implementation, I have one concern and one problem with it.
My concern is that what I am doing in publishResults with the notifyItemRangeRemoved and notifyItemInserted is the wrong way to update the recycler view. I originally was doing notifyDatasetChanged but his would cause the header row to be refreshed too and the edit text to lose focus. What I really want is a way to refresh only the item rows and leave the header row untouched.
My current problem is that with the existing code if I scroll down too much the edit text looses focus. I want the edit text to keep focus even if I scroll to the bottom of the list.
The code used to use a ListView with setHeaderView and that worked somehow so there must be someway of achieving the goal just not sure what the trick with a recycler view is. Any help is much appreciated.
public class SideListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements Filterable {
private static final int TYPE_HEADER = 0;
private static final int TYPE_ITEM = 1;
private final List<String> data;
public List<String> filteredData;
private HeaderActionListener headerActionListener;
public SideListAdapter(Context context, ArrayList<String> data, HeaderActionListener headerActionListener) {
this.data = data;
filteredData = new ArrayList<>(data);
this.context = context;
this.headerActionListener = headerActionListener;
}
#Override
public Filter getFilter() {
return new TestFilter();
}
static class SideListItem extends RecyclerView.ViewHolder {
LinearLayout baseLayout;
public SideListItem(View itemView) {
super(itemView);
baseLayout = (LinearLayout) itemView.findViewById(R.id.settings_defaultcolor);
}
}
class SideListHeader extends SideListHeader {
EditText sort;
public SideListHeaderLoggedIn(View itemView) {
super(itemView);
sort = (EditText) itemView.findViewById(R.id.sort);
}
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == TYPE_ITEM) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false);
return new SideListItem(v);
} else if (viewType == SideListHeader) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.header, parent, false);
return new SideListHeader(v);
}
throw new RuntimeException("there is no type that matches the type " + viewType + " + make sure your using types correctly");
}
public interface HeaderActionListener {
boolean onSortEditorAction(TextView arg0, int arg1, KeyEvent arg2);
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
if (holder instanceof SideListHeader) {
final SideListHeader sideListHeader = (SideListHeader) holder;
sideListHeader.sort.setOnEditorActionListener(new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
}
});
sideListHeader.sort.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) {
}
#Override
public void afterTextChanged(Editable editable) {
String result = sideListHeader.sort.getText().toString().replaceAll(" ", "");
getFilter().filter(result);
}
});
}
if (holder instanceof SideListItem) {
// Inflate normal item //
}
}
// need to override this method
#Override
public int getItemViewType(int position) {
if (isPositionHeader(position)) {
return TYPE_HEADER;
}
return TYPE_ITEM;
}
private boolean isPositionHeader(int position) {
return position == 0;
}
//increasing getItemcount to 1. This will be the row of header.
#Override
public int getItemCount() {
return filteredData.size() + 1;
}
private class TestFilter extends Filter {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
String prefix = constraint.toString().toLowerCase();
if (prefix.isEmpty()) {
ArrayList<String> list = new ArrayList<>(data);
results.values = list;
results.count = list.size();
} else {
final ArrayList<String> list = new ArrayList<>(data);
final ArrayList<String> nlist = new ArrayList<>();
for (int i = 0 ; i < list.size(); i++) {
String item = list.get(i);
if (item.contains(prefix)) {
nlist.add(item);
}
}
results.values = nlist;
results.count = nlist.size();
}
return results;
}
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
notifyItemRangeRemoved(1, getItemCount()-1);
filteredData.clear();
filteredData.addAll((List<String>)results.values);
for(int i = 1; i < getItemCount() - 1; i++){
notifyItemInserted(i);
}
}
}
}
I'm not sure how correct this way is, but in my code I implemented it like that
private var headerList: List<HeaderItem> = listOf(HeaderItem("Title"))
private fun searchItem(items: List<Items>, query: String) {
items.filterIsInstance<MainItem>().filter { filteredItems ->
filteredItems.header.lowercase().contains(query.lowercase())
}.let { searchedItems ->
rvAdapter.submitList(headerList + searchedItems)
}
}
This way I was able to preserve header element when I did my search

Recyclerview adapter with asyncTask

I'm trying to use custom adapter with RecyclerView, but the holders are empty. I can't understand what did i miss. Please help.
In MainActivity's AsyncTask:
#Override
protected void onPostExecute(String result) {
json_result = result;
super.onPostExecute(result);
dialog.dismiss();
if (result == null) {
Toast.makeText(MainActivity.this, "error getting results...", Toast.LENGTH_LONG).show();
} else {
try {
JSONObject json = new JSONObject(result);
Log.e(TAG, "create json object");
JSONArray searchArray = json.getJSONArray("Search");
Log.e(TAG, "Search");
for (int i = 0; i < searchArray.length(); i++) {
Log.e(TAG, "run on length");
JSONObject searchObject = searchArray.getJSONObject(i);
Log.e(TAG, "create search object");
String title = searchObject.getString("Title");
Log.e(TAG, "Title" + title);
String type = searchObject.getString("Type");
Log.e(TAG, "Type" + type);
String year = searchObject.getString("Year");
Log.e(TAG, "Year" + year);
String imdbID = searchObject.getString("imdbID");
String poster = searchObject.getString("Poster");
Log.e(TAG, "" + result);
movieList.add(new Movie(title, type, year, imdbID, poster));
Log.e(TAG, "Add to adapter");
}
} catch (JSONException e) {
e.printStackTrace();
Toast.makeText(MainActivity.this, "error parsing results...", Toast.LENGTH_LONG).show();
}
adapter.notifyDataSetChanged();
Log.e(TAG, "Notify");
}
}
Custom Adapter:
public class Adapter extends
RecyclerView.Adapter<Adapter.ViewHolder> {
private LruCache<String, Bitmap> bitmapCache;
Context context;
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView title;
public TextView year;
public TextView type;
public ImageView poster;
public ViewHolder(View itemView) {
super(itemView);
title = (TextView) itemView.findViewById(R.id.txt_title);
year = (TextView) itemView.findViewById(R.id.txt_year);
type = (TextView) itemView.findViewById(R.id.txt_rating);
poster = (ImageView) itemView.findViewById(R.id.imageView);
}
}
private List<Movie> mList;
public Adapter(List<Movie> mList) {
this.mList = mList;
int numImages = 4 * 1024 * 1024;
this.bitmapCache = new LruCache<String, Bitmap>(numImages) {
#Override
protected int sizeOf(String key, Bitmap value) {
// this is how to calculate a bitmap size in bytes.
// (bytes-in-a-row * height)
return value.getRowBytes() * value.getHeight();
}
};
}
#Override
public Adapter.ViewHolder onCreateViewHolder
(ViewGroup parent, int viewType) {
Context context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context);
View movieView = inflater.inflate(R.layout.card_view, parent, false);
ViewHolder viewHolder = new ViewHolder(movieView);
return viewHolder;
}
#Override
public void onBindViewHolder
(Adapter.ViewHolder holder, int position) {
Movie movie = mList.get(position);
holder.title.setText(movie.getTitle());
holder.year.setText(movie.getYear());
holder.type.setText(movie.getType());
holder.poster.setVisibility(View.INVISIBLE);
GetImageTask task = new GetImageTask(movie, holder);
task.execute(movie.getPoster_url());
}
#Override
public int getItemCount() {
return mList.size();
}
class GetImageTask extends AsyncTask<String, Void, Bitmap> {
private final Movie movie;
private final ViewHolder holder;
public GetImageTask(Movie movie, ViewHolder holder) {
this.movie = movie;
this.holder = holder;
}
#Override
protected Bitmap doInBackground(String... params) {
//download:
String address = params[0];
Bitmap bitmap = HttpHandler.getBitmap(address, null);
//save it in the cache for later:
if (bitmap != null) {
bitmapCache.put(address, bitmap);
}
return bitmap;
}
#Override
protected void onPostExecute(Bitmap result) {
if (movie.equals(holder.poster)) {
holder.poster.setVisibility(View.VISIBLE);
holder.poster.setImageBitmap(result);
}
}
}
}
I think the problem is that my movie class is empty, but i do have JSON results in asynctask...
Your received data , which you have saved in the list -->movieList.
Have you used it in your adapter and set the adapter to the recycler view.
Initialize recycler view in main class
initialize adapter and pass the movielist as arguement to the adapter object created.
attach the adapter to the recyclerview --> recyclerView.setAdapter(adapter).
I think this should work

AsyncTask in Android (pass ArrayList<Integer>)

I have a
ArrayList<Integer>
and i want to pass it to
AsyncTask<ArrayList<Integer>, void, void>.
But in
doInBackground(ArrayList<Integer>...params) function,
i can't receive arrayList, which i passed.
Inside doInBackground i use ArrayList<Integer> arr = params[0] then i log(arr.size()) is 0
My code:
class count extends AsyncTask<Void, Integer, ArrayList<Integer>>{
ArrayList<Integer> arr = new ArrayList<Integer>();
ArrayList<Integer> temp = new ArrayList<Integer>();
#SuppressWarnings("unchecked")
#Override
protected ArrayList<Integer> doInBackground(Void... params) {
// TODO Auto-generated method stub
for(int i = 1; i <= 100; i++){
SystemClock.sleep(200);
arr.add(i);
if(i % 10 == 0){
temp = arr;
//Log.d("DEBUG", "Length of temp = "+ temp.size());
arr.clear();
mean task1 = new mean();
task1.execute(temp);
}
publishProgress(i);
}
return arr;
}
#Override
protected void onProgressUpdate(Integer... values) {
// TODO Auto-generated method stub
super.onProgressUpdate(values);
tvNum.setText(values[0]+"");
}
}
class mean extends AsyncTask<ArrayList<Integer>, Integer, ArrayList<Integer>>{
#Override
protected ArrayList<Integer> doInBackground(
ArrayList<Integer>... params) {
// TODO Auto-generated method stub
ArrayList<Integer> arrL =new ArrayList<Integer>();
arrL= params[0];
Log.d("DEBUG","iNPUT Size = " + arrL.size());
return null;
}
}
Please help me,
Thanks.
If you pass the Arraylist in as the only parameter when you're calling execute(), it should be in params[0]. For example,
YourTask.execute(YourList);
And you would access it inside of the ASyncTask as so:
Arraylist<Integer> myList = params[0];
Easy Example for your understanding. such as
public class MainActivity extends Activity {
List<CalcPrimesTask> taskList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
taskList = new ArrayList<CalcPrimesTask>();
}
public void onClickStart(View view) {
EditText maximumEditText = (EditText) findViewById(R.id.maximumEditText);
int maxNum = Integer.parseInt(maximumEditText.getText().toString());
CalcPrimesTask task = new CalcPrimesTask(this);
taskList.add(task);
task.execute(maxNum);
Toast.makeText(getApplicationContext(), "New run queued.", Toast.LENGTH_SHORT).show();
}
public void onStopClick(View view) {
for (CalcPrimesTask task : taskList) {
task.cancel(true);
}
Toast.makeText(getApplicationContext(), "All runs cancelled.", Toast.LENGTH_SHORT).show();
}
}
and
public class CalcPrimesTask extends AsyncTask<Integer, String, List<Integer>> {
Activity activity;
public CalcPrimesTask(Activity mainActivity) {
activity = mainActivity;
}
#Override
protected List<Integer> doInBackground(Integer... params) {
int maxNum = params[0];
List<Integer> primeList = new ArrayList<Integer>();
for (int i = 2; i <= maxNum ; i++) {
int maxCalc = (int)Math.sqrt(i);
boolean isPrime = true;
for (int j = 2; j <= maxCalc ; j++) {
if (i % j == 0) {
isPrime = false;
break;
}
}
if (isPrime) {
primeList.add(i);
publishProgress("Prime " + i + " found.");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
}
return primeList;
}
#Override
protected void onProgressUpdate(String... values) {
TextView messageView = (TextView) activity.findViewById(R.id.messageText);
messageView.setText(values[0]);
super.onProgressUpdate(values);
}
#Override
protected void onPostExecute(List<Integer> result) {
TextView messageView = (TextView) activity.findViewById(R.id.messageText);
messageView.setText("Total of " + result.size() + " primes found.");
super.onPostExecute(result);
}
}
If your hand available time then read Android AsyncTask. Best of Luck!

Resources