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;
                }
            }
        }
    }
  • 相关阅读:
    笔记35 跨重定向请求传递数
    判断邮箱的正则表达式
    按钮
    async await 的用法
    笔记34 Spring MVC的高级技术——处理multipart形式的数据
    Convert Sorted Array to Binary Search Tree
    Binary Tree Zigzag Level Order Traversal
    Unique Binary Search Trees,Unique Binary Search Trees II
    Validate Binary Search Tree
    Populating Next Right Pointers in Each Node,Populating Next Right Pointers in Each Node II
  • 原文地址:https://www.cnblogs.com/rainmj/p/5237284.html
Copyright © 2011-2022 走看看