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.
2172 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.
2782 0
|
Android开发
android应用开发—获取当前运行的services列表
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/voidreturn/article/details/78110190 p...
1367 0
|
Android开发
Android中Services之异步IntentService
IntentService:异步处理服务,新开一个线程:handlerThread在线程中发消息,然后接受处理完成后,会清理线程,并且关掉服务。 IntentService有以下特点: (1)  它创建了一个独立的工作线程来处理所有的通过onStartCommand()传递给服务的intents。
843 0
|
6天前
|
编解码 Java Android开发
通义灵码:在安卓开发中提升工作效率的真实应用案例
本文介绍了通义灵码在安卓开发中的应用。作为一名97年的聋人开发者,我在2024年Google Gemma竞赛中获得了冠军,拿下了很多项目竞赛奖励,通义灵码成为我的得力助手。文章详细展示了如何安装通义灵码插件,并通过多个实例说明其在适配国际语言、多种分辨率、业务逻辑开发和编程语言转换等方面的应用,显著提高了开发效率和准确性。
|
5天前
|
Android开发 开发者 UED
安卓开发中自定义View的实现与性能优化
【10月更文挑战第28天】在安卓开发领域,自定义View是提升应用界面独特性和用户体验的重要手段。本文将深入探讨如何高效地创建和管理自定义View,以及如何通过代码和性能调优来确保流畅的交互体验。我们将一起学习自定义View的生命周期、绘图基础和事件处理,进而探索内存和布局优化技巧,最终实现既美观又高效的安卓界面。
18 5
|
3天前
|
JSON Java Android开发
探索安卓开发之旅:打造你的第一个天气应用
【10月更文挑战第30天】在这个数字时代,掌握移动应用开发技能无疑是进入IT行业的敲门砖。本文将引导你开启安卓开发的奇妙之旅,通过构建一个简易的天气应用来实践你的编程技能。无论你是初学者还是有一定经验的开发者,这篇文章都将成为你宝贵的学习资源。我们将一步步地深入到安卓开发的世界中,从搭建开发环境到实现核心功能,每个环节都充满了发现和创造的乐趣。让我们开始吧,一起在代码的海洋中航行!
|
5天前
|
缓存 数据库 Android开发
安卓开发中的性能优化技巧
【10月更文挑战第29天】在移动应用的海洋中,性能是船只能否破浪前行的关键。本文将深入探讨安卓开发中的性能优化策略,从代码层面到系统层面,揭示如何让应用运行得更快、更流畅。我们将以实际案例和最佳实践为灯塔,引领开发者避开性能瓶颈的暗礁。
16 3
|
7天前
|
存储 IDE 开发工具
探索Android开发之旅:从新手到专家
【10月更文挑战第26天】在这篇文章中,我们将一起踏上一段激动人心的旅程,探索如何在Android平台上从零开始,最终成为一名熟练的开发者。通过简单易懂的语言和实际代码示例,本文将引导你了解Android开发的基础知识、关键概念以及如何实现一个基本的应用程序。无论你是编程新手还是希望扩展你的技术栈,这篇文章都将为你提供价值和启发。让我们开始吧!