Xamarin android get location before location changes - c#

using Android.App;
using Android.Widget;
using Android.OS;
using Android.Locations;
using Android.Content;
[Activity(Label = "Getlocation", MainLauncher = true)]
public class MainActivity : Activity, ILocationListener
{
Button bttnGo;
TextView txtLoc;
LocationManager locMgr;
Location currentLocation;
string provider;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
bttnGo = FindViewById<Button>(Resource.Id.get_address_button);
txtLoc = FindViewById<TextView>(Resource.Id.location_text);
InitializeLocationManager();
bttnGo.Click += BttnGo_Click;
}
async void BttnGo_Click(object sender, EventArgs e)
{
if (currentLocation == null)
{
txtLoc.Text = "No location found, try moving around";
}
else
{
txtLoc.Text = currentLocation.ToString();
}
}
private void InitializeLocationManager()
{
locMgr = (LocationManager)GetSystemService(LocationService);
Criteria criteriaForLocationService = new Criteria
{
Accuracy = Accuracy.Fine
};
IList<string> acceptableLocationProviders = locMgr.GetProviders(criteriaForLocationService, true);
if(acceptableLocationProviders.Any())
{
provider = acceptableLocationProviders.First();
}
else
{
provider = string.Empty;
}
}
protected override void OnResume()
{
base.OnResume();
locMgr.RequestLocationUpdates(provider, 2000, 0, this);
}
protected override void OnPause()
{
base.OnPause();
locMgr.RemoveUpdates(this);
}
public void OnLocationChanged(Location location)
{
currentLocation = location;
if (currentLocation == null)
{
txtLoc.Text = "No location detected";
}
else
{
txtLoc.Text = location.Latitude.ToString();
}
}
public void OnProviderDisabled(string provider)
{
}
public void OnProviderEnabled(string provider)
{
}
public void OnStatusChanged(string provider, [GeneratedEnum] Availability status, Bundle extras)
{
}
}
}
My coding knowledge is minimal and I was just following a tutorial to retrieve current location.
My problem is that I can only retrieve the location when the actual location changes. I know this is probably because of currentLocation not getting a value until OnLocationChanged happens. how to go around this?

Xamarin android get location before location changes
You could use GetLastKnownLocation(provider) method to implement this feature. Here is a simple demo :
LocationManager locationManager = (LocationManager)GetSystemService(Context.LocationService);
IList<String> lp = locationManager.AllProviders;
foreach (String item in lp)
{
Log.Debug("TAG", "Available Location Service :" + item);
}
//A class indicating the application criteria for selecting a location provider.
Criteria criteria = new Criteria();
//Indicates whether the provider is allowed to incur monetary cost.
criteria.CostAllowed = false;
//Set desired accuracy of location Accuracy
criteria.Accuracy = Accuracy.Coarse;
//Returns the name of the provider that best meets the given criteria
String providerName = locationManager.GetBestProvider(criteria, true);
Log.Debug("8023", "------Location Service:" + providerName);
//Directly choose a Location Provider
//String providerName = LocationManager.GpsProvider;
Location location = locationManager.GetLastKnownLocation(providerName);
double lat = location.Latitude;
double lng = location.Longitude;
txtLoc.Text = "Latitude = " + lat + ", Longitude = " + lng;

Related

Xamarin / SQLite: update doubles in a database

