0

I'm not usually posting questions on forums like this one, but today my frustration reached the sky.

I am trying to implement a solution that would let me update the Exchange rate list in my application every every hour/day (doesn't matter). I was looking for the answer to my problem on many forums, but even though other people had the same problem of onReceive not being called, none of answers helped me.

I am currently trying to run a Broadcast Receiver that is being fired by AlarmManager's SetRepeating Method. My code for Main activity + Receiver + Manifest look like this:

Main method (just a block of code with starting the alarm):

    var lvarManager = (AlarmManager)GetSystemService (Context.AlarmService);

    Intent lvarCurrencyIntent = new Intent (this, typeof(CurrencyUpdateService));

    var lvarPendingIntent = PendingIntent.GetBroadcast (this, 0, lvarCurrencyIntent, PendingIntentFlags.CancelCurrent);
    lvarManager.SetRepeating (AlarmType.Rtc, 1000, 5000, lvarPendingIntent);

Receiver:

    public class CurrencyUpdateService : BroadcastReceiver
{       
    public override void OnReceive (Context context, Intent intent)
    {
        Toast.MakeText (context, "Running", ToastLength.Short).Show ();
    }
}

Manifest:

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="SplitTheBill.SplitTheBill" android:versionCode="1" android:versionName="1.0">
<uses-sdk android:minSdkVersion="16" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<application android:label="SplitTheBill" android:icon="@drawable/groups"></application>
<receiver android:process=":remote" android:name=".CurrencyUpdateService"/>
<provider android:name="mono.MonoRuntimeProvider" android:exported="false" android:initOrder="2147483647" android:authorities="StockService.StockService.mono.MonoRuntimeProvider.__mono_init__" />

I want to state that I'm a somewhat new user of Xamarin and as it quite succesfully makes shure that you don't touch Manifest files, I only added the line:

<receiver android:process=":remote" android:name=".CurrencyUpdateService"/>

I tried running the code in a fresh solution and it didn't work. I tried using different types of Alarm types and Services with no luck.

Feel free to suggest your own solutions and laugh at my face for asking obvious questions ;)

Marcin Bator
  • 341
  • 1
  • 8
  • 23

2 Answers2

2

1st) Tag your broadcast receiver class with the BroadcastReceiver attribute so that the appropriate tag gets generated in your AndroidManifest.xml at compile time:

[BroadcastReceiver]
public class CurrencyUpdateService : BroadcastReceiver
{
    public override void OnReceive(Context context, Intent intent)
    {
        Toast.MakeText(context, "Running", ToastLength.Short).Show();
    }
}

Now your receiver will start toasting every 5 seconds.

Note: Xamarin auto-generates Android class name identifiers so if you do not hard-code a name for your class, there is no way to manually edit the manifest to add this item.

AndroidManifest.xml from the above code generates (for me):

<receiver android:name="md57db81284125fca721c48509d8e9cea0b.CurrencyUpdateService" />

Now if you manually add a Name to the Attribute, you can control what is generated. This is needed in cases where other Android applications need to call you and need a pre-defined (static) name to do so.

[BroadcastReceiver(Name = "com.sushihangover.alarmso.Foobar")]
public class CurrencyUpdateService : BroadcastReceiver
{
    public override void OnReceive(Context context, Intent intent)
    {
        Toast.MakeText(context, "Running", ToastLength.Short).Show();
    }
}

Note: Do not use Android-style "dot name", use the fully qualified name that includes your package name, see link for details

AndroidManifest.xml now contains:

<receiver android:name="com.sushihangover.alarmso.Foobar" />

2nd) As far as why you are trying to start a new process, remember that a BroadcastReceiver is not an Android Service... You can remove the :process tag in your manifest as it is not needed for what you're are doing.

If you really are looking to create and start a local or background service, you should checkout:

Community
  • 1
  • 1
SushiHangover
  • 73,120
  • 10
  • 106
  • 165
0

Thank you for the answer.

I finally got it to work by adding an intent filter attribute to the CurrencyUpdateService class, but I realized that what I really needed was a sticky service that was going to run even if the application was closed.

I finished with a service that is running every day at specified time (also 5 seconds after the app is closed due to service being sticky) + BroadcastReceiver for system reboot to reschedule the service + couple of other broadcast receivers to make the app work smarter.

The only thing to remember is to not believe AlarmManager when it comes to testing on short intervals (< 10 mins) as sometimes it fires the alarm way out of time.

Marcin Bator
  • 341
  • 1
  • 8
  • 23