A question recently went through the Mono for Android mailing lists regarding how to automatically start an application on Android using Mono for Android. Basically, how do you load on boot with Mono for Android. I had this issue a few months ago. Thankfully, Jon Pryor helped me with it, so I thought I would post it with a little more info. Basically, its a 3 step process.
- The first step is to ask for the boot permission in the AndroidManifest.xml file. I used the following manifest file. I am doing some location based stuff in it, so I'll just bold the important part.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="internalOnly" android:versionCode="1">
<application>
</application>
<uses-sdk android:minSdkVersion="4" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
</manifest>
- The next step is to create a BroadcastReceiver. The code I have used is below. The key part for me is to check for the Android.Content.Intent.ActionBootCompleted Intent via the IntentFilter.
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 Android.Util;
using Android.Locations;
namespace BootCompleted
{
[BroadcastReceiver]
[IntentFilter(new[] { Android.Content.Intent.ActionBootCompleted },
Categories = new[] { Android.Content.Intent.CategoryDefault }
)]
public class ReceiveBoot : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
Toast.MakeText(context, "Received intent!", ToastLength.Short).Show();
if ((intent.Action != null) &&
(intent.Action ==
Android.Content.Intent.ActionBootCompleted))
{ // Start the service or activity
context.ApplicationContext.StartService(new Intent(context, typeof(LocationService)));
}
}
}
} - Finally, I have a Service. An Android Service is not part of this specifically, but I need to start something, so a Service makes sense. When the device moves, a notification is sent to the UI.
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 Android.Util;
using Android.Locations;
namespace BootCompleted
{
[Service]
public class LocationService : Service,
Android.Locations.ILocationListener
{
private NotificationManager nm;
private IBinder binder;
string bestProvider;
public LocationService()
{
binder = new LocalBinder(this);
}
public class LocalBinder : Binder
{
LocationService self;
public LocalBinder(LocationService self)
{
this.self = self;
}
public LocationService Service
{
get { return self; }
}
}
private LocationManager lm;
public override void OnCreate()
{
nm = (NotificationManager)GetSystemService(NotificationService);
ShowNotification();
Criteria cr = new Criteria();
cr.Accuracy = Accuracy.Coarse;
cr.PowerRequirement = Power.Low;
cr.AltitudeRequired = false;
cr.BearingRequired = false;
cr.SpeedRequired = false;
cr.CostAllowed = true;
String serviceString = Context.LocationService;
lm = (LocationManager)GetSystemService(serviceString);
bestProvider = lm.GetBestProvider(cr, false);
Location l = lm.GetLastKnownLocation(bestProvider);
lm.RequestLocationUpdates(bestProvider, 5000, 100f, this);
}
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
Log.Info("LocationService", "Received start id " + startId + ": " + intent);
return StartCommandResult.Sticky;
}
public override void OnDestroy()
{
nm.Cancel(Resource.String.local_service_started);
Toast.MakeText(this, Resource.String.local_service_stopped, ToastLength.Short).Show();
lm.RemoveUpdates(this);
StopSelf();
}
public override IBinder OnBind(Intent intent)
{
return binder;
}
void ShowNotification()
{
var text = GetText(Resource.String.local_service_started);
var notification = new Notification(Resource.Drawable.stat_sample, text, System.Environment.TickCount);
PendingIntent contentIntent = PendingIntent.GetActivity(this, 0,
new Intent(this, typeof(Activity1)), 0);
notification.SetLatestEventInfo(this,
GetText(Resource.String.local_service_label), text, contentIntent);
nm.Notify(Resource.String.local_service_started, notification);
}
public void OnLocationChanged(Android.Locations.Location location)
{
var text = "Lat: " + location.Latitude.ToString() +
" Lon: " + location.Longitude.ToString();
var notification = new Notification(Resource.Drawable.stat_sample, text, System.Environment.TickCount);
PendingIntent contentIntent = PendingIntent.GetActivity(this, 0,
new Intent(this, typeof(Activity1)), 0);
notification.SetLatestEventInfo(this, GetText(Resource.String.local_service_label), text, contentIntent);
nm.Notify(Resource.String.local_service_started, notification);
Toast.MakeText(this, text, ToastLength.Short).Show();
}
public void OnProviderDisabled(string provider)
{
//throw new NotImplementedException();
}
public void OnProviderEnabled(string provider)
{
//throw new NotImplementedException();
}
public void OnStatusChanged(string provider, int status, Bundle extras)
{
//throw new NotImplementedException();
}
}
}
|