zoukankan      html  css  js  c++  java
  • Android中Services简析

          Services是Android中四大基础组件(Activities、 Services、 Content Providers、 BroadCast Receivers)之一,主要用于在后台长时间运行操作,不提供界面,如音乐播放器,关闭界面后还能继续播放。当页面需要交互时用线程。

          创建Services,继承Service,复写里面的方法,用日志显示运行过程:

    package com.example.androidservice;
    
    import android.app.Service;
    import android.content.Intent;
    import android.os.IBinder;
    import android.util.Log;
    
    public class MyService extends Service {
    
        private static final String TAG="TestTag";
        
        @Override
        public IBinder onBind(Intent arg0) {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public void onCreate() {
            Log.i(TAG, "onCreate");
            super.onCreate();
        }
    
        @Override
        public void onStart(Intent intent, int startId) {
            Log.i(TAG, "onStart");
            super.onStart(intent, startId);
        }
    
        @Override
        public void onDestroy() {
            Log.i(TAG, "onDestroy");
            super.onDestroy();
        }
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            Log.i(TAG, "onStartCommand");
            return super.onStartCommand(intent, flags, startId);
        }
    
    }

    服务生命周期context.startService() ->onCreate()- >onStart()- >onStartCommand()->Service running ->context.stopService()  ->onDestroy() ->Service stop

    如果Service还没有运行,则android先调用onCreate()然后调用onStartCommand(),每次调用startService(Intent)的时候,都会调用执行onStartCommand();
    如果Service已经运行,则只调用onStartCommand()。 

    我们要执行操作可在onStartCommand方法中定义,onStartCommand有4种返回值: 

            START_STICKY:如果service进程被kill掉,保留service的状态为开始状态,但不保留递送的intent对象。随后系统会尝试重新创建service,由于服务状态为开始状态,所以创建服务后一定会调用onStartCommand(Intent,int,int)方法。如果在此期间没有任何启动命令被传递到service,那么参数Intent将为null。

            START_NOT_STICKY:“非粘性的”。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统不会自动重启该服务。

             START_REDELIVER_INTENT:重传Intent。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统会自动重启该服务,并将Intent的值传入。

             START_STICKY_COMPATIBILITY:START_STICKY的兼容版本,但不保证服务被kill后一定能重启。

    创建页面用来启动Services,布局:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".AndroidServiceActivity" >
    
        <Button
            android:id="@+id/btnStart"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="开始" >
        </Button>
    
        <Button
            android:id="@+id/btnStop"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="结束" >
        </Button>
    
    </LinearLayout>

    开始结束绑定事件,startService来启动服务(调用者与服务之间没有联系,调用都关闭不影响服务运行),stopService来停止服务,注意其参数为Intent对象,所以可以可以通过些Intent传递一些参数给Service,Service可以通过Intent来接收:

    package com.example.androidservice;
    
    import android.os.Bundle;
    import android.app.Activity;
    import android.content.Intent;
    import android.view.Menu;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    
    public class AndroidServiceActivity extends Activity {
    
        private Button btnStart;
        private Button btnStop;
        
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_android_service);
            btnStart=(Button)this.findViewById(R.id.btnStart);
            btnStop=(Button)this.findViewById(R.id.btnStop);
            btnStart.setOnClickListener(listener);
            btnStop.setOnClickListener(listener);
        }
        
        private OnClickListener listener=new OnClickListener() {
            
            @Override
            public void onClick(View v) {
                Intent intent=new Intent(AndroidServiceActivity.this,MyService.class);
                switch(v.getId()){
                case R.id.btnStart:
                    startService(intent);
                    break;
                case R.id.btnStop:
                    stopService(intent);
                    break;
                }
                
            }
        };
    
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.activity_android_service, menu);
            return true;
        }
    
    }

    最后在manifest.xml中添加节点<service android:name=".MyService" />与AndroidServiceActivity的Activity节点同级。

    还有一种是用bindService()来启动,通过服务链接(ServiceConnection)或直接获取Service中状态和数据信息 
    服务链接能够获取Service的对象,因此绑定Service的组件可以调用Service中的实现的函数 
    使用Service的组件通过Context.bindService()建立服务链接,通过Context.unbindService()停止服务链接 
    如果在绑定过程中Service没有启动,Context.bindService()会自动启动Service 
    同一个Service可以绑定多个服务链接,这样可以同时为多个不同的组件提供服务

     创建BindService继承Service,扩展Binder类声明方法getBindService返回BindService,以便调用自定义方法ShowLog()

    package com.example.androidservice;
    
    import android.app.Service;
    import android.content.Intent;
    import android.os.Binder;
    import android.os.IBinder;
    import android.util.Log;
    
    public class BindService extends Service {
    
        private static final String TAG="BindService";
        
        private BindServiceX myBinderServiceX=new BindServiceX();
        public class BindServiceX extends Binder{
            public BindService getBindService() {
                return BindService.this;
            }
        }
    
        @Override
        public IBinder onBind(Intent arg0) {
            // TODO Auto-generated method stub
            return myBinderServiceX;
        }
        
        @Override
        public void onCreate() {
            Log.i(TAG, "onCreate");
            super.onCreate();
        }
    
        @Override
        public void onStart(Intent intent, int startId) {
            Log.i(TAG, "onStart");
            super.onStart(intent, startId);
        }
    
        @Override
        public void onDestroy() {
            Log.i(TAG, "onDestroy");
            super.onDestroy();
        }
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            Log.i(TAG, "onStartCommand");
            return super.onStartCommand(intent, flags, startId);
        }
        
        public void ShowLog(){
            Log.i(TAG, "BindService=>ShowLog");
        }
    
    }

    Manifest.xml文件中声明<service android:name=".BindService" />

    界面添加启动停止按钮:

    <Button
            android:id="@+id/btnStartBindService"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="开始BindService" >
        </Button>
    
        <Button
            android:id="@+id/btnStopBindService"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="结束BindService" >
        </Button>

    AndroidServiceActivity绑定方法,Context.BIND_AUTO_CREATE表明只要绑定存在,就自动建立Service;同时也告知Android系统,这个Service的重要程度与调用者相同,除非考虑终止调用者,否则不要关闭这个Service。

    如果service没被创建,那么调用一次onCreate(),然后调用onBind(),多次绑定时,不会多次调用onBind()。

    通过unbindService()函数取消绑定Servcie时,onUnbind()函数将被调用, 
    如果onUnbind()函数的返回true,则表示在调用者绑定新服务时, 
    onRebind()函数将被调用

    取消绑定仅需要使用unbindService()方法,并将ServiceConnnection传递给unbindService()方法需注意的是,unbindService()方法成功后,系统并不会调用onServiceDisconnected(),因为onServiceDisconnected()仅在意外断开绑定时才被调用

    当bindService后,不能stopService,需要通过unBindService()来解除绑定

    startService()后,不可以通过unBindService()来销毁service

    private boolean isConn = false;//用来标志服务是否绑定
    private
    OnClickListener listener = new OnClickListener() { @Override public void onClick(View v) { Intent intentBind = new Intent(AndroidServiceActivity.this, BindService.class); switch (v.getId()) { case R.id.btnStartBindService: bindService(intentBind, conn, Context.BIND_AUTO_CREATE); break; case R.id.btnStopBindService: if (isConn) { unbindService(conn); //不可以多次调用 isConn=false; } break; } } };

    声明conn,用来连接服务,调用服务的方法。

    private ServiceConnection conn = new ServiceConnection() {
    
            @Override
            public void onServiceDisconnected(ComponentName name) {
                isConn=false;
            }
    
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                BindServiceX bindServiceX = (BindServiceX) service;
                BindService bindService = bindServiceX.getBindService();
                bindService.ShowLog();
                isConn=true;
            }
        };

    bindService()目的是回调onBind()方法,它的作用是在Service和调用者之间建立一个桥梁,并不负责更多的工作(例如一个Service需要连接服务器的操作),一般使用bindService来绑定到一个现有的Service(即通过StartService启动的服务),Activity 与 Service传递数据和调用接口。

    以上两种使用方法并不是完全独立的,在某些情况下可以混合使用以MP3播放器为例,在后台的工作的Service通过Context.startService()启动某个特定音乐播放,但在播放过程中如果用户需要暂停音乐播放,则需要通过Context.bindService()获取服务链接和Service对象,进而通过调用Service的对象中的函数,暂停音乐播放过程,并保存相关信息。在这种情况下,如果调用Context.stopService()并不能够停止Service,需要在所有的服务链接关闭后,Service才能够真正的停止

  • 相关阅读:
    HTML-body标签介绍-2
    HTML-body标签介绍-1
    HTML-简介及header
    中文字体编辑工具 Fontmin
    移动端点击复制文本 clipboard.js
    alert弹窗样式修改
    关闭微信页面与微信分享等配置
    Emmet 使用
    js cookie
    select 清除默认样式
  • 原文地址:https://www.cnblogs.com/zhangs1986/p/3601786.html
Copyright © 2011-2022 走看看