I am working on a Xamarin.Forms app that will store a list of receipes for some chemicals. The chemicals have names (not user changeable) and concentrations. I want the user to be able to change the concentrations in the form and store them.
I have it to where I can modify values in the list with the UPDATE button, I can add (or delete) members of the list, all persistent. However, I cannot figure out how to change the values in the list within the Entry box, itself.
I tried to do something like Arvind Chourasiya did here, but I could not quite figure out the equivalent "connection.Update." I think the SQLite can't be connected to because it's not in the right event, but I am not sure.
My most functional C# code is...
using System;
using System.ComponentModel;
using Xamarin.Forms;
using SQLite;
using System.Collections.ObjectModel;
using System.Runtime.CompilerServices;
namespace contactBook
{
public class Recipe : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
private string _name;
[MaxLength(255)]
public string Name
{
get { return _name; }
set
{
if (_name == value)
return;
_name = value;
OnPropertyChanged();
}
}
private double _concentration;
public double Concentration
{
get
{ return _concentration; }
set
{
if (_concentration == value)
return;
_concentration = value;
OnPropertyChanged();
}
}
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
// Learn more about making custom code visible in the Xamarin.Forms previewer
// by visiting https://aka.ms/xamarinforms-previewer
[DesignTimeVisible(false)]
public partial class MainPage : ContentPage
{
private SQLiteAsyncConnection _connection;
private ObservableCollection<Recipe> _recipes;
public MainPage()
{
InitializeComponent();
_connection = DependencyService.Get<ISQLiteDb>().GetConnection();
//setBasicReceipies();
}
protected override async void OnAppearing()
{
await _connection.CreateTableAsync<Recipe>();
var recipes = await _connection.Table<Recipe>().ToListAsync();
_recipes = new ObservableCollection<Recipe>(recipes);
recipesListView.ItemsSource = _recipes;
base.OnAppearing();
}
async void setBasicReceipies() // worked during tests
{
var recipe1 = new Recipe { Name = "NH3", Concentration = 0.0 };
var recipe2 = new Recipe { Name = "H2SO4", Concentration = 0.1 };
var recipe3 = new Recipe { Name = "NaCl", Concentration = 0.2 };
await _connection.InsertAsync(recipe1);
await _connection.InsertAsync(recipe2);
await _connection.InsertAsync(recipe3);
}
async void OnAdd(object sender, System.EventArgs e)
{
var recipe = new Recipe { Name = "test ", Concentration = 0.0 };
await _connection.InsertAsync(recipe);
_recipes.Add(recipe);
}
async void OnUpdate(object sender, System.EventArgs e)
{
var recipe = _recipes[0];
recipe.Concentration += 0.05;
await _connection.UpdateAsync(recipe);
}
async void OnDelete(object sender, System.EventArgs e)
{
var recipe = _recipes[0];
await _connection.DeleteAsync(recipe);
_recipes.Remove(recipe);
}
//async void Entry_PropertyChanged(System.Object sender, System.ComponentModel.PropertyChangedEventArgs e)
//{
// await _connection.UpdateAllAsync();
//}
}
}

Retrieve data from SQLite using xamarin Android & C#?

I have a class that gets longitude and latitude from user's device and and saves it to an SQLite database. Here's the code:
[Activity(Label = "GetLocation")]
public class GetLocation : Activity, ILocationListener
{
Button btncreate;
EditText txtlong;
EditText txtlat;
static readonly string TAG = "X:" + typeof(GetLocation).Name;
Location _currentLocation;
LocationManager _locationManager;
string _locationProvider;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.GetLocation);
txtlong = FindViewById<EditText>(Resource.Id.txtlong);
txtlat = FindViewById<EditText>(Resource.Id.txtlat);
btncreate = FindViewById<Button>(Resource.Id.btnvalidate);
btncreate.Click += Btncreate_Click;
InitializeLocationManager();
}
void InitializeLocationManager()
{
_locationManager = (LocationManager) GetSystemService(LocationService);
Criteria criteriaForLocationService = new Criteria
{
Accuracy = Accuracy.Fine
};
IList<string> acceptableLocationProviders = _locationManager.GetProviders(criteriaForLocationService, true);
if (acceptableLocationProviders.Any())
{
_locationProvider = acceptableLocationProviders.First();
}
else
{
_locationProvider = string.Empty;
}
Log.Debug(TAG, "Using " + _locationProvider + ".");
}
public void OnProviderDisabled(string provider) { }
public void OnProviderEnabled(string provider) { }
public void OnStatusChanged(string provider, Availability status, Bundle extras) { }
protected override void OnResume()
{
base.OnResume();
_locationManager.RequestLocationUpdates(_locationProvider, 0, 0, this);
}
protected override void OnPause()
{
base.OnPause();
_locationManager.RemoveUpdates(this);
}
public void OnLocationChanged(Location location)
{
_currentLocation = location;
if (_currentLocation == null)
{
txtlong.Text = "Unable to determine your location. Try again in a short while.";
txtlat.Text = "Unable to determine your location. Try again in a short while.";
}
else
{
txtlong.Text = _currentLocation.Longitude.ToString();
txtlat.Text = _currentLocation.Latitude.ToString();
}
}
private void Btncreate_Click(object sender, EventArgs e)
{
try
{
string dpPath = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), "Location.db3");
var db = new SQLiteConnection(dpPath);
db.CreateTable<DataTable>();
DataTable tbl = new DataTable();
tbl.Longitude = txtlong.Text;
tbl.Latitude = txtlat.Text;
db.Insert(tbl);
NextPage();
Toast.MakeText(this, "Data Store Successfully...,", ToastLength.Short).Show();
}
catch (Exception ex)
{
Toast.MakeText(this, ex.ToString(), ToastLength.Short).Show();
}
}
void NextPage()
{
//code to get next page
}
}
the DataTable class is as follows:
class DataTable
{
[PrimaryKey, AutoIncrement, Column("_Id")]
public int Id {get; set;}
public string Longitude { get; set; }
public string Latitude { get; set; }
}
once it has saved the data, I would like another class (activity) to be able to display it on a separate .axml page. my problem is I am a programmer in training (college) and have no clue what to do. Your help is greatly appreciated.
You need to start a new activity using
StartActivity(typeof(Activity2));
and in the OnCreate of your Activity2 set you new .axml layout:
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.MyView);
}
Then to retrieve the data use Query:
string dpPath = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), "Location.db3");
var db = new SQLiteConnection(dpPath);
var dataTables = db.Query<DataTable>("select * from DataTable");
I'd recommend you to read SQLite: GettingStarted and if you want to improve that move all about SQLite to another class to reuse the code of openning an SQLiteConnection. Also if you can use asynchronous calls in order to prevent blocking the UI while persisting data in your database.
Also check Xamarin Android docs that is really helpful
HIH

OnButtonPressed issue

Started with Xamarin Android yesterday and can't seem to figure out why the Back Button script(s) won't be called.
Searched and seen that a lot of people recommend something like this:
public override void OnBackPressed()
{
Toast.MakeText(this, "Back Button Pressed", ToastLength.Short).Show();
}
However this doesn't stop my phone or the android emulator from closing the app instantly.
Most of the things I have found about this thread I haven't managed to make work for some reason or they won't be called.
Thanks
Update:
Checked another project. It works 100% there with the same code as above. Not sure what makes it not work in my project
Update
Here is some of the code. I know it's terrible but I'm just messing around trying to learn as I'm a total newbie with Xamarin & Android - Feel free to give links on something I should read however!
namespace Workout_App {
[Activity(Label = "Workout App", MainLauncher = true)]
public class MainActivity : Activity
{
private List<Exercise> mItems, mItemsDay1;
private ListView mListView;
MyListViewAdapter adapter, adapter2;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.Main);
mListView = FindViewById<ListView>(Resource.Id.myListView); // myListView er navnet på objekte i AXML fila f.eks
mItems = new List<Exercise>();
mItemsDay1 = new List<Exercise>();
mItems.Add(new Exercise() { Name = "Day 1"});
mItems.Add(new Exercise() { Name = "Day 2"});
mItems.Add(new Exercise() { Name = "Day 3"});
mItemsDay1.Add(new Exercise() { Name = "Benkpress", Reps = "8x4", kg = 140});
mItemsDay1.Add(new Exercise() { Name = "Lårpress", Reps = "8x4", kg = 58});
mItemsDay1.Add(new Exercise() { Name = "BankPro", Reps = "8x4", kg = 22});
adapter = new MyListViewAdapter(this, mItems);
adapter2 = new MyListViewAdapter(this, mItemsDay1);
mListView.Adapter = adapter;
mListView.ItemClick += mListView_ItemClick; // subscribes it, - to unsub
mListView.ItemLongClick += mListView_ItemLongClick;
// mListView.ItemClick += mListView_ItemClick2;
}
public override void OnBackPressed()
{
Toast.MakeText(this, "Back Button Pressed Detected", ToastLength.Short).Show();
}
void mListView_ItemClick(object sender, AdapterView.ItemClickEventArgs e)
{
mListView.Adapter = adapter2;
}
And this is the view
namespace Workout_App {
class MyListViewAdapter : BaseAdapter<Exercise>
{
public List<Exercise> mItems;
private Context mContext;
public MyListViewAdapter(Context context, List<Exercise> items)
{
mItems = items;
mContext = context;
}
public override int Count
{
get { return mItems.Count; }
}
public override long GetItemId(int position)
{
return position;
}
public override Exercise this[int position]
{
get { return mItems[position]; }
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
View row = convertView;
if(row == null)
{
row = LayoutInflater.From(mContext).Inflate(Resource.Layout.listview_row, null, false );
}
TextView txtName = row.FindViewById<TextView>(Resource.Id.txtName);
txtName.Text = mItems[position].Name;
TextView txtReps = row.FindViewById <TextView>(Resource.Id.txtReps);
txtReps.Text = mItems[position].Reps;
TextView txtKg = row.FindViewById<TextView>(Resource.Id.txtKg);
if(mItems[position].kg > 0) {
txtKg.Text = mItems[position].kg + " kg";
} else
{
txtKg.Text = "";
}
return row;
}
}
}

