Android学习总结——Service组件

Posted ChaoYoung

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android学习总结——Service组件相关的知识,希望对你有一定的参考价值。

    从Service的启动方式上,可以将Service分为Started Service和Bound Service。在使用Service时,要想系统能够找到此自定义Service,无论哪种类型,都需要在androidManifest.xml中声明:

<service android:name=".MyService">

 

一:StartService方式启动服务

    Started Service相对比较简单,通过context.startService(Intent serviceIntent)启动Service,context.stopService(Intent serviceIntent)停止此Service。

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.servicetest">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        
        <service android:name=".MyService">

        </service>
    </application>

</manifest>

 

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<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="com.example.servicetest.MainActivity">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="启动服务"
        android:id="@+id/btn_StartService" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="停止服务"
        android:id="@+id/btn_StopService" />
</LinearLayout>

MainActivity:
package com.example.servicetest;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    private Button startService;
    private Button stopService;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        startService=(Button)findViewById(R.id.btn_StartService);
        stopService=(Button) findViewById(R.id.btn_StopService);

        startService.setOnClickListener(this);
        stopService.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()){
            case R.id.btn_StartService:
                //启动服务
                Intent intentStart=new Intent(MainActivity.this,MyService.class);
                startService(intentStart);
                break;
            case R.id.btn_StopService:
                //停止服务
                Intent intentStop=new Intent(MainActivity.this,MyService.class);
                stopService(intentStop);
                break;
        }
    }
}

 

MyService:
package com.example.servicetest;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Created by xch on 2016/9/5.
 */
public class MyService extends Service{

    private boolean flag=true;

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.i("tag","服务被创建!");

    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.i("tag","服务被销毁!");
        new MyThread().setFlagFalse();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        new MyThread().start();

        return super.onStartCommand(intent, flags, startId);
    }

    class MyThread extends Thread{
        public void setFlagFalse(){
            flag=false;
        }
        @Override
        public void run() {
            super.run();

            while (flag){
                //每隔一秒钟打印当前时间一次
                //设置时间打印格式
                SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//24小时制
                Date date=new Date();
                String time=sdf.format(date);
                Log.i("date",time);
                try {
                    //沉睡1秒
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

 

二. BoundService方式启动服务

    bindService启动流程: context.bindService()  ——> onCreate()  ——> onBind()  ——> Service running  ——> onUnbind()  ——> onDestroy()  ——> Service stop

 

MainActivity:
package com.example.servicetest2;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    private Button bindService,unBindService;
    private Intent intent;
    private MyServiceConn conn=new MyServiceConn();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        bindService=(Button)findViewById(R.id.btn_BindService);
        unBindService=(Button)findViewById(R.id.btn_UnBindService);

        bindService.setOnClickListener(this);
        unBindService.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn_BindService:
                intent=new Intent(MainActivity.this,MyService.class);
                bindService(intent,conn, Context.BIND_AUTO_CREATE);
                break;
            case R.id.btn_UnBindService:
                intent=new Intent(MainActivity.this,MyService.class);
                unbindService(conn);
                break;
        }
    }
    private class MyServiceConn implements ServiceConnection {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
           //在服务绑定成功的时候执行
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
           //当服务所在的进程被杀死,或崩溃的时候执行
        }
    }
}

 

MyService:
package com.example.servicetest2;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Created by xch on 2016/9/7.
 */
