Android中Services简析

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

      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才能够真正的停止

目录
相关文章
|
Go Android开发
Key Management Services Android Demo using Alibaba Cloud KMS Service
In this tutorial, we will explore how to use the Key Management Service to create, control, and manage your encryption keys on your mobile device.
2127 0
|
消息中间件 网络协议 Android开发
Reliable and Fast Messaging and Notification Services Using Alibaba Cloud Message Service for Android
This is a sample project created to demonstrate the usage of Alibaba Cloud Message Service on Android.
2754 0
|
Android开发
android应用开发—获取当前运行的services列表
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/voidreturn/article/details/78110190 p...
1295 0
|
Android开发
Android中Services之异步IntentService
IntentService:异步处理服务,新开一个线程:handlerThread在线程中发消息,然后接受处理完成后,会清理线程,并且关掉服务。 IntentService有以下特点: (1)  它创建了一个独立的工作线程来处理所有的通过onStartCommand()传递给服务的intents。
821 0
|
1天前
|
存储 安全 Android开发
安卓应用开发:构建一个高效的用户登录系统
【5月更文挑战第3天】在移动应用开发中,用户登录系统的设计与实现是至关重要的一环。对于安卓平台而言,一个高效、安全且用户体验友好的登录系统能够显著提升应用的用户留存率和市场竞争力。本文将探讨在安卓平台上实现用户登录系统的最佳实践,包括对最新身份验证技术的应用、安全性考量以及性能优化策略。
|
17小时前
|
缓存 Java Android开发
大厂首发,Android开发社招面试总结
大厂首发,Android开发社招面试总结
大厂首发,Android开发社招面试总结
|
17小时前
|
Android开发 缓存 双11
android的基础ui组件,Android开发社招面试经验
android的基础ui组件,Android开发社招面试经验
android的基础ui组件,Android开发社招面试经验
|
17小时前
|
设计模式 程序员 Android开发
android开发的基础,大厂程序员35岁后的职业出路在哪
android开发的基础,大厂程序员35岁后的职业出路在哪
android开发的基础,大厂程序员35岁后的职业出路在哪
|
17小时前
|
前端开发 Java 物联网
Android开发面试基础,3天拿到网易Android岗offer
Android开发面试基础,3天拿到网易Android岗offer