Black Screen of Death in Mobile

I'm trying to figure out in my customer's Mobile what causes black screens of death. The apk in different places and random moments causes a black screen of death and application stucks. I have place exceptions almost everywhere but i dont get any exception message.I will send you an examample from my code:
What can cause this black screens???
Here is my class:
class MyListViewAdapterInventory : BaseAdapter<InventoryPreviewClass>
{
public List<InventoryPreviewClass> mitems;
private Context mContext;
private int mRowLayout;
private int[] mAlternatingColors;
public MyListViewAdapterInventory(Context context, int rowLayout, List<InventoryPreviewClass> items)
{
mitems = items;
mContext = context;
mRowLayout = rowLayout;
mAlternatingColors = new int[] { 0xF2F2F2, 0xbfddff };
}
public override int Count
{
get
{
return mitems.Count;
}
}
public override long GetItemId(int position)
{
return position;
}
public override InventoryPreviewClass this[int position]
{
get
{
return mitems[position];
}
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
View row = convertView;
if (row == null)
{
row = LayoutInflater.From(mContext).Inflate(Resource.Layout.InventoryPreview, null, false);
}
row = LayoutInflater.From(mContext).Inflate(Resource.Layout.InventoryPreview, null, false);
row.SetBackgroundColor(GetColorFromInteger(mAlternatingColors[position % mAlternatingColors.Length]));
TextView txtInventoryID = row.FindViewById<TextView>(Resource.Id.txtInventoryID);
txtInventoryID.Text = mitems[position].InventoryItemID;
TextView txtInventoryName = row.FindViewById<TextView>(Resource.Id.txtInventoryName);
txtInventoryName.Text = mitems[position].InventoryItemName;
TextView txtInventoryPrice = row.FindViewById<TextView>(Resource.Id.txtInventoryPrice);
txtInventoryPrice.Text = mitems[position].InventoryItemPrice.Replace(",", ".");
Button ExtraBtn = row.FindViewById<Button>(Resource.Id.ExtrasBtn);
ExtraBtn.Click += (sender, e) =>
{
try
{
Connection.InventoryItemID = mitems[position].InventoryItemID;
Connection.InventoryItemName = mitems[position].InventoryItemName;
Connection.RetailPrice = mitems[position].InventoryItemPrice;
Toast toast = Toast.MakeText(mContext, txtInventoryName.Text, ToastLength.Short);
toast.Show();
mContext.StartActivity(typeof(ExtrasPreviewMain));
}
catch (Exception ex)
{
Toast toast = Toast.MakeText(mContext, Convert.ToString(ex), ToastLength.Long);
toast.Show();
}
};
return row;
}
private Color GetColorFromInteger(int color)
{
return Color.Rgb(Color.GetRedComponent(color), Color.GetGreenComponent(color), Color.GetBlueComponent(color));
}
}
And here is my activity Main when running:
private List<InventoryPreviewClass> mItems;
private ListView mlistview;
private EditText mSearch;
private EditText etSearchAlwaysOn;
private LinearLayout mContainer;
private bool mAnimatedDown;
private bool mIsAnimating;
private MyListViewAdapterInventory mAdapter;
string dpPath = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), "student.db3");
SQLiteConnection db;
private TextView mTxtHeaderFirstName;
private TextView mTxtHeaderLastName;
private bool mFirstNameAscending;
private bool mLastNameAscending;
protected override void OnCreate(Bundle savedInstanceState)
{
try
{
ActionBar.SetHomeButtonEnabled(true);
ActionBar.SetDisplayHomeAsUpEnabled(true);
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.InventoryPreviewMain);
OverridePendingTransition(Resource.Layout.trans_left_in, Resource.Layout.trans_left_out);
mSearch = FindViewById<EditText>(Resource.Id.etSearch);
etSearchAlwaysOn = FindViewById<EditText>(Resource.Id.etSearchAlwaysOn);
mContainer = FindViewById<LinearLayout>(Resource.Id.llContainer);
mTxtHeaderFirstName = FindViewById<TextView>(Resource.Id.txtHeaderFirstName);
mTxtHeaderLastName = FindViewById<TextView>(Resource.Id.txtHeaderLastName);
mTxtHeaderFirstName.Click += mTxtHeaderFirstName_Click;
mTxtHeaderLastName.Click += mTxtHeaderLastName_Click;
mSearch.Alpha = 0;
mContainer.BringToFront();
mSearch.TextChanged += mSearch_TextChanged;
etSearchAlwaysOn.TextChanged += EtSearchAlwaysOn_TextChanged;
mlistview = FindViewById<ListView>(Resource.Id.InventoryList);
}
catch (Exception ex)
{
Toast.MakeText(this, Convert.ToString(ex), ToastLength.Short).Show();
}
try
{
db = new SQLiteConnection(dpPath);
var table = db.Query<InventoryPreviewClass>("select * from InventoryPreviewClass where CategoryID =" + Connection.CategoryID+ "");
mItems = new List<InventoryPreviewClass>();
foreach (var item in table)
{
mItems.Add(new InventoryPreviewClass() { InventoryItemID = item.InventoryItemID, InventoryItemName = item.InventoryItemName, InventoryItemPrice = item.InventoryItemPrice });
}
MyListViewAdapterInventory adapter = new MyListViewAdapterInventory(this, Resource.Layout.InventoryPreview, mItems);
mlistview.Adapter = adapter;
mlistview.ItemClick += Mlistview_ItemClick;
}
catch
{
}
try
{
if (SearchAlwaysOn == true)
{
var param = (LinearLayout.LayoutParams)etSearchAlwaysOn.LayoutParameters;
var WidthParam = ViewGroup.LayoutParams.MatchParent;
var HeigthParam = ViewGroup.LayoutParams.WrapContent;
param.Width = WidthParam;
param.Height = HeigthParam;
mIsAnimating = true;
}
}
catch (Exception ex)
{
Toast.MakeText(this, Convert.ToString(ex), ToastLength.Short).Show();
}
}

