当前位置: 首页 > news >正文

LaPlayer(1)------Service浅析

  Service是一个长期运行在后台,并不提供界面的应用组件。其他组件可以启动一个服务,并且即使用户切换到其他的应用,该服务仍可在后台继续运行。另外,组件可以把某个服务邦定到自己,来与其交互通信,甚至包括执行进程间通信(IPC)。因此在播放器的开发中,为了让播放音乐不依赖于具体的Activity,将播放音乐的控制放于Service中。

  Service和Activity一样,需要在AndroidMainfest.xml中进行配置,配置如下:

1         <service  
2             android:name="com.porco.service.PlayService"   android:exported="false">
3             <intent-filter>
4                 <action android:name="PlayService" />
5             </intent-filter>
6         </service>        

    在此处设置了android:exported这个属性。这是用于指示该服务是否能够被其他应用程序组件调用或跟它交互:如果设置为true,则能够被调用或交互,否则不能。设置为false时,只有同一个应用程序的组件或带有相同用户ID的应用程序才能启动或绑定该服务。
 它的默认值依赖与该服务所包含的过滤器。没有过滤器则意味着该服务只能通过指定明确的类名来调用,这样就是说该服务只能在应用程序的内部使用(因为其他外部使用者不会知道该服务的类名),因此这种情况下,这个属性的默认值是false。另一方面,如果至少包含了一个过滤器,则意味着该服务可以给外部的其他应用提供服务,因此默认值是true,此种情况下在Eclipse中会有警告信息:Exported service does not require permission。

  Service的使用方式有两种:context.s在tartService() 和 context.bindService()。其生命周期分别是:

 

  context.startService() 启动流程:

  context.startService()  -> onCreate()  -> onStartCommand()  -> Service running  -> context.stopService()  -> onDestroy()  -> Service stop 

  如果Service还没有运行,则android先调用onCreate(),然后调用onStartCommand();

  如果Service已经运行,则只调用onStartCommand(),所以一个Service的onStartCommand方法可能会重复调用多次。 

  如果stopService的时候会直接onDestroy,如果是调用者自己直接退出而没有调用stopService的话,Service会一直在后台运行,该Service的调用者再启动起来后可以通过stopService关闭Service。

  所以调用startService的生命周期为:onCreate --> onStart (可多次调用) --> onDestroy

 

  context.bindService()启动流程:

  context.bindService()  -> onCreate()  -> onBind()  -> Service running  -> onUnbind()  -> onDestroy()  -> Service stop

  onBind()将返回给客户端一个IBind接口实例,IBind允许客户端回调服务的方法,比如得到Service的实例、运行状态或其他操作。这个时候把调用者(Context,例如Activity)会和Service绑定在一起,Context退出了,Srevice就会调用onUnbind->onDestroy相应退出。 

  所以调用bindService的生命周期为:onCreate --> onBind(只一次,不可多次绑定) --> onUnbind --> onDestory。

  在Service每一次的开启关闭过程中,只有onStart可被多次调用(通过多次startService调用),其他onCreate,onBind,onUnbind,onDestory在一个生命周期中只能被调用一次。

 

  在具体使用时,可分为以下三种情况:

  1.startService启动服务。

  2.bindService启动服务。

  3.startService & bindService 启动服务。

 

  为了测试不同情况下的service的调用及生命周期,编写测试demo代码如下:

Activity部分·:

public class PlayActivity extends Activity {

    private Intent intent=new Intent("tService");
    private Button mButtonBind;
    private Button mButtonUnbind;
    private Button mButtonplay; 
    private Button mButtonStart;
    private Button mButtonStop;
    TestService tService;
    
    ServiceConnection conn=new ServiceConnection() {
        
        @Override
        public void onServiceDisconnected(ComponentName name) {
            // TODO Auto-generated method stub
            Log.d("activity1","service service disconnected");
        }
        
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            // TODO Auto-generated method stub
            //System.out.println("bind ok");
            Log.d("activity1","service connnected");
            tService=((TestService.MBinder) service ).getService();
        }
    };
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.player);
        //bindService(intent, conn, BIND_AUTO_CREATE);
        
        mButtonBind=(Button)findViewById(R.id.buttonbind);
        mButtonUnbind=(Button)findViewById(R.id.buttonunbind);
        mButtonplay=(Button)findViewById(R.id.buttonserviceplay);
        mButtonStart=(Button)findViewById(R.id.buttonstart);
        mButtonStop=(Button)findViewById(R.id.buttonstop);
        
        mButtonBind.setOnClickListener(new OnClickListener() {
            
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub                
                bindService(intent, conn, BIND_AUTO_CREATE);
                Log.d("activity1","activity after bindservice");
            }
        });


        mButtonUnbind.setOnClickListener(new OnClickListener() {
            
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub                
                unbindService(conn);
                Log.d("activity1","activity after unbindservice");
            }
        });
        
        mButtonplay.setOnClickListener(new OnClickListener() {
            
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                tService.play();
            }
        });
        
        mButtonStart.setOnClickListener(new OnClickListener() {
            
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub                
                startService(intent);
                Log.d("activity1","start service");
            }
        });
        
        mButtonStop.setOnClickListener(new OnClickListener() {
            
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub                
                stopService(intent);
                Log.d("activity1","stop service");
            }
        });
        
    }
}

 

