I followed this tutorial
The main problem is :
What is WAKELOCK_KEY in their code ? What I must put here ?
What is classType in their code ? What I must put here ?
For the WAKELOCK_KEY I just put "NOTIF", and for classType is use typeof(MyIntentService).
I receive notification but can't receive notification when I kill the application. So how to manage this in Xamarin (no PushSharp or similar lib) ?
(My code is the same as in the tutorial, except for WAKELOCK_KEY and classType).
If you follow the tutorial, you just have to do that (seems my solution for the wakelock_key and the classType was good)
:-)
[BroadcastReceiver]
[IntentFilter(new[] { Android.Content.Intent.ActionBootCompleted })]
public class BootReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
MyIntentService.RunIntentInService(context, intent);
}
}
Related
I have problem with broadcast receiver in xamarin.android. Can't get it to work.
I have notification in my app working and I want to change some things in my app after I get notification (e.g. Toast message or change icon of a button) But it doesn't work. I don't know what am I doing wrong and I can't find solution because all the topics are Java related. I need something, event or broadcastreceiver to fire when user gets notification and then I want to do some stuff in my MainActivity.
So, this is the code.
BroadcastReceiver class:
[BroadcastReceiver(Enabled = true, Exported = false)]
public class MyMessageReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
bool messageReceived = intent.GetBooleanExtra("messageReceived", false);
}
}
OnMessageReceived method:
{
base.OnMessageReceived(message);
SendNotification(message.GetNotification().Body);
LocalBroadcastManager broadcaster = LocalBroadcastManager.GetInstance(this);
Intent intent = new Intent("message");
intent.PutExtra("messageReceived", true);
broadcaster.SendBroadcast(intent);
}
And OnResume and OnPause methods:
protected override void OnResume()
{
base.OnResume();
LocalBroadcastManager.GetInstance(this).RegisterReceiver(myReceiver, new IntentFilter("message"));
RegisterReceiver(myReceiver, new IntentFilter("message"));
}
protected override void OnPause()
{
base.OnPause();
LocalBroadcastManager.GetInstance(this).UnregisterReceiver(myReceiver);
}
I don't know how to receive that info for example in my OnCreate method in MainActivity? I tried with
messageReceived = Intent.GetBooleanExtra("messageReceived", false);
if (messageReceived)
{
Toast.MakeText(this, "new notification", ToastLength.Long).Show();
}
But that doesn't work, messageReceived is null.
I know it is a bit too late but better late than never :
After analysing the firebase messaging I have done a suitable workaround for this purpose :
When your application is in the background the handle intent method is called by default on receiving push notification :
public override void HandleIntent(Intent p0)
{
base.HandleIntent(intent);
//Your code to know that you received a notification (backgrounnd)
// Use shared preference for this
}
Don't know how to use shared preferences check this.
For more information on how handle intent works check my answer out here.
When the application is in the foreground you can simply use on message received method as such :
public override void OnMessageReceived(Context context, Intent intent)
{
//Your code to know that you received a notification (backgrounnd)
// Use shared preference for this
}
Then, wherever you need to use this you can get a flag or count or whatever using shared preferences.
In case of any queries revert!
I'm starting learning MVVM cross, In the android app, I have a splash screen class:
[Activity(MainLauncher = true,
Label = "#string/app_name",
Theme = "#style/Theme.Splash",
NoHistory = true,
ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation,
ScreenOrientation = ScreenOrientation.Portrait)]
public class SplashScreen : MvxSplashScreenActivity
{
public SplashScreen() : base(Resource.Layout.SplashScreen)
{
}
}
and this is the Setup class:
public class Setup : MvxAndroidSetup
{
protected Setup(Context applicationContext) : base(applicationContext)
{
}
protected override IMvxApplication CreateApp()
{
return null;
}
}
the problem is that the debugger doesn't hit the constructor of the Setup Class, instead I get "An unhandled exception" after the constructor of the splash screen
EDIT
I've already defined the App class in the PCL project:
public class App : MvxApplication
{
public override void Initialize()
{
base.Initialize();
}
also defined the AppStart:
public class AppStart : MvxNavigatingObject, IMvxAppStart
{
public async void Start(object hint = null)
{
//hardcoded login for this demo
//var userService = Mvx.Resolve<IUserDataService>();
//await userService.Login("gillcleeren", "123456");
ShowViewModel<MainViewModel>();
}
}
The main reason behind this project is to understand the sequence of code required and executed by MVVM Cross, so I provide the minimum code till it runs successfully without runtime errors.
Update
I have read your code again more thoroughly and I can see the issue now. You defined the constructor of the Setup class as protected, which makes it invisible for activation.
On MvvmCross for Android the magic happens inside MvxAndroidSetupSingleton class (see the source code here) which searches for the Setup type you defined. The FindSetupType method looks for your defined Setup class first and then inside the CreateSetup method Activator.CreateInstance is used to build the Setup instance. The CreateInstance method variant used however searches only for public constructors, which means it doesn't find your protected one. The result is that it cannot build the Setup class and crashes.
Original answer
The reason this happens is that you have no Core libary that would define the MvvmCross App class and would initialize other required setup. I suggest you to start with a simple tutorial or to look into the official sample projects to see what is necessary to make MvvmCross work in a Xamarin.Android app.
I've been searching for a way to send a local message within my app and found a tutorial from the Xamarin website on Broadcast Receivers here, more specifically at the bottom of the web page concerning LocalBroadcastManager. I followed the tutorial and read the page a few times but my BroadcastReceiver class still isn't receiving anything when I send a message. I've hit a lot of the questions concerning LocalBroadcastManager for java, but can't seem to figure out what's missing for C#.
This is the code that's triggering a sent message:
Intent intent = new Intent("dirty");
intent.PutExtra("dirtyAppCount", dirtyAppCount);
LocalBroadcastManager.GetInstance(Context).SendBroadcast(intent);
Here's where I'm registering my receiver in OnResume():
_dirtyMessageReceiver = new DirtyBroadcastReceiver();
RegisterReceiver(_dirtyMessageReceiver, new IntentFilter("dirty"));
Unregistering receiver in OnPause():
UnregisterReceiver(_dirtyMessageReceiver);
And here's my receiver class:
[BroadcastReceiver(Enabled = true, Exported = false)]
public class DirtyBroadcastReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
int dirtyAppCount = intent.GetIntExtra("dirtyAppCount", 0);
OnMessageReceived?.Invoke(this, new MessageArgs(dirtyAppCount));
}
}
There are two issues with this code. First, you should use be registering the Receiver with the LocalBroadcastManager:
_dirtyMessageReceiver = new DirtyBroadcastReceiver();
RegisterReceiver(_dirtyMessageReceiver, new IntentFilter("dirty"));
Should be
_dirtyMessageReceiver = new DirtyBroadcastReceiver();
LocalBroadcastManager.GetInstance(this).RegisterReceiver(_dirtyMessageReceiver, new IntentFilter("dirty"));
Secondly, the Unregistering of the Receiver should be one against the LocalBroadcastManager as well:
UnregisterReceiver(_dirtyMessageReceiver);
becomes
LocalBroadcastManager.GetInstance(this).UnregisterReceiver(_dirtyMessageReceiver);
You need to add a broadcast receiver for these.For example, Set Android.Content.Intent to ActionTimeTick so that android os will broadcast message(an android intent) whenever time is changed.
[BroadcastReceiver(Enabled = true)]
[IntentFilter(new[] { Android.Content.Intent.ActionTimeTick })]
public class GridStartBroadcastReceiver : BroadcastReceiver
{
public static readonly string GRID_STARTED = "GRID_STARTED";
public override void OnReceive(Context context, Intent intent)
{
if (intent.Action == GRID_STARTED)
{
//your logic
}
}
}
you need to register the broadcast receiver first. Add these code to oncreate method to register broadcast receiver.
IntentFilter filter = new IntentFilter(GridStartBroadcastReceiver.GRID_STARTED);
filter.AddCategory(Intent.CategoryDefault);
_receiver = new GridStartBroadcastReceiver();
RegisterReceiver(_receiver, filter);
Next send the broadcast to the broadcast receiver.
//calling
Intent BroadcastIntent = new Intent(this, typeof(MainActivity.GridStartBroadcastReceiver));
BroadcastIntent.SetAction(MainActivity.GridStartBroadcastReceiver.GRID_STARTED);
BroadcastIntent.AddCategory(Intent.CategoryDefault);
SendBroadcast(BroadcastIntent);
In Visual Studio I created a new class library (Xamarin Forms) :-
Xamarin class library
Here I added my service and gave it the most basic implementation possible for a started service (note - not a bound service. Expecting - toasts to be displayed when the application is started / stopped :-
namespace AndroidBatteryService
{
public class AndroidBatteryService : Service
{
public AndroidBatteryService()
{
}
[return: GeneratedEnum]
public override StartCommandResult OnStartCommand(Intent intent, [GeneratedEnum] StartCommandFlags flags, int startId)
{
Toast.MakeText(this, "The Battery Service was just started", ToastLength.Long).Show();
return base.OnStartCommand(intent, flags, startId);
}
public override void OnCreate()
{
base.OnCreate();
}
public override void OnDestroy()
{
base.OnDestroy();
Toast.MakeText(this, "The Battery Service has been stopped", ToastLength.Long).Show();
}
public override IBinder OnBind(Intent intent)
{
//started service, NOT a binded service - return null...
return null;
}
}
}
In another project I am invoking this service my running the following code :-
public void StartBatteryService()
{
Intent intent = new Intent(Android.App.Application.Context, typeof(AndroidBatteryService.AndroidBatteryService));
Android.App.Application.Context.StartService(intent);
}
The code runs (I can step over it), but the OnStartCommand method in the actual service is not run and I am expecting it to. Any ideas??
I think the problem is that you need to decorate the service class with:-
[Service (Label = "AndroidBatteryService", Icon = "#drawable/Icon") ]
This causes Xamarin to put the following into the generated AndroidManifest.xml file during the build (you can find this in the \obj\Debug\android directory)
<service android:icon="#drawable/icon" android:label="AndroidBatteryService" android:name="md55...1a.AndroidBatteryService" />
I used a very similar piece of code in my app and it worked fine. (Although you've probably worked this out by now.)
Whats the difference b/w using Activity vs Application in Xamarin? Why would one want to use one approach over another?
For example, when I create a new Xamarin Form project in VS I get the follow:
[Activity(Label = "eApprove Main Activity", MainLauncher = true, Icon = "#drawable/eA_icon")]
public class MainActivity : Activity
{
...
}
I have also seen examples on internet where people are using Application class as their main Entry point:
namespace MyExpenses.Android
{
[Application(Theme = "#android:style/Theme.Holo.Light") ]
public class MyExpensesApplication : Application
{
public static Activity CurrentActivity { get; set; }
public MyExpensesApplication(IntPtr handle, global::Android.Runtime.JniHandleOwnership transer)
:base(handle, transer)
{
}
public override void OnCreate()
{
base.OnCreate();
}
}
}
Please make sure you do not confuse a classical Xamarin.Android app with the android portion of a Xamarin.Forms app. My quick and easy answer/recommendation would be that you would have one Application class per App project per platform and as many Activities as you like. The application is your entry point that kicks of any numbers activities based on your needs...