using Android.App;
using Android.Content;
using Android.Locations;
using Android.OS;
using Android.Runtime;
using Android.Util;
using Android.Views;
using Android.Widget;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.Support;
namespace App3.Droid
{
[Service]
public class LocationService : Service, ILocationListener
{
LocationManager _locationManager;
Context c;
string _locationProvider;
//const int REQUEST_FOREGROUND_SERVICE = 0;
const int NOTIFICATION_ID = 1;
NotificationManager manager;
//private string _notificationTitle = "App is running in background";
//private string _notificationText = "App is tracking your location";
public override IBinder OnBind(Intent intent)
{
return null;
}
public override void OnCreate()
{
base.OnCreate();
c = this;
}
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId) {
Android.Util.Log.Debug("LocationService", "OnStartCommand Called");
_locationManager = (LocationManager)c.GetSystemService(LocationService);
_locationProvider = LocationManager.GpsProvider;
System.Diagnostics.Debug.WriteLine(_locationManager);
System.Diagnostics.Debug.WriteLine(_locationProvider);
System.Diagnostics.Debug.WriteLine(_locationManager.IsProviderEnabled(_locationProvider) +
"," + _locationManager.AllProviders.Contains(_locationProvider));
if (_locationManager.IsProviderEnabled(_locationProvider) && _locationManager.AllProviders.Contains(_locationProvider))
{
_locationManager.RequestLocationUpdates(_locationProvider, 0, 0, this);
//System.Diagnostics.Debug.WriteLine();
manager = (NotificationManager)GetSystemService(NotificationService);
if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
//var channel = new NotificationChannel("channel_01", "My Channel", NotificationImportance.High);
//manager.CreateNotificationChannel(channel);
//var notificationBuilder = new Notification.Builder(this)
//.SetContentTitle(_notificationTitle)
//.SetContentText(_notificationText)
//.SetSmallIcon(Resource.Mipmap.icon);
//var notification = notificationBuilder.Build();
//manager = (NotificationManager)GetSystemService(Context.NotificationService);
//manager.Notify(NOTIFICATION_ID, notification);
Toast.MakeText(this, "Notifcations On", ToastLength.Short).Show();
}
else
{
Toast.MakeText(this, "Notifications not supported", ToastLength.Long).Show();
}
}
else
{
Toast.MakeText(this, "Please enable GPS.", ToastLength.Long).Show();
}
return StartCommandResult.Sticky;
}
public override void OnDestroy()
{
Log.Debug("LocationService", "StopService called");
base.OnDestroy();
_locationManager.RemoveUpdates(this);
}
public void OnLocationChanged(Location location)
{
double latitude = location.Latitude;
double longitude = location.Longitude;
string coordinates = latitude + "," + longitude;
System.Diagnostics.Debug.WriteLine(latitude + "," + longitude);
String msg = "New Latitude: " + latitude + "New Longitude: " + longitude;
Toast.MakeText(this, msg, ToastLength.Long).Show();
}
}
}
I've tried debugging by checking the _locationProvider and _locationManager and they both return true and walking around to see if i've gotten location updates. I've registered the service in AndroidManifest.xml and the OnStartCommand gets called and a notification pops up that the gps is currently being used by the android device.
Related
I've made this simple app for recieving sms,When I receive a message I want to output this on my TextView,upuntil now for testing I was just doing
that inside a button .You recieve a message ,click on the button and you get the sms on textview.If I try to do this without a button ,at the start of compilation
I get a null reference exception.Can anyone help me on this ?
//----------MainActivity.cs---------------
using Android.App;
using Android.OS;
using Android.Support.V7.App;
using Android.Runtime;
using Android.Widget;
using Android.Content;
using Android.Telephony;
using Android.Provider;
using Android.Util;
using Java.Lang;
using System.Text.RegularExpressions;
using Xamarin.Essentials;
using System;
using Android;
using Android.Support.V4.Content;
using Android.Content.PM;
namespace Sms_Receiver2
{
[Activity(Label = "#string/app_name", Theme = "#style/AppTheme", MainLauncher = true)]
public class MainActivity : AppCompatActivity
{
public Receiver1 _receiver; // Receiver class
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.activity_main);
TextView translatedPhoneWord = FindViewById<TextView>(Resource.Id.TranslatedPhoneword);
Button translateButton = FindViewById<Button>(Resource.Id.TranslateButton);
if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.ReadSms) != (int)Permission.Granted)
{
RequestPermissions(new string[] { Manifest.Permission.ReadSms, Manifest.Permission.SendSms, Manifest.Permission.ReceiveSms }, 0);
}
translateButton.Click += (s, e) =>
{};
translatedPhoneWord.Text = _receiver.message;// null reference exception
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
{
Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
protected override void OnResume()
{
base.OnResume();
_receiver = new Receiver1();
IntentFilter filter = new IntentFilter();
filter.AddAction("android.provider.Telephony.SMS_RECEIVED");
filter.AddAction("android.provider.Telephony.SMS_DELIVER");
RegisterReceiver(_receiver, filter);
}
protected override void OnPause()
{
base.OnPause();
UnregisterReceiver(_receiver);
}
}
}
//---------Reciever.cs -------------
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.Telephony;
using Android.Provider;
namespace Sms_Receiver2
{
[BroadcastReceiver(Enabled = true, Exported = true, Permission = "android.permission.BROADCAST_SMS")]
[IntentFilter(new[] { "android.provider.Telephony.SMS_RECEIVED", "android.provider.Telephony.SMS_DELIVER" }, Priority = (int)IntentFilterPriority.HighPriority)]
public class Receiver1 : BroadcastReceiver
{
public string message, address = "";
public static readonly string INTENT_ACTION = "android.provider.Telephony.SMS_RECEIVED";
public override void OnReceive(Context context, Intent intent)
{
if (intent.HasExtra("pdus"))
{
var smsArray = (Java.Lang.Object[])intent.Extras.Get("pdus");
foreach (var item in smsArray)
{
var sms = SmsMessage.CreateFromPdu((byte[])item);
address = sms.OriginatingAddress;
message = sms.MessageBody;
Toast.MakeText(context, "Number :" + address + "Message : " + message, ToastLength.Short).Show();
}
}
}
}
}
Slight modification of your code works
[Activity(Label = "#string/app_name", Theme = "#style/AppTheme.NoActionBar", MainLauncher = true)]
public class MainActivity : AppCompatActivity
{
private SMSBroadcastReceiver _receiver;
private TextView _smsTextView; //Textview where list of received sms will show
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.activity_main);
_smsTextView = FindViewById<TextView>(Resource.Id.smstextview);
_receiver = new SMSBroadcastReceiver();
_receiver.SmsActionDelegate = InokeOnNewSMS;
IntentFilter filter = new IntentFilter();
filter.AddAction("android.provider.Telephony.SMS_RECEIVED");
filter.AddAction("android.provider.Telephony.SMS_DELIVER");
RegisterReceiver(_receiver, filter);
}
//this method will be invoked when new sms is received in the broadcast received
public void InokeOnNewSMS(string address, string message)
{
_smsTextView.Text += $"{address} : {message}\n\n";
}
}
[BroadcastReceiver(Enabled = true, Exported = true, Permission = "android.permission.BROADCAST_SMS")]
[IntentFilter(new[] { "android.provider.Telephony.SMS_RECEIVED", "android.provider.Telephony.SMS_DELIVER" }, Priority = (int)IntentFilterPriority.HighPriority)]
public class SMSBroadcastReceiver : BroadcastReceiver
{
public string message = "", address = "";
public static readonly string INTENT_ACTION = "android.provider.Telephony.SMS_RECEIVED";
public Action<string, string> SmsActionDelegate;
public override void OnReceive(Context context, Intent intent)
{
if (intent.HasExtra("pdus"))
{
var smsArray = (Java.Lang.Object[])intent.Extras.Get("pdus");
foreach (var item in smsArray)
{
var sms = SmsMessage.CreateFromPdu((byte[])item);
address = sms.OriginatingAddress;
message = sms.MessageBody;
SmsActionDelegate?.Invoke(address, message);
Toast.MakeText(context, "Number :" + address + "Message : " + message, ToastLength.Short).Show();
}
}
}
}
i have xamarin android application that read from clipboard and write to it. it uses foreground services if the user hit the button. the problem is when the user hit the button again the services disappear from running services but still doing it's job (editing copied text). how can i completely stop it from working?
foreground.cs:
public override IBinder OnBind(Intent intent)
{
return null;
}
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
Clipboard.ClipboardContentChanged += async (o, e) =>
{
var text = await Clipboard.GetTextAsync();
Toast.MakeText(this, text, ToastLength.Long).Show();
if (text.Contains("#"))
{
await Clipboard.SetTextAsync(text.Replace("#", ""));
}
};
Notification notif = ReturnNotif();
StartForeground(1, notif);
return StartCommandResult.NotSticky;
}
public override void OnDestroy()
{
base.OnDestroy();
}
public override void OnCreate()
{
base.OnCreate();
}
public override bool StopService(Intent name)
{
StopForeground(true);
StopSelf();
return base.StopService(name);
}
MainActivity.cs:
if (id == Resource.Id.myService)
{
if (count != 1)
{
count = 1;
var intent = new Intent(this, typeof(foreground));
intent.SetAction("No");
if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
StartForegroundService(intent);
}
else
{
StartService(intent);
}
}
else
{
var intent = new Intent(this,typeof(foreground));
StopService(intent);
Toast.MakeText(this, "Service Stopped", ToastLength.Long).Show();
count = 0;
}
}
what i am doing wrong ?
Edit :
Service will completely stops if the app is removed from recently used apps.
In your MyForegroundService.cs. Just add StopForeground(true) in OnDestroy() method like following code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
namespace ForegroundServiceDemo
{
[Service]
class MyForegroundService : Service
{
public const int SERVICE_RUNNING_NOTIFICATION_ID = 10000;
[return: GeneratedEnum]
public override StartCommandResult OnStartCommand(Intent intent, [GeneratedEnum] StartCommandFlags flags, int startId)
{
CreateNotificationChannel();
string messageBody = "service starting";
// / Create an Intent for the activity you want to start
Intent resultIntent = new Intent(this,typeof(Activity1));
// Create the TaskStackBuilder and add the intent, which inflates the back stack
TaskStackBuilder stackBuilder = TaskStackBuilder.Create(this);
stackBuilder.AddNextIntentWithParentStack(resultIntent);
// Get the PendingIntent containing the entire back stack
PendingIntent resultPendingIntent = stackBuilder.GetPendingIntent(0, PendingIntentFlags.UpdateCurrent);
var notification = new Notification.Builder(this, "10111")
.SetContentIntent(resultPendingIntent)
.SetContentTitle("Foreground")
.SetContentText(messageBody)
.SetSmallIcon(Resource.Drawable.main)
.SetOngoing(true)
.Build();
StartForeground(SERVICE_RUNNING_NOTIFICATION_ID, notification);
//do you work
return StartCommandResult.Sticky;
}
public override void OnDestroy()
{
base.OnDestroy();
StopForeground(true);
}
public override IBinder OnBind(Intent intent)
{
return null;
}
void CreateNotificationChannel()
{
if (Build.VERSION.SdkInt < BuildVersionCodes.O)
{
return;
}
var channelName = Resources.GetString(Resource.String.channel_name);
var channelDescription = GetString(Resource.String.channel_description);
var channel = new NotificationChannel("10111", channelName, NotificationImportance.Default)
{
Description = channelDescription
};
var notificationManager = (NotificationManager)GetSystemService(NotificationService);
notificationManager.CreateNotificationChannel(channel);
}
}
}
When you want to stop it. Just call following code.
Android.App.Application.Context.StopService(intent);
Here is my code in the Activity.
public class MainActivity : AppCompatActivity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.activity_main);
Button button1 = FindViewById<Button>(Resource.Id.button1);
Button button2 = FindViewById<Button>(Resource.Id.button2);
button2.Click += Button2_Click;
button1.Click += Button1_Click;
}
Intent intent;
private void Button2_Click(object sender, System.EventArgs e)
{
// stop foreground service.
Android.App.Application.Context.StopService(intent);
}
private void Button1_Click(object sender, System.EventArgs e)
{
intent = new Intent(Android.App.Application.Context, typeof(MyForegroundService));
// start foreground service.
if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.O)
{
StartForegroundService(intent);
}
}
Here is running GIF.
====Update====
the expected behavior is : when service stopped user can copy and paste normally without the service interference
You can use following way to achieve that.Use Clipboard.ClipboardContentChanged += Clipboard_ClipboardContentChanged; to execute the behavior, use Clipboard.ClipboardContentChanged -= Clipboard_ClipboardContentChanged; to disable the behavior in the OnDistory method.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Xamarin.Essentials;
namespace ForegroundServiceDemo
{
[Service]
class MyForegroundService : Service
{
public const int SERVICE_RUNNING_NOTIFICATION_ID = 10000;
[return: GeneratedEnum]
public override StartCommandResult OnStartCommand(Intent intent, [GeneratedEnum] StartCommandFlags flags, int startId)
{
CreateNotificationChannel();
string messageBody = "service starting";
Clipboard.ClipboardContentChanged += Clipboard_ClipboardContentChanged;
// / Create an Intent for the activity you want to start
Intent resultIntent = new Intent(this,typeof(Activity1));
// Create the TaskStackBuilder and add the intent, which inflates the back stack
TaskStackBuilder stackBuilder = TaskStackBuilder.Create(this);
stackBuilder.AddNextIntentWithParentStack(resultIntent);
// Get the PendingIntent containing the entire back stack
PendingIntent resultPendingIntent = stackBuilder.GetPendingIntent(0, PendingIntentFlags.UpdateCurrent);
var notification = new Notification.Builder(this, "10111")
.SetContentIntent(resultPendingIntent)
.SetContentTitle("Foreground")
.SetContentText(messageBody)
.SetSmallIcon(Resource.Drawable.main)
.SetOngoing(true)
.Build();
StartForeground(SERVICE_RUNNING_NOTIFICATION_ID, notification);
//do you work
return StartCommandResult.Sticky;
}
private async void Clipboard_ClipboardContentChanged(object sender, EventArgs e)
{
//throw new NotImplementedException();
var text = await Clipboard.GetTextAsync();
Toast.MakeText(this, text, ToastLength.Long).Show();
if (text.Contains("#"))
{
await Clipboard.SetTextAsync(text.Replace("#", ""));
}
}
public override void OnDestroy()
{
base.OnDestroy();
Clipboard.ClipboardContentChanged -= Clipboard_ClipboardContentChanged;
StopForeground(true);
}
public override IBinder OnBind(Intent intent)
{
return null;
}
void CreateNotificationChannel()
{
if (Build.VERSION.SdkInt < BuildVersionCodes.O)
{
return;
}
var channelName = Resources.GetString(Resource.String.channel_name);
var channelDescription = GetString(Resource.String.channel_description);
var channel = new NotificationChannel("10111", channelName, NotificationImportance.Default)
{
Description = channelDescription
};
var notificationManager = (NotificationManager)GetSystemService(NotificationService);
notificationManager.CreateNotificationChannel(channel);
}
}
}
Here is run GIF.
To prevent this issues, add a "myServiceIsRunning" bool value in the Properties dictionary when you start your foreground method like this:
Application.Current.Properties["myServiceIsRunning"] = true
With a get function or whatever you want, before start the foreground method, verify if the key "myServiceIsRunning" exist, and if it exist, how is his status:
public bool getRunningStateMyService(){
bool myServiceIsRunningValue;
if (Application.Current.Properties.ContainsKey("myServiceIsRunning"))
{
myServiceIsRunningValue = Convert.ToBoolean(Application.Current.Properties["myServiceIsRunning"]);
}
else
{
myServiceIsRunningValue = false;
}
return locationServiceIsRunning;
}
After you get the value, with a simple if{}/else{}, you can choose to start a new instance or not if you're service is running or not. Or, in you're case just prevent the foreground method continue to run.
Don't forget to set your value to false when you destroy the foreground method.
the Properties dictionary can store data trought closing app to. you can have more infos here:
https://learn.microsoft.com/fr-fr/xamarin/xamarin-forms/app-fundamentals/application-class#Properties_Dictionary
Attaching the source code for application i have created, its a simple application with collection view and button to choose image from gallery or camera. ios app crashes after taking 8 images continuously from camera.
using CoreGraphics;
using Foundation;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using UIKit;
namespace App2.iOS
{
public class imagesDisplay
{
public bool PlusImg;
public bool uploaded;
public string path { get; set; }
public int id { get; set; }
public imagesDisplay(bool uploaded, bool PlusImg = false, string path = null, int id = 0)
{
this.uploaded = uploaded;
this.PlusImg = PlusImg;
this.path = path;
this.id = id;
}
}
public partial class ViewController : UIViewController
{
public List<imagesDisplay> images = new List<imagesDisplay>();
private UIAlertController alert;
private UIImagePickerController imagePicker;
private NSData imgData;
private NSData thumdata;
public ViewController (IntPtr handle) : base (handle)
{
}
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
imgCollection.SetCollectionViewLayout(new LineLayout(), false);
imgCollection.AllowsMultipleSelection = true;
imgCollection.RegisterNibForCell(UINib.FromName("imageceCollectionViewCell", null), imageceCollectionViewCell.Key);
alert = UIAlertController.Create("", "Select image from : ", UIAlertControllerStyle.ActionSheet);
var cameraaction = UIAlertAction.Create("Bruk kamera", UIAlertActionStyle.Default, a =>
{
imagePicker = new UIImagePickerController();
imagePicker.SourceType = UIImagePickerControllerSourceType.Camera;
imagePicker.FinishedPickingMedia += Handle_FinishedPickingMedia;
imagePicker.Canceled += Handle_Canceled;
imagePicker.AllowsImageEditing = false;
this.NavigationController.PresentViewController(imagePicker, true, null);
});
alert.AddAction(cameraaction);
var galleryaction = UIAlertAction.Create("Last opp bilder", UIAlertActionStyle.Default, a =>
{
imagePicker = new UIImagePickerController();
imagePicker.SourceType = UIImagePickerControllerSourceType.PhotoLibrary;
imagePicker.FinishedPickingMedia += Handle_FinishedPickingMedia;
imagePicker.Canceled += Handle_Canceled;
imagePicker.AllowsImageEditing = false;
this.NavigationController.PresentViewController(imagePicker, true, null);
});
alert.AddAction(galleryaction);
alert.AddAction(UIAlertAction.Create("Avbryt", UIAlertActionStyle.Cancel, a => { }));
imgCollection.Source = new ImageCollectionSource(images,new WeakReference<UINavigationController>(this.NavigationController));
}
public override void DidReceiveMemoryWarning ()
{
base.DidReceiveMemoryWarning ();
// Release any cached data, images, etc that aren't in use.
}
partial void UIButton125_TouchUpInside(UIButton sender)
{
this.PresentViewController(alert, true, null);
}
private void Handle_Canceled(object sender, EventArgs e)
{
imagePicker.DismissModalViewController(true);
}
private void Handle_FinishedPickingMedia(object sender, UIImagePickerMediaPickedEventArgs e)
{
try
{
NSUrl referenceURL = e.Info[new NSString("UIImagePickerControllerReferenceUrl")] as NSUrl;
if (referenceURL != null)
Console.WriteLine("Url:" + referenceURL.ToString());
UIImage originalImage = e.Info[UIImagePickerController.OriginalImage] as UIImage;
if (originalImage != null)
{
var documentsDirectory = Environment.GetFolderPath
(Environment.SpecialFolder.Personal);
string timestamp = DateTime.Now.ToString("yyyyMMddHHmmssffff");
string jpgFilename = System.IO.Path.Combine(documentsDirectory, timestamp + ".jpg"); // hardcoded filename, overwritten each time
string thumname = System.IO.Path.Combine(documentsDirectory, timestamp + "_thumb" + ".jpg");
imgData = originalImage.AsJPEG();
Console.WriteLine("Original image size = " + imgData.Length);
thumdata = originalImage.AsJPEG(0.0f);
Console.WriteLine("after funtion compresion image size = " + thumdata.Length);
NSError err = null;
if (imgData.Save(jpgFilename, false, out err))
{
Console.WriteLine("saved as " + jpgFilename);
NSError err1 = null;
if (thumdata.Save(thumname, false, out err1))
{
Console.WriteLine("saved as " + jpgFilename);
}
else
{
Console.WriteLine("NOT saved as " + jpgFilename + " because" + err.LocalizedDescription);
}
}
else
{
Console.WriteLine("NOT saved as " + jpgFilename + " because" + err.LocalizedDescription);
}
images.Add(new imagesDisplay(false, false, thumname, 0));
}
imgCollection.ReloadData();
imagePicker.DismissViewController(true, null);
}
catch (Exception ex)
{
}
}
}
public class LineLayout : UICollectionViewFlowLayout
{
public LineLayout()
{
ItemSize = new CGSize((UIScreen.MainScreen.Bounds.Width / 2) - 12, (UIScreen.MainScreen.Bounds.Height / 3) - 40);
MinimumInteritemSpacing = 0f;
}
}
}
Force to release the image data before creating the new one:
if (imgData != null) {
imgData.Dispose();
imgData = null;
}
imgData = originalImage.AsJPEG();
Or use local variable with using sentence:
using (NSData imgData = originalImage.AsJPEG()) { //imgData will be disposed immediately at the end of block
//......
}
I want to get the user's current location (latitude and longitude) always using Sim-based network only, not by using any other networks (like WiFi, Mobile Data, GPS and other Network and even all these are in Disabled mode in mobile). Not necessarily exact location but even approximate location.
Is there any possibility to get it? If any of you can explain and include code; I searched in Google but did not get the correct related answer.
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using Android.Locations;
using Android.Util;
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.Xml.Linq;
using System.Threading;
namespace GPS_Android
{
[Activity(Label = "GPS_Android", MainLauncher = true, Icon = "#drawable/icon")]
public class MainActivity : Activity,ILocationListener
{
private Location _currentLocation;
private LocationManager _locationManager;
private TextView _locationText;
private TextView _addressText;
private string _locationProvider;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
_addressText = FindViewById<TextView>(Resource.Id.address_text);
_locationText = FindViewById<TextView>(Resource.Id.location_text);
FindViewById<TextView>(Resource.Id.get_address_button).Click += AddressButton_OnClick;
InitializeLocationManager();
}
public 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;
}
}
protected override void OnResume()
{
base.OnResume();
_locationManager.RequestLocationUpdates(_locationProvider, 0, 0, this);
}
protected override void OnPause()
{
base.OnPause();
_locationManager.RemoveUpdates(this);
}
async void AddressButton_OnClick(object sender, EventArgs eventArgs)
{
if (_currentLocation == null)
{
_addressText.Text = "Can't determine the current location.";
return;
}
Geocoder geocoder = new Geocoder(this);
IList<Address> addressList = await geocoder.GetFromLocationAsync(_currentLocation.Latitude, _currentLocation.Longitude, 10);
Address address = addressList.FirstOrDefault();
if (address != null)
{
StringBuilder deviceAddress = new StringBuilder();
for (int i = 0; i < address.MaxAddressLineIndex; i++)
{
deviceAddress.Append(address.GetAddressLine(i))
.AppendLine(",");
}
_addressText.Text = deviceAddress.ToString();
}
else
{
_addressText.Text = "Unable to determine the address.";
}
}
public void OnLocationChanged(Location location)
{
_currentLocation = location;
if (_currentLocation == null)
{
_locationText.Text = "Unable to determine your location.";
}
else
{
_locationText.Text = String.Format("{0},{1}", _currentLocation.Latitude, _currentLocation.Longitude);
}
}
public void OnProviderDisabled(string provider) { }
public void OnProviderEnabled(string provider) { }
public void OnStatusChanged(string provider, Availability status, Bundle extras) { }
}
}
You can use LocationManager.NETWORK_PROVIDER to get Latitude and Longitude without opening GPS
btnNWShowLocation.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
Location nwLocation = appLocationService
.getLocation(LocationManager.NETWORK_PROVIDER);
if (nwLocation != null) {
double latitude = nwLocation.getLatitude();
double longitude = nwLocation.getLongitude();
Toast.makeText(
getApplicationContext(),
"Mobile Location (NW): \nLatitude: " + latitude
+ "\nLongitude: " + longitude,
Toast.LENGTH_LONG).show();
} else {
showSettingsAlert("NETWORK");
}
}
});
Why I can't recieved messages from Chat Server ?
I developed Chat Client in Visual Studio C# with mono for android.
I want to receive mesagens from Chat server they are sent but he Chat Client may be receiving them and i can not seem to show in Text1.Text
The Source Code Chat Client for receiving messages:
//Criado por EcoDuty, Frederico Vaz
using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
//
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;
using System.Runtime.InteropServices;
namespace ChatClient_Android
{
[Activity(Label = "ChatClient_Android", MainLauncher = true, Icon = "#drawable/icon")]
public class MainChat : Activity
{
public delegate void OnRecievedMessage(string message);
public MainChat form;
const int WM_VSCROLL = 0x115;
const int SB_BOTTOM = 7;
TextView text1;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
// Get our button from the layout resource,
// and attach an event to it
Button ligar = FindViewById<Button>(Resource.Id.btligar);
text1 = FindViewById<TextView>(Resource.Id.text1);
//Conexão com o servidor
ligar.Click += delegate
{
Connect();
ligar.Enabled = false;
};
}
//Função Actualizar a Caixa de Entrada de Mensagens
private void UpdateTextbox(string text)
{
text1.Text += "\r\n";
text1.Text += text;
}
//Recieved Mesages
public void RecievedMessage(string message)
{
UpdateTextbox(message);
}
//TCP Connection
public StreamWriter Outgoing;
private StreamReader Incoming;
private TcpClient Connection;
private Thread Messages;
private IPAddress IP;
//public string host;
//public string nick;
//MainChat m_ParentForm;
bool isConnected;
//Função Conectar
public void Connect()
{
try
{
IP = IPAddress.Parse("10.0.2.2");
Connection = new TcpClient();
Connection.Connect(IP, 1986);
Outgoing = new StreamWriter(Connection.GetStream());
Outgoing.WriteLine("EcoDuty");
Outgoing.Flush();
//m_ParentForm.Vis(true);
Messages = new Thread(new ThreadStart(this.Communication));
Messages.Start();
}
catch (Exception e) { Disconnected(e.Message); }
}
private void Communication()
{
Incoming = new StreamReader(Connection.GetStream());
string check = Incoming.ReadLine();
if (check[0] == '1')
{
//Vis(true);
isConnected = true;
}
else
{
string Reason = "Disconnected: ";
Reason += check.Substring(2, check.Length - 2);
Disconnected(Reason);
return;
}
while (isConnected == true)
{
try
{
ServerMessage(Incoming.ReadLine());
}
catch (Exception e)
{
if (isConnected == true)
{
Disconnected("Connection to server lost");
Console.WriteLine("Connection Lost: " + e.ToString());
}
break;
}
}
}
private void ServerMessage(string message)
{
try
{
RecievedMessage(message);
}
catch { }
}
public void CloseConnection()
{
isConnected = false;
Incoming.Close();
Outgoing.Close();
Connection.Close();
Messages.Abort();
}
public void SendMessage(string message)
{
Outgoing.WriteLine(message);
Outgoing.Flush();
}
}
}
You seem to be trying to update the text from a non UI thread (if you follow the calls stack you see that the method is triggered from a dedicated thread you spawn):
private void UpdateTextbox(string text)
{
text1.Text += "\r\n";
text1.Text += text;
}
Instead use RunOnUiThread() to schedule the text change to run on the UI thread:
private void UpdateTextbox(string text)
{
RunOnUiThread(() =>
{
text1.Text += "\r\n";
text1.Text += text;
});
}
Also you should get rid of the empty exception catching you do along the way - this most likely masked the problem.
Also always check the catlog for exceptions they usually are a good indicator.