分类:C#、Android、VS2015;
创建日期:2016-03-01
这一节演示带Intent过滤器的Services的基本用法。
1、配置Intent Filter
不论是本地解决方案还是远程解决方案,都可以通过intent过滤器显式指定要调用的是哪个已启动的服务。换言之,Intent过滤器主要解决的问题是:在Activity中调用StartService方法启动自定义的Service类以后,通过Intent过滤器指定调用的是已启动的服务中的哪些服务(过滤掉其他的服务)。当然,其他应用程序也可以用这种方式来实现。
在C#代码中,可以用[IntentFilte(…)]特性声明来自动注册Intent过滤器,其作用就像可以用[Service]特性声明自动注册服务一样,也是让系统自动修改AndroidManifest.xml配置文件,而不需要我们去手工在AndroidManifest.xml文件中注册配置信息。
例如,下面的代码将Intent过滤器与 mj.demos.DemoService 关联在一起:
namespace ServiceDemo1 { [Service] [IntentFilter(new String[]{"mj.demos.ServiceDemo1"})] public class MyService : Service { …… } }
通过C#代码声明Service特性和IntentFilter特性以后,系统就会自动在AndroidManifest.xml文件中添加下面的配置:
<service android:name="servicedemo1.MyService"> <intent-filter> <action android:name="mj.demos.MyService" /> </intent-filter> </service>
其中,“servicedemo1.MyService”中的servicedemo1是将命名空间ServiceDemo1全部变为小写字母后的结果,MyService是自定义的服务名。
这样一来,就可以在任何类中调用StartService方法,并在参数中传递Intent过滤器。例如,下面的代码演示了如何在某个Activity中传递Intent过滤器:
StartService (new Intent ("mj.demos.MyService"));
下面的代码演示了如何停止过滤服务:
StopService (new Intent ("mj.demos.MyService"));
2、通知用户
利用前面章节介绍的通知用户的办法,可将后台运行的Service的状态或结果告诉用户,比如传输一个大文件时,告诉用户后台传输已完成等。
该例子与上一节介绍的StartedServiceDemo1的运行结果相同。不同的是在这个例子中添加了Intent过滤器。
运行截图
主要设计步骤
(1)添加ch1602_Main.axml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <Button android:id="@+id/ch1602StartService" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="启动服务" /> <Button android:id="@+id/ch1602StopService" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="停止服务" /> </LinearLayout>
(2)添加ch1602ServiceDemo.cs
using System; using Android.App; using Android.Content; using Android.OS; using Android.Runtime; using Android.Widget; using System.Threading; namespace MyDemos.SrcDemos { [Service] [IntentFilter(new string[] { action })] public class ch1602ServiceDemo : Service { public const string action = "MyDemos.ch1602Service"; Thread thread; [return: GeneratedEnum] public override StartCommandResult OnStartCommand(Intent intent, [GeneratedEnum] StartCommandFlags flags, int startId) { var myHandler = new Handler(MainLooper); myHandler.Post(() => { Toast.MakeText(this, "服务已启动", ToastLength.Short).Show(); }); thread = new Thread(() => { for (int i = 1; i <= 10; i++) { var msg = string.Format("这是来自服务的第{0}个消息", i); Thread.Sleep(TimeSpan.FromSeconds(4)); myHandler.Post(() => { Toast.MakeText(this, msg, ToastLength.Short).Show(); }); } StopSelf(); }); thread.Start(); return StartCommandResult.Sticky; } public override void OnDestroy() { base.OnDestroy(); thread.Abort(); new Handler(MainLooper).Post(() => { Toast.MakeText(this, "服务已停止", ToastLength.Short).Show(); }); } //基类要求实现的接口 public override IBinder OnBind(Intent intent) { return null; } } }
(3)添加ch1602MainActivity.cs
using Android.App; using Android.Content; using Android.OS; using Android.Widget; namespace MyDemos.SrcDemos { [Activity(Label = "ch1602MainActivity")] public class ch1602MainActivity : Activity { protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); SetContentView(Resource.Layout.ch1602_Main); var start = FindViewById<Button>(Resource.Id.ch1602StartService); start.Click += delegate { StartService(new Intent(ch1602ServiceDemo.action)); }; var stop = FindViewById<Button>(Resource.Id.ch1602StopService); stop.Click += delegate { StopService(new Intent(ch1602ServiceDemo.action)); }; } } }