您的位置:首页 > 移动开发 > Android开发

Xamarin.Android其他类型的服务

2014-07-12 14:31 183 查看

一、前言

前面我们已经学了关于服务的很多知识,但是对于真实的开发那些远远不够,通过这节我们将学习其他类型的服务,比如前台服务、IntentService和消息服务。下面我们开始进入正题。

二、前台服务

顾名思义,就是拥有前台的优先等级。当然服务还是不可见的。因为前面我们介绍过Android系统会在低内存的情况下将一些长时间不用的应用关闭,如果还是不够,那么就会通过关闭服务服务来达到目的,然而对于某些应用而言,这样将会影响用户的正常使用。比如听音乐,我们基本上都会打开应用选择歌曲后将应用置为后台。但是你会发现通知栏中会存在这个通知并且无法移除,只有正确的退出这个应用了才会消失,而这节我们就要实现这个功能。

首先我们必须要用一个通知,通过这个通知我们的服务才能够变成前台服务,这里我们新建一个名为ForegroundService的服务,然后重写OnStartCommand方法。

public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
var notify = new Notification(Resource.Drawable.Icon, "前台服务");
var activityIntent = new Intent(this, typeof(MainActivity));
var activityPintent = PendingIntent.GetActivity(this, 0, activityIntent, PendingIntentFlags.UpdateCurrent);
notify.SetLatestEventInfo(this, "标题", "内容", activityPintent);
StartForeground((int)NotificationFlags.ForegroundService, notify);
return StartCommandResult.Sticky;
}


很多代码都是我们在讨论通知的时候都已经掌握的了,既然是前台服务,自然最后发送这个方法是不同的,我们需要使用服务的StartForeground来发送这个通知,同时第一个参数也要设置为前台服务,这样我们就可以看到如图的结果了(需要在MainActivity的OnCreate方法中开启该服务)。

public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
if (notify == null)
{
notify = CreateNotify("初始化");
StartForeground((int)NotificationFlags.ForegroundService, notify);
}
bool isBtn1Click = intent.GetBooleanExtra("showBtn1", false);
bool isBtn2Click = intent.GetBooleanExtra("showBtn2", false);
if (isBtn1Click)
{
if (notify != null)
{
notify = CreateNotify("来自按钮1");
StartForeground((int)NotificationFlags.ForegroundService, notify);
}
}
else if (isBtn2Click)
{
if (notify != null)
{
notify = CreateNotify("来自按钮2");
StartForeground((int)NotificationFlags.ForegroundService, notify);
}
}
return StartCommandResult.Sticky;
}


View Code
可以看到我们通过GetBooleanExtra获取了通过意图传递的参数,当然笔者这里的用法不同于前面的方式,我还传入了第二个参数,这样做的目的就是在意图中不存在该值的时候将会把第二参数返回,下面就是进行不同的判断从而更新通知。

最终运行结果如下所示:



按下“显示1”后



按下“显示2”后



至此我们就完成了前台服务的学习。

三、IntentService

很多时候我们都需要利用服务进行耗时的操作,势必需要创建新的线程去处理。但是普通的Service并不会主动创建而需要开发者自行在OnStartCommand中去创建,为此就繁衍出了IntentService类,它会为我们创建好线程去执行我们的代码,从而避免一些代码。但是我们不能重写OnStartCommand方法而应该是OnHandleIntent方法。比如下面的代码。

[Service]
public class MainIntentService : IntentService
{
protected override void OnHandleIntent(Android.Content.Intent intent)
{
Thread.Sleep(1000);
Toast.MakeText(this, "来自新线程" , ToastLength.Long).Show();
}
}


通过下面的截图我们可以看到OnHandleIntent中执行的代码是新建的一个线程



关于IntentService的使用非常简单。

四、通信服务

上一节关于绑定服务的学习中,活动必须确切的知道服务的类型才能使用,这样就加大了他们之间的耦合度,而通过本节我们将会学习如何通过消息机制将他们解耦,首先我们需要理解Handler类,它将会负责处理发送过来的消息,我们需要继承该类,并重写HandleMessage方法,我们新建一个MainHandler类并继承该类,然后重写。

public class MainHandler : Handler
{
public override void HandleMessage(Message msg)
{
Toast.MakeText(Application.Context, "接收到的消息的what为" + msg.What.ToString() + " 内容为" + msg.Data.GetString("_str"), ToastLength.Short).Show();
}
}


这里我们仅仅只是简单的输出了消息的类型以及消息传递的参数,下面我们还需要一个服务将这个消息传递给活动。

[Service]
public class MessengerService : Service
{
Messenger messenger;

public MessengerService()
{
messenger = new Messenger(new MainHandler());
}

public override Android.OS.IBinder OnBind(Android.Content.Intent intent)
{
return messenger.Binder;
}
}


这里我们还需要Messenger去封装MainHandler,因为MainHandler是无法在OnBind中直接返回的,只有Messenger的Binder属性可以,自然活动那边就需要接收这个接口,下面是IserviceConnection的实现。

public class MessengerServiceConnection : Java.Lang.Object , IServiceConnection
{
MainActivity mainActivity;

public MessengerServiceConnection(MainActivity ma)
{
mainActivity = ma;
}

public void OnServiceConnected(ComponentName name, Android.OS.IBinder service)
{
mainActivity.messenger = new Messenger(service);
}

public void OnServiceDisconnected(ComponentName name)
{
mainActivity.messenger.Dispose();
mainActivity.messenger = null;
}
}


这里的方式依然是使用之前我们讲述绑定服务时候的方法,只是在我们接收接口的时候是用Messenger的去封装的,这样就统一了。我们的活动只要有Messenger,并且对应的服务都满足这个接口那么我们的活动就可以灵活的绑定任意服务,使用他们的功能了,最后是MainActivity的代码(需要在Main.axml中拖拽两个按钮,以便发送消息给服务)。

[Activity(Label = "OtherService", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity
{
public Messenger messenger;

protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
BindService(new Intent(this, typeof(MessengerService)), new MessengerServiceConnection(this), Bind.AutoCreate);
Button btn1 = FindViewById<Button>(Resource.Id.button1);
btn1.Click += (e, s) =>
{
Message msg = Message.Obtain();
Bundle b = new Bundle();
b.PutString("_str", "消息1");
msg.Data = b;
msg.What = 1;
messenger.Send(msg);
};

Button btn2 = FindViewById<Button>(Resource.Id.button2);
btn2.Click += (e, s) =>
{
Message msg = Message.Obtain();
Bundle b = new Bundle();
b.PutString("_str", "消息2");
msg.Data = b;
msg.What = 2;
messenger.Send(msg);
};
}
}


唯一要说的就是发送消息,我们需要实例化Messager(不是Messenger),设置它的what,如果我们还需要传递更多的参数我们可以实例化一个Bundle,然后通过其PutXXX方法赋值,最后赋给MessageData类型,最后要通过Messenger实例的Send方法发送这个消息,那么MainHandler就可以处理这个消息了。

下面是实际的运行图。

点击“发送消息1”按钮后



点击“发送消息2”按钮后

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: