How to call same service instance from multiple activities in Android - c#

I've just started looking into Xamarin and just can not to wrap around my head how to make multiple Activities have a reference same instance of service.
I am starting KeyPressedReceiver from MainActivity and start listening for power button being pressed.
When three click are being made, I am calling service method InitCancelActivity, which starts playing mp3 file and opens CancelActivity.
In CancelActivity there is a text field and a button. And when user press this button, I want the value from text field to be passes to the GeneralService method KillAlert.
The question is how to reference instance of GeneralService (which is already created) from CancelActivity, so I could call KillAlert?
And this part
if (_service == null)
_service = new GeneralService();
looks absolutely wrong. Should I instantiate it in MainActivity and pass to a KeyPressedReceiver constructor?
[Activity(Label = "TTTT", MainLauncher = true, Icon = "#drawable/icon")]
public class MainActivity : Activity
{
KeyPressedReceiver receiver;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
receiver = new KeyPressedReceiver();
RegisterReceiver(receiver, new IntentFilter(Intent.ActionScreenOn));
}
}
[BroadcastReceiver(Enabled = true)]
public class KeyPressedReceiver : BroadcastReceiver
{
private GeneralService _service;
private int _clicks = 0;
public override void OnReceive(Context context, Intent intent)
{
if (_service == null)
_service = new GeneralService();
_clicks++;
if (_clicks > 5)
{
_service.InitCancelActivity();
}
}
}
[Service(Name = "com.ff.GeneralService")]
public class GeneralService : Service {
private readonly Android.Media.MediaPlayer _player;
public GeneralService()
{
_player = new Android.Media.MediaPlayer();
}
public void RaiseAlert()
{
// start playing .mp3 file
}
public void KillAlert(string pass)
{
// stop playing .mp3 file
}
public void InitCancelActivity()
{
this.RaiseAlert();
var i = new Intent(this, typeof(CancelActivity));
i.SetFlags(ActivityFlags.NewTask);
this.StartActivity(i);
}
}
[Activity(Label = "CancelActivity")]
public class CancelActivity : Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.cancel);
this.FindViewById(Resource.Id.cancelButtonYes).Click += delegate
{
var password = this.FindViewById(Resource.Id.cancelPassword);
// call KillAlert method from GeneralServic
};
}
}

Create static GeneralService instance and use in Cancel Activity.
for example
[Service(Name = "com.ff.GeneralService")]
public class GeneralService : Service {
private readonly Android.Media.MediaPlayer _player;
public static generalService;
public GeneralService()
{
_player = new Android.Media.MediaPlayer();
generalService=this
}
public void RaiseAlert()
{
// start playing .mp3 file
}
public void KillAlert(string pass)
{
// stop playing .mp3 file
}
public void InitCancelActivity()
{
this.RaiseAlert();
var i = new Intent(this, typeof(CancelActivity));
i.SetFlags(ActivityFlags.NewTask);
this.StartActivity(i);
}
}
and use in CancelActivity like below example
[Activity(Label = "CancelActivity")]
public class CancelActivity : Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.cancel);
this.FindViewById(Resource.Id.cancelButtonYes).Click += delegate
{
var password = this.FindViewById(Resource.Id.cancelPassword);
// call KillAlert method from GeneralServic
GeneralService.generalService.KillAlert(password.TEXT);
};
}
}

Related

Xamarin.Forms Firebasepushnotification plugin OnNotificationOpened event causes app to restart for android