Service部分:

public class TestService extends Service {

    private Thread mThread;
    
    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        Log.d("service","onbind");
        return new MBinder();
    }
    
    class MBinder extends Binder{
        public TestService getService(){
            return TestService.this;
        }
    }

    @Override
    public void onCreate() {
        // TODO Auto-generated method stub
        super.onCreate();
        Log.d("service","service create");                
    }
    
    

    @Override
    public void onDestroy() {
        // TODO Auto-generated method stub
        
        super.onDestroy();
        Log.d("service","service destory");
        
    }



    @Override
    public boolean onUnbind(Intent intent) {
        // TODO Auto-generated method stub
        Log.d("service","service unbind");
        return super.onUnbind(intent);
        
    }



    @Override
    public void onRebind(Intent intent) {
        // TODO Auto-generated method stub        
        super.onRebind(intent);
        Log.d("service","service rebind");
    }



    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // TODO Auto-generated method stub
        Log.d("service","service start");
        return super.onStartCommand(intent, flags, startId);
    }
    
    public void play(){
        Log.d("service","service play");
        
    }
        
}

 

  1.startService启动服务:用于启动一个服务执行后台任务,不进行通信,停止服务使用stopService。点击按钮调用startService()方法,输出结果如下:

  2.bindService启动服务:该方法启动的服务要进行通信,停止服务使用unbindService。点击按钮调用bindService()方法,输出结果如下:

  3.startService & bindService 启动服务:Service将会一直在后台运行,同时调用stopService和unbindService才能停止服务。输出结果(一种)如下:

 

综合以上,可以得出:

  1.在Service未启动时,无论是调用startService 还是 bindService 方法,都会先调用service的onCreate()方法创建一个service服务。

  2.在Service创建后销毁前,如果调用startService方法,每调用一次都会触发一次service的onStartCommand()方法;如果调用bindService方法,如果已绑定,则不会再触发service的onBind方法。

  3.如果要销毁service,则需要调用对应的方法:startService--stopService ,bindService--unbindService,startService & bindService--stopService &unbindService,才会触发service的onDestory方法。

 

  

  此外,有一点需要注意的是,在执行bindService方法后,下一个语句的执行先于service的创建,因此,需要注意对于binder返回的对象的使用,防止出错。具体service和activity在同一进程中的运行关系及情况需要后续学习。

 

参考文档:

Android Service 服务(一)—— Service

Android 中的 Service 全面总结

 

转载于:https://www.cnblogs.com/porco-zheng/p/4316243.html

相关文章:

  • bouml简介与使用总结
  • Oracle的隐式转换
  • 在同一个页面父窗口打开子窗口,动态无刷新提交,超炫基于jquery ajax提交,兼容IE7+,火狐.....
  • PHP统计目录下的文件总数及代码行数(去除注释及空行)
  • nyoj 523 双向广搜
  • JS调用后台方法大全
  • 即时通信3
  • frame-relay实验
  • eclipse启动不了报错java was started but returned exit code=13
  • GDAL编译Windows平台下64位的方式
  • java调用webservice
  • 使用JSR234实现对图片的缩放
  • 《大型分布式网站架构设计与实践》
  • 迷路
  • SQL Server 高可用使用环境
  • [LeetCode] Wiggle Sort
  • flask接收请求并推入栈
  • HTML5新特性总结
  • Javascript设计模式学习之Observer(观察者)模式
  • Java应用性能调优
  • JS函数式编程 数组部分风格 ES6版
  • Linux链接文件
  • springboot_database项目介绍
  • 成为一名优秀的Developer的书单
  • 分布式任务队列Celery
  • - 概述 - 《设计模式(极简c++版)》
  • 利用jquery编写加法运算验证码
  • 前端临床手札——文件上传
  • 数据科学 第 3 章 11 字符串处理
  • 算法---两个栈实现一个队列
  • 我感觉这是史上最牛的防sql注入方法类
  • Java性能优化之JVM GC(垃圾回收机制)
  • ​​​​​​​sokit v1.3抓手机应用socket数据包: Socket是传输控制层协议,WebSocket是应用层协议。
  • ​520就是要宠粉,你的心头书我买单
  • #调用传感器数据_Flink使用函数之监控传感器温度上升提醒
  • #预处理和函数的对比以及条件编译
  • (1)SpringCloud 整合Python
  • (14)Hive调优——合并小文件
  • (3)选择元素——(17)练习(Exercises)
  • (C语言)球球大作战
  • (M)unity2D敌人的创建、人物属性设置,遇敌掉血
  • (MIT博士)林达华老师-概率模型与计算机视觉”
  • (办公)springboot配置aop处理请求.
  • (附源码)springboot工单管理系统 毕业设计 964158
  • (附源码)SSM环卫人员管理平台 计算机毕设36412
  • (离散数学)逻辑连接词
  • (强烈推荐)移动端音视频从零到上手(上)
  • (转)nsfocus-绿盟科技笔试题目
  • (转)ObjectiveC 深浅拷贝学习
  • (转)菜鸟学数据库(三)——存储过程
  • .aanva
  • .equals()到底是什么意思?
  • .net CHARTING图表控件下载地址
  • .NET CORE 第一节 创建基本的 asp.net core
  • .Net MVC4 上传大文件,并保存表单