zoukankan      html  css  js  c++  java
  • 【Android】17.3 Activity与StartedService的绑定

    分类:C#、Android、VS2015;

    创建日期:2016-03-03

    一、简介

    除了上一节介绍的基本绑定以外,你还可以创建一个同时支持started和bound的服务。也就是说,服务可以通过调用 StartService() 来启动,这会使它一直保持运行,同时它也允许客户端通过调用BindService() 来与之绑定。

    虽然你通常应该要实现 OnBind() 或 OnStartCommand() 中的一个,但有时需要同时实现两者。比如,音乐播放器的服务也许就需要同时实现后台运行和支持绑定。这样,activity就可以启动服务来播放音乐,并且音乐会一直播放下去,即使用户离开该应用程序也没关系,这个activity可以绑定播放服务来重新获得播放控制权。

    另外,如果你的服务是started和bound的,那么服务启动后,系统将不会在所有客户端解除绑定时销毁它。取而代之的是,你必须通过调用StopSelf() 或 StopService() 显式终止此服务。

    服务只在为绑定的应用程序组件工作时才会存活,因此,只要没有组件绑定到服务,系统就会自动销毁服务(你不需要像started服务中那样通过OnStartCommand()来终止一个bound服务)。

    一旦OnBind方法返回绑定的实例,Android就会引发实现IServiceConnection接口的对象的ServiceConnected事件,然后,客户端就可以通过Binder引用它。

    多个客户端可以同时连接到同一个服务上。不过,只有在第一个客户端绑定时,系统才会调用服务的 OnBind() 方法来获取 IBinder 。然后,系统会向后续请求绑定的客户端传送这同一个 IBinder ,而不再调用 OnBind() 。当最后一个客户端解除绑定后,系统会自动销毁服务(除非服务是同时通过 StartService() 启动的)。

    二、示例2运行截图

    该例子演示如何绑定到一个started服务。

    单击【启动服务】按钮后,就会在左上角出现一个通知图标,下拉展开该图标,就可以看到来自服务的通知信息。

    image  image

    单击【调用服务中提供的方法】按钮,会显示调用服务中对应方法返回的结果,单击【停止服务】按钮,左上角的通知图标也会同时消失。

    三、主要设计步骤

    1、添加ch1702_main.xml

    <?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/ch1702_startService"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="启动服务" />
        <Button
            android:id="@+id/ch1702_callService"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="调用服务中提供的方法" />
        <Button
            android:id="@+id/ch1702_stopService"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="停止服务" />
    </LinearLayout>

    2、添加ch1702Service.cs

    using Android.App;
    using Android.Content;
    using Android.OS;
    using Android.Widget;
    using System.Threading;
    
    namespace MyDemos.SrcDemos
    {
        [Service]
        [IntentFilter(new string[] { action })]
        public class ch1702Service : Service
        {
            public const string action = "ServiceDemo.ch1702Service";
            ch1702ServiceBinder binder;
    
            public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
            {
                Notification notification = GetNotification();
                //启动前台任务
                StartForeground((int)NotificationFlags.ForegroundService, notification);
    
                var t = new Thread(() =>
                {
                    //发送通知
                    var m = (NotificationManager)GetSystemService(NotificationService);
                    m.Notify((int)NotificationFlags.ForegroundService, notification);
    
                    Thread.Sleep(50000);  //延时50秒模拟长时间运行的服务
    
                    //停止前台任务
                    StopForeground(true);
                    //停止后台服务
                    StopSelf();
                });
                t.Start();
                return StartCommandResult.NotSticky;
            }
    
            private Notification GetNotification()
            {
                var pendingIntent = PendingIntent.GetActivity(this,
                    (int)NotificationFlags.ForegroundService,
                    new Intent(this, typeof(MainActivity)),
                    PendingIntentFlags.UpdateCurrent);
                Notification.Builder builder = new Notification.Builder(this)
                    .SetContentTitle("来自ch1702Service的通知")
                    .SetContentText("正在前台运行ch1702Service")
                    .SetContentIntent(pendingIntent)
                    .SetSmallIcon(Resource.Drawable.Icon);
                Notification notification = builder.Build();
                return notification;
            }
    
            public override IBinder OnBind(Android.Content.Intent intent)
            {
                binder = new ch1702ServiceBinder(this);
                return binder;
            }
    
            public string GetText()
            {
                return "这是来自ch1702Service的信息";
            }
    
            public override void OnDestroy()
            {
                var myHandler = new Handler();
                myHandler.Post(() =>
                {
                    Toast.MakeText(this, "正在停止ch1702Service", ToastLength.Long).Show();
                });
                base.OnDestroy();
            }
        }
    
        public class ch1702ServiceBinder : Binder
        {
            ch1702Service service;
    
            public ch1702ServiceBinder(ch1702Service service)
            {
                this.service = service;
            }
    
            public ch1702Service GetMyService()
            {
                return service;
            }
        }
    }

    3、添加ch1702MainActivity.cs

    using Android.App;
    using Android.Content;
    using Android.OS;
    using Android.Widget;
    using Android.Content.Res;
    
    namespace MyDemos.SrcDemos
    {
        [Activity(Label = "ch1702MainActivity")]
        public class ch1702MainActivity : Activity
        {
            bool isBound = false;
            bool isConfigurationChange = false;
            ch1702ServiceBinder binder;
            ch1702ServiceConnection myServiceConnection;
            Intent serviceIntent;
    
            protected override void OnCreate(Bundle savedInstanceState)
            {
                base.OnCreate(savedInstanceState);
                SetContentView(Resource.Layout.ch1702_main);
    
                var start = FindViewById<Button>(Resource.Id.ch1702_startService);
                start.Click += delegate
                {
                    serviceIntent = new Intent(ch1702Service.action);
                    StartService(serviceIntent);
                };
    
                var callService = FindViewById<Button>(Resource.Id.ch1702_callService);
                callService.Click += delegate
                {
                    if (isBound)
                    {
                        RunOnUiThread(() =>
                        {
                            string text = binder.GetMyService().GetText();
                            Toast.MakeText(this, text, ToastLength.Short).Show();
                        });
                    }
                };
    
                var stop = FindViewById<Button>(Resource.Id.ch1702_stopService);
                stop.Click += delegate
                {
                    StopService(serviceIntent);
                    if (isBound)
                    {
                        UnbindService(myServiceConnection);
                        isBound = false;
                    }
                };
    
                // 如果配置改变了(比如旋转了屏幕),则恢复连接
                if (myServiceConnection != null)
                {
                    binder = myServiceConnection.Binder;
                }
            }
    
            protected override void OnStart()
            {
                base.OnStart();
                var myServiceIntent = new Intent(ch1702Service.action);
                myServiceConnection = new ch1702ServiceConnection(this);
                BindService(myServiceIntent, myServiceConnection, Bind.AutoCreate);
            }
    
            public override void OnConfigurationChanged(Configuration newConfig)
            {
                isConfigurationChange = true;
                base.OnConfigurationChanged(newConfig);
            }
    
            protected override void OnDestroy()
            {
                base.OnDestroy();
    
                if (!isConfigurationChange)
                {
                    if (isBound)
                    {
                        UnbindService(myServiceConnection);
                        isBound = false;
                    }
                }
            }
    
            private class ch1702ServiceConnection : Java.Lang.Object, IServiceConnection
            {
                private ch1702MainActivity activity;
                public ch1702ServiceBinder Binder { get; private set; }
    
                public ch1702ServiceConnection(ch1702MainActivity activity)
                {
                    this.activity = activity;
                }
    
                public void OnServiceConnected(ComponentName name, IBinder service)
                {
                    var myServiceBinder = service as ch1702ServiceBinder;
                    if (myServiceBinder != null)
                    {
                        activity.binder = myServiceBinder;
                        activity.isBound = true;
    
                        // 即使配置发生了改变,仍保持绑定到该实例
                        Binder = myServiceBinder;
                    }
                }
    
                public void OnServiceDisconnected(ComponentName name)
                {
                    activity.isBound = false;
                }
            }
        }
    }
  • 相关阅读:
    二叉树前序中序遍历求后序遍历
    二叉树的遍历
    Codeforces Round #381 (Div. 2)
    Codeforces Round #380 (Div. 2, Rated, Based on Technocup 2017
    Codeforces Round #379 (Div. 2)
    HDU 2896 ac自动机裸题
    RabbitMQ镜像模式双节点部署时故障转移过程中队列中消息的状态
    Maven搭建Spring MVC时使用jstl无效
    在使用HttpClient做客户端调用一个API时 模拟并发调用时发生“死锁"?
    使用mongodb提供的dotnet core sdk进行地理位置运算
  • 原文地址:https://www.cnblogs.com/rainmj/p/5237284.html
Copyright © 2011-2022 走看看