I'm trying to handle a notifications opening on android that I've sent through Google's FCM on the SharedProject level by using "Plugin.FirebasePushNotification" plugin and subscribing to "OnNotificationOpened" event.
When I try to open the notification while the app is in the background I'm able to hit a breakpoint inside "OnNotificationOpened" event but after the work inside the event ends the App const. is hit and the application restarts.
I want the application to continue from its last state and hit "OnResume" method that is located inside the App class.
I've done some research about it online and almost all of them were about how splash activity might cause this issue so I've disabled my splash activity by turning the whole "SplashActivity.cs" file into a comment except the namespace and usages and implemented the wanted features of splashactivity(style) inside the "MainActivity" class after that I made sure my "MainActivity" class was the only activity that had it's "MainLauncher" attribute set to true but the problem continues.
Here are the relevant classes:
FirebaseReg.cs
public class FirebaseReg
{
public static void FirebaseInit()
{
CrossFirebasePushNotification.Current.OnTokenRefresh += (s, p) =>
{
System.Diagnostics.Debug.WriteLine($"TOKEN : {p.Token}");
CrossFirebasePushNotification.Current.Subscribe("defaultTopic");
};
CrossFirebasePushNotification.Current.OnNotificationOpened += (s, p) =>
{
try
{
//Breakpoint hits here and I'm able to finish all my work without any exceptions
}
catch (Exception ex)
{
}
};
CrossFirebasePushNotification.Current.OnNotificationAction += (s, p) =>
{
};
CrossFirebasePushNotification.Current.OnNotificationReceived += Current_OnNotificationReceived;
}
private static void Current_OnNotificationReceived(object source, FirebasePushNotificationDataEventArgs e)
{
//DO WORK
}
}
App.xaml.cs
public partial class App : Application
{
public static Uri ServerUri = new Uri(" ");
public static bool IsInForeground { get; set; } = false;
public App()
{
try
{
InitializeComponent(); //After the work in OnNotificationOpened ends breakpoint goes here
Application.Current.UserAppTheme = OSAppTheme.Unspecified;
Application.Current.MainPage = new LoginPage();
}
catch (Exception ex)
{
}
}
protected override void OnStart()
{
IsInForeground = true;
}
protected override void OnSleep()
{
IsInForeground = false;
}
protected override void OnResume()
{
IsInForeground = true;
}
}
MainActivity.cs
[Activity(Label = "TestProject1", Theme = "#style/MyTheme.Splash", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize )]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.Window.RequestFeature(WindowFeatures.ActionBar);
// Name of the MainActivity theme you had there before.
// Or you can use global::Android.Resource.Style.ThemeHoloLight
base.SetTheme(Resource.Style.MainTheme);
base.OnCreate(savedInstanceState);
Rg.Plugins.Popup.Popup.Init(this);
UserDialogs.Init(this);
Xamarin.FormsGoogleMaps.Init(this, savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
FirebasePushNotificationManager.ProcessIntent(this ,Intent);
LoadApplication(new App());
}
protected override void OnNewIntent(Intent intent)
{
FirebasePushNotificationManager.ProcessIntent(this, intent);
base.OnNewIntent(intent);
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)
{
Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
MainApplication.cs
[Application]
public class MainApplication : Application, Application.IActivityLifecycleCallbacks
{
public MainApplication(IntPtr handle, JniHandleOwnership transer) : base(handle, transer)
{
}
public override void OnCreate()
{
base.OnCreate();
RegisterActivityLifecycleCallbacks(this);
if (Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.O)
{
FirebasePushNotificationManager.DefaultNotificationChannelId = "DefaultChannel";
FirebasePushNotificationManager.DefaultNotificationChannelName = "defaultTopic";
}
#if DEBUG
FirebasePushNotificationManager.Initialize(this, true);
FirebaseRegister.FirebaseInit();
#else
FirebasePushNotificationManager.Initialize(this, false);
FirebaseRegister.FirebaseInit();
#endif
}
public override void OnTerminate()
{
base.OnTerminate();
UnregisterActivityLifecycleCallbacks(this);
}
public void OnActivityCreated(Activity activity, Bundle savedInstanceState)
{
CrossCurrentActivity.Current.Activity = activity;
}
public void OnActivityDestroyed(Activity activity)
{
}
public void OnActivityPaused(Activity activity)
{
}
public void OnActivityResumed(Activity activity)
{
CrossCurrentActivity.Current.Activity = activity;
}
public void OnActivitySaveInstanceState(Activity activity, Bundle outState)
{
}
public void OnActivityStarted(Activity activity)
{
CrossCurrentActivity.Current.Activity = activity;
}
public void OnActivityStopped(Activity activity)
{
}
}
From the Android docs, it states this:
If it has declared its launch mode to be "multiple" (the default) and
you have not set FLAG_ACTIVITY_SINGLE_TOP in the same intent, then it
will be finished and re-created; for all other launch modes or if
FLAG_ACTIVITY_SINGLE_TOP is set then this Intent will be delivered to
the current instance's onNewIntent().
That's why your app is restarting.
The launchMode attribute of the activity affects how the activity is launched.
singleTop, singleTask, or singleInstance should be used to prevent the notification intent from creating a new activity instance.
The flag FLAG_ACTIVITY_NEW_TASK doesn't influence a new activity being created, but makes the launched activity the root of a new task.
For more, check:
https://developer.android.com/guide/topics/manifest/activity-element.html#lmode
https://developer.android.com/guide/components/activities/tasks-and-back-stack

Xamarin Android: Set ExpandableListView.SetOnGroupExpandListener

I want to set a listener for ExpandableList. I have searched around but found only android specific following code. How can I convert the following android code to Xamarin.
ExpandableList expListView; // suppose it is initilized
expListView.setOnGroupExpandListener(new IOnGroupExpandListener() {
int previousItem = -1;
#Override
public void onGroupExpand(int groupPosition)
{
if (groupPosition != previousItem)
expandableList.collapseGroup(previousItem);
previousItem = groupPosition;
}
});
You can implement the interface ExpandableListView.IOnGroupExpandListener on the Activity (or Fragment) or as a separate Java-based object.
Activity Example:
public class MainActivity : Activity, ExpandableListView.IOnGroupExpandListener
{
~~~
ExpandableListView expListView;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
expListView.SetOnGroupExpandListener(this);
}
~~~
public void OnGroupExpand(int groupPosition)
{
// implement your onexpand code
}
~~~
}
Separate Class:
public class MyExpander : Java.Lang.Object, ExpandableListView.IOnGroupExpandListener
{
public void OnGroupExpand(int groupPosition)
{
// implement your onexpand code
}
}

Unable to access data from service in activity

I am building a Xamarin.Android application. I have a working service, and I am trying to get data from that service to an activity that I have. I know that people get upset over too much code being posted, but I am unsure where my issue is. I am going post what I think is necessary:
Service
[Service]
public class DataService : Service
{
public List<MyObjects> MyObjectList { get; private set; }
public IBinder Binder { get; private set; }
public override IBinder OnBind(Intent intent)
{
this.Binder = new DataServiceBinder(this);
return this.Binder;
}
public override void OnCreate()
{
base.OnCreate();
pendingIntent = PendingIntent.GetActivity(this, 0, new Intent(this, typeof(MainActivity)), 0);
StartForeground(NotificationID, GetNotification("Started Sync"));
//Do some work here to instantiate and populate the List
}
}
Service Binder
public class DataServiceBinder : Binder
{
public DataServiceBinder(DataService service)
{
Service = service;
}
public DataService Service { get; private set; }
}
Service Connection
public class DataServiceConnection : Object, IServiceConnection
{
public DataService Service { get; private set; }
public DataServiceBinder dataServiceBinder;
public bool IsConnected { get; private set; }
public void OnServiceConnected(ComponentName name, IBinder service)
{
dataServiceBinder = service as DataServiceBinder;
IsConnected = this.dataServiceBinder != null;
Service = dataServiceBinder.Service;
ServiceConnectionChanged?.Invoke(this, true);
}
public void OnServiceDisconnected(ComponentName name)
{
ServiceConnectionChanged?.Invoke(this, false);
Service = null;
}
public event EventHandler<bool> ServiceConnectionChanged;
}
Activity
public class MyDataActivity : AppCompatActivity
{
private DataServiceConnection DataServiceConnection;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
if (DataServiceConnection == null)
{
this.DataServiceConnection = new DataServiceConnection();
}
Intent serviceToStart = new Intent(this, typeof(DataService));
BindService(serviceToStart, this.DataServiceConnection, Bind.AutoCreate);
SetContentView(Resource.Layout.MyDataLayout);
var adapter = new MyDataAdapter(DataServiceConnection.Service.MyObjectList);
}
protected override void OnResume()
{
var intent = new Intent(this, typeof(DataService));
BindService(intent, DataServiceConnection, Bind.AutoCreate);
base.OnResume();
}
protected override void OnPause()
{
UnbindService(DataServiceConnection);
base.OnPause();
}
In my activity, when I try to pass the adapter the list from the service, the "Service" is null, and there for I get a null reference exception. Why is my Service null? Am I not binding my service properly? For the record, they service is started in the Application context.
Ok, I found the solution. Since connecting to the service is asynchronous I cannot expect the adapter to be able to get data synchronously like this:
var adapter = new MyDataAdapter(DataServiceConnection.Service.MyObjectList);
Instead, I modified my activity to look like this:
public class MyDataActivity : AppCompatActivity
{
private DataServiceConnection DataServiceConnection;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
if (DataServiceConnection == null)
{
this.DataServiceConnection = new DataServiceConnection();
}
Intent serviceToStart = new Intent(this, typeof(DataService));
BindService(serviceToStart, this.DataServiceConnection, Bind.AutoCreate);
DataServiceConnection.ServiceConnectionChanged += ServiceConnectionChanged;
SetContentView(Resource.Layout.MyDataLayout);
}
private void ServiceConnectionChanged(object sender, bool isConnected)
{
if(DataServiceConnection.Service == null)
{
return;
}
if(isConnected)
{
var adapter = new MyDataAdapter(DataServiceConnection.Service.MyObjectList);
}
}
protected override void OnResume()
{
var intent = new Intent(this, typeof(DataService));
BindService(intent, DataServiceConnection, Bind.AutoCreate);
base.OnResume();
}
protected override void OnPause()
{
UnbindService(DataServiceConnection);
base.OnPause();
}
I also modified my Service Connection as such:
public class DataServiceConnection : Object, IServiceConnection
{
public DataService Service { get; private set; }
public MyDataActivity DataActivity;
public event EventHandler<bool> ServiceConnectionChanged;
public DataServiceConnection(MyDataActivity myDataActivity)
{
DataActivity = myDataActivity;
}
public void OnServiceConnected(ComponentName name, IBinder service)
{
dataServiceBinder = service as DataServiceBinder;
Service = dataServiceBinder.Service;
ServiceConnectionChanged?.Invoke(this, true);
}
public void OnServiceDisconnected(ComponentName name)
{
ServiceConnectionChanged?.Invoke(this, false);
Service = null;
}
}
Now my solution only tries to send data to the adapter when the service is connected. This solution is working for me, and I hope it helps anyone else.