public class MyService extends Service {
    private boolean flag=true;
    private MyThread thread=new MyThread();

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        thread.start();
        return null;
    }

    @Override
    public void onCreate() {
        Log.i("service","服务被创建!");
        super.onCreate();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.i("service","服务被销毁!");
        thread.setFlagFalse();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }

    class MyThread extends Thread{
        public void setFlagFalse(){
            flag=false;
        }

        @Override
        public void run() {
            super.run();
            while (flag){
                Date date=new Date();
                SimpleDateFormat sdf=new SimpleDateFormat("yyyy-mm-dd HH:mm:ss");
                Log.i("date",sdf.format(date));
                try {
                    sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }
    }
}

 

三.Service与Activity之间通讯

    BoundService可以实现,但是startService没有这个特点。这里需要注意的是,利用bindService启动的Service无法获取这个Service对象,所以这里需要在Service中将对象返回,既然有返回就需要接收。so,看代码:

MyService:
package com.example.servicetest2;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Created by xch on 2016/9/7.
 */
public class MyService extends Service {
    private boolean flag=true;
    private MyThread thread;
    private String format="yyyy-mm-dd HH:mm:ss";

    //更改系统时间的输出格式
    public void setFormat(String format){
        this.format=format;
    }

    public void changeFormat(String format){
        if(thread!=null){
            //调用方法,更改时间输出格式
            setFormat(format);
        }
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        thread.start();
        //将代理类返回回去
        return new ServiceBinder();
    }

    @Override
    public void onCreate() {
        Log.i("service","服务被创建!");
        thread=new MyThread();
        super.onCreate();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.i("service","服务被销毁!");
        thread.setFlagFalse();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }

    class MyThread extends Thread{
        public void setFlagFalse(){
            flag=false;
        }

        @Override
        public void run() {
            super.run();
            while (flag){
                Date date=new Date();
                SimpleDateFormat sdf=new SimpleDateFormat(format);
                Log.i("date",sdf.format(date));
                try {
                    sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }
    }

    /**
     * 当前服务的代理类,即可使用changeFormat()方法
     * 需要通过IBinder将这个代理类返回回去,即onBinder()方法
     */
    public class ServiceBinder extends Binder{
        public void changeServiceBinder(String format){
            if(thread!=null){
                changeFormat(format);
            }
        }

    }
}

这里需要在service中定义一个代理类,并利用onBinder()方法返回去。

 

MainActivity:

package com.example.servicetest2;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    private Button bindService,unBindService,changeFormat;
    private Intent intent;
    private MyServiceConn conn=new MyServiceConn();
    //接收到的service对象
    private MyService.ServiceBinder serviceBinder;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        bindService=(Button)findViewById(R.id.btn_BindService);
        unBindService=(Button)findViewById(R.id.btn_UnBindService);
        changeFormat=(Button)findViewById(R.id.btn_changeFormat);

        bindService.setOnClickListener(this);
        unBindService.setOnClickListener(this);
        changeFormat.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn_BindService:
                intent=new Intent(MainActivity.this,MyService.class);
                bindService(intent,conn, Context.BIND_AUTO_CREATE);
                break;
            case R.id.btn_UnBindService:
                intent=new Intent(MainActivity.this,MyService.class);
                unbindService(conn);
                break;
            case R.id.btn_changeFormat:
                serviceBinder.changeServiceBinder("HH:mm:ss");
                break;
        }
    }
    private class MyServiceConn implements ServiceConnection {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
           //在服务绑定成功的时候执行,同时接收到了IBinder对象(类型为代理类对象,因为onBinder方法返回了代理类对象)
            serviceBinder= (MyService.ServiceBinder) service;
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
           //当服务所在的进程被杀死,或崩溃的时候执行
        }
    }
}

   这里实现了ServiceConnection接口的自定义类需要实现如上两个方法,其中onServiceConnected(ComponentName name, IBinder service)方法能获取onBinder()返回的service对象。

 结果:










以上是关于Android学习总结——Service组件的主要内容,如果未能解决你的问题,请参考以下文章

Android探索之Service全面回顾及总结

Android学习笔记:Android Service组件深入解析

Android服务Service使用总结

Android 四大组件之Service学习

20189217 2018-2019-2 《移动平台开发实践》第6周学习总结

错误记录Oboe / AAudio 播放器报错 ( onEventFromServer - AAUDIO_SERVICE_EVENT_DISCONNECTED - FIFO cleared )(代码片