OnClickListeners for Recyclerviews -Xamarin.Droid

I have tried to look out for an answer to the behavior of my views but I seem not find any question or solution related to it. My recycler views seemed to be set up well. I just realized that my app is not responding in the right way to the OnClickListeners.
I have set up toasts in my adapter for the recycler view click events. When i have 10 views. When i click on a view, it gives a text of another view. It seems it randomly gives me the text of another view amongst the 9 remaining views. What could be the cause of this?
Activity
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
FrameLayout content = (FrameLayout)FindViewById(Resource.Id.content_frame);
LayoutInflater.Inflate(Resource.Layout.Main, content);
setUpRecyclerView();
}
public void setUpRecyclerView(){
rv = FindViewById<RecyclerView>(Resource.Id.recyclerView);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.Orientation = LinearLayoutManager.Vertical;
layoutManager.ReverseLayout = true;
layoutManager.StackFromEnd = true;
rv.HasFixedSize = true;
rv.SetLayoutManager(layoutManager);
}
Adapter
public class FeedViewHolder : RecyclerView.ViewHolder, View.IOnClickListener, View.IOnLongClickListener
{
public FeedViewHolder(View itemView):base(itemView)
{
//binding of variables here
itemView.SetOnClickListener(this);
itemView.SetOnLongClickListener(this);
}
public void OnClick(View v)
{
itemClickListener.OnClick(v, AdapterPosition, false);
}
public bool OnLongClick(View v)
{
itemClickListener.OnClick(v, AdapterPosition, true);
return true;
}
public class FeedAdapter : RecyclerView.Adapter, ItemClickListener
{
public FeedAdapter(RssObject rssObject, Context mContext)
{
this.mContext = mContext;
this.inflater = LayoutInflater.From(mContext);
activity = (MainActivity)mContext;
}
public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
hold = holder as FeedViewHolder;
//binding
hold.itemClickListener = this;
}
public void OnClick(View view, int position, bool isLongClick)
{
Toast.MakeText(activity, "Main text : " + hold.txtContent.Text, ToastLength.Long).Show();
}
public override int ItemCount
{
get { return rssObject.items.Count; }
}
}
}
}

Categories