How to get variable from another class to OnPrepare/CreateOptionsMenu

I have a simple wifi app. It is just scanning wifis and listing them. I figured out my ScanResult List is filling in another method but in OnPrepare/CreateOptionsMenu it is always null.
This method calls first when program starts I know that, but when i try to call it again with InvalidateOptionsMenu(); nothing changes. Here is my piec of code:
MainActivity:
public class MainActivity : Activity
{
public static Context context;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
Button wifiButton = FindViewById<Button>(Resource.Id.popupButton);
RegisterReceiver(new WiFiReceiver(), new IntentFilter(WifiManager.ScanResultsAvailableAction));
((WifiManager)GetSystemService(WifiService)).StartScan();
wifiButton.Click += (s, arg) => {
InvalidateOptionsMenu();
PopupMenu menu = new PopupMenu(this, wifiButton);
menu.Inflate(Resource.Menu.menu);
menu.Show();
};
}
public override bool OnCreateOptionsMenu(IMenu menu) {
WiFiReceiver wifiReceiver = new WiFiReceiver();
IList<ScanResult> availableWifis = wifiReceiver.GetWifiList();//This is always null
if (availableWifis != null) {
foreach (ScanResult token in availableWifis) {
menu.Add(token.Ssid);
}
}
return base.OnCreateOptionsMenu(menu);
}
}
WiFi Scanning this class:
class WiFiReceiver : BroadcastReceiver {
private IList<ScanResult> wifiList;
private string message;
public override async void OnReceive(Context context, Intent intent) {
MainActivity mainActivity = (MainActivity)context;
WifiManager wifiManager = (WifiManager)mainActivity.GetSystemService(Context.WifiService);
this.message = string.Join("\r\n", wifiManager.ScanResults
.Select(r => $"{r.Ssid} - {r.Level} dB"));
this.wifiList = wifiManager.ScanResults.ToList(); //This has connection informations
mainActivity.DisplayText(message);
await Task.Delay(TimeSpan.FromSeconds(1));
wifiManager.StartScan();
}
public IList<ScanResult> GetWifiList() {
return wifiList;
}

Send Data from a Service to BroadcastReceiver of other Activity (Xamarin Android)

I have a problem with sending Location from service to custom BroadcastReceiver.
This is my BroadcastReceiver.cs
[BroadcastReceiver]
class MyBroadcastReceiver : BroadcastReceiver
{
public static readonly string GRID_STARTED = "GRID_STARTED";
public event EventHandler<OnLocationChangedEventArgs> mOnLocationChanged;
private Location location;
public override void OnReceive(Context context, Intent intent)
{
if (intent.Action == GRID_STARTED)
{
Toast.MakeText(context, "Grid Started", ToastLength.Short).Show();
//location = JsonConvert.DeserializeObject<Location>(intent.GetStringExtra("location"));
//mOnLocationChanged.Invoke(this, new OnLocationChangedEventArgs(location));
}
}
}
If I UNCOMMENT two lines in the upper code my app suddenly stops. I cannot tell you what is the error because, while developing Xamarin apps debugging is stopped by an internal error (I read about it on Xamarin Forums but couldn't find time to deal with it).
This is what I have done in service:
private void BroadcastStarted(Location location)
{
Intent BroadcastIntent = new Intent(this, typeof(MyBroadcastReceiver));
BroadcastIntent.PutExtra("location",JsonConvert.SerializeObject(location));
BroadcastIntent.SetAction(MyBroadcastReceiver.GRID_STARTED);
BroadcastIntent.AddCategory(Intent.CategoryDefault);
SendBroadcast(BroadcastIntent);
}
I'm using Newtonsoft.Json for sending an objet.
Any help would be appreciated.
UPDATE:
Ok, somehow I managed to reveal the error:
Unable to find a constructor to use for type
Android.Location.Location. A class should either have a default
constructor,one constructor with arguments or a constructor marked
with JsonConstructor attribute.
UPDATE:
Whole service code:
using Newtonsoft.Json;
namespace GoogleMaps
{
public class OnLocationChangedEventArgs
{
Location location;
public Location Location
{
get { return location; }
set { location = value; }
}
public OnLocationChangedEventArgs(Location location)
{
this.location = location;
}
}
[Service]
class MyService : Service
{
private LocationManager locationManager = null;
public MyService()
{
}
private class MyLocationListener : Java.Lang.Object,ILocationListener
{
Location mLastLocation;
public event EventHandler<OnLocationChangedEventArgs> onLoc;
public MyLocationListener(String provider)
{
mLastLocation = new Location(provider);
}
public void OnLocationChanged(Location location)
{
try
{
mLastLocation.Set(location);
onLoc.Invoke(this, new OnLocationChangedEventArgs(mLastLocation));
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
public void OnProviderDisabled(string provider)
{
}
public void OnProviderEnabled(string provider)
{
}
public void OnStatusChanged(string provider, [GeneratedEnum] Availability status, Bundle extras)
{
}
}
private MyLocationListener locationListener = new MyLocationListener("network");
public override IBinder OnBind(Intent intent)
{
return null;
}
private void BroadcastStarted(Location location)
{
Intent BroadcastIntent = new Intent(this, typeof(MyBroadcastReceiver));
BroadcastIntent.PutExtra("location",JsonConvert.SerializeObject(location));
BroadcastIntent.SetAction(MyBroadcastReceiver.GRID_STARTED);
BroadcastIntent.AddCategory(Intent.CategoryDefault);
SendBroadcast(BroadcastIntent);
}
[return: GeneratedEnum]
public override StartCommandResult OnStartCommand(Intent intent, [GeneratedEnum] StartCommandFlags flags, int startId)
{
return StartCommandResult.Sticky;
}
public override void OnCreate()
{
try
{
base.OnCreate();
InitializeLocationManager();
locationManager.RequestLocationUpdates(LocationManager.NetworkProvider, 0, 0, locationListener);
locationListener.onLoc += MyService_onLoc;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
private void MyService_onLoc(object sender, OnLocationChangedEventArgs e)
{
BroadcastStarted(e.Location);
}
public override void OnDestroy()
{
base.OnDestroy();
locationManager.RemoveUpdates(locationListener);
}
private void InitializeLocationManager()
{
if (locationManager == null)
{
locationManager = (LocationManager)GetSystemService(LocationService);
}
}
}
}
UPDATE:
This is what I told in 6th comment:
public override void OnReceive(Context context, Intent intent)
{
if (intent.Action == GRID_STARTED)
{
try
{
Toast.MakeText(context, "Grid Started", ToastLength.Short).Show();
a = new LatLng(intent.GetDoubleExtra("latitude",0),intent.GetDoubleExtra("longitude",0));
mOnLocationChanged.Invoke(this, new OnLatLngChangedEventArgs(a)); // NULL EXCEPTION LINE
}
catch (Exception ex)
{
Toast.MakeText(context, ex.Message, ToastLength.Short).Show();
}
}
}
Why is event handler mOnLocationChanged equal to null?
And service's part:
private void BroadcastStarted(Location location)
{
Intent BroadcastIntent = new Intent(this, typeof(MyBroadcastReceiver));
BroadcastIntent.PutExtra("latitude",location.Latitude);
BroadcastIntent.PutExtra("longitude", location.Longitude);
BroadcastIntent.SetAction(MyBroadcastReceiver.GRID_STARTED);
BroadcastIntent.AddCategory(Intent.CategoryDefault);
SendBroadcast(BroadcastIntent);
}
Send data (not object) from Service (using SendBroadcast) to BroadcastReceiver (in MainActivity):
Android-java Gist here. (100% working and tested code).
C# equivalent Service Class code:
(see import statements in a gist for required namespaces/classes)
[Service]
public class BackgroundService : Service
{
private static LocationReceiver mTickReceiver;
public BackgroundService()
{
}
public override IBinder OnBind(Intent arg0)
{
return null;
}
public override StartCommandResult OnStartCommand (Android.Content.Intent intent, StartCommandFlags flags, int startId)
{
return StartCommandResult.Sticky;
}
public override void OnCreate()
{
registerReceiver();
}
public override void OnDestroy()
{
UnregisterReceiver(mTickReceiver);
mTickReceiver = null;
}
private void registerReceiver()
{
mTickReceiver = new LocationReceiver();
IntentFilter filter = new IntentFilter(Android.Content.Intent.ActionTimeTick); // this will broadcast Intent every minute
RegisterReceiver(mTickReceiver, filter);
}
// you can write this class in separate cs file
[BroadcastReceiver(Enabled = true)]
[IntentFilter(new[] { Android.Content.Intent.ActionTimeTick })]
public class LocationReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
// sample data, you should get your location here,
// one way is to implement location logic in this class
double SampleLatitude=52.01566;
double SampleLongitude=65.00487;
// assuming above coordinates are from some location manager code
Intent I = new Intent();
i.SetAction("LocationData");
i.PutExtra("Latitude", SampleLatitude);
i.PutExtra("Longitude", SampleLongitude);
// PREPARE BROADCAST FOR MAINACTIVITY
SendBroadcast(i); // this broadcast will be received by mainactivity
}
}
}
C# equivalent MainActivity Class code:
(see import statements in a gist for required namespaces/classes)
public class MainActivity : AppCompatActivity
{
protected override Void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(R.layout.activity_main);
Intent i = new Intent(this, typeof(BackgroundService));
StartService(i);
IntentFilter filter = new IntentFilter("LocationData");
RegisterReceiver(new MyBroadcastReceiver(), filter);
}
// public static variables of MainActivty can be accessed and manipulated in this class
[BroadcastReceiver(Enabled = true)]
[IntentFilter(new[] { "LocationData" })]
class MyBroadcastReceiver : BroadcastReceiver
{
public override Void OnReceive(Context context, Intent intent)
{
// GET BROADCAST FROM RECEIVER IN THE BACKGROUND SERVICE CLASS
if (intent.GetAction() == "LocationData")
{
double lat=intent.GetDoubleExtra("Latitude", 0);
double lng=intent.GetDoubleExtra("Longitude", 1);
String LocationDataFromService=lat+","+lng;
// REPLACE this with console.writeline
Log.d("LocationDataFromService",LocationDataFromService);
}
}
}
}
In AndroidManifest.xml declare the service as:
<service android:name=".BackgroundService">
</service>
It may still throw some errors. Hope this helps.
You can also implement interface in MyBroadcastReceiver.cs.I think its easier way.
Here is the code:
MyBroadcastReceiver.cs
[BroadcastReceiver]
class MyBroadcastReceiver : BroadcastReceiver
{
public interface LocationDataInterface
{
void OnLocationChanged(LatLng point);
}
public static readonly string GRID_STARTED = "GRID_STARTED";
private LocationDataInterface mInterface;
private LatLng a;
public override void OnReceive(Context context, Intent intent)
{
if (intent.Action == GRID_STARTED)
{
try
{
// data you got from background service
a = new LatLng(intent.GetDoubleExtra("latitude",0), intent.GetDoubleExtra("longitude",0));
mInterface = (LocationDataInterface)context;
mInterface.OnLocationChanged(a);
}
catch (Exception ex)
{
Toast.MakeText(context, ex.Message, ToastLength.Short).Show();
}
}
}
}
MainActivity.cs
public class MainActivity : Activity, MyBroadcastReceiver.LocationDataInterface
{
...
public void OnLocationChanged(LatLng point)
{
// textview where you want to show location data
locationText.Text += point.Latitude + "," + point.Longitude;
// things that you want to do with location point
}
}
If there are some problems with this approach, feel free to comment it.

Categories

Resources