Android Service(服务)

参考文章

  1. 关于Android Service真正的完全详解,你需要知道的一切
  2. Android Service 启动方式,生命周期和应用场景详解

Android Service 启动方式

android有两种服务启动模式,startServicebindService

startService 和 bindService 区别

模式名称特点
startService一旦服务开启跟调用者(开启者)就没有任何关系了。开启者退出了,开启者挂了,服务还在后台长期的运行,只有通过调用停止服务的方法才能停止服务,或者是整个程序被kill掉,那么服务也会随之kill。开启者不能调用服务里面的方法
bindServicebind的方式开启服务,绑定服务,调用者挂了,服务也会跟着挂掉。绑定者可以调用服务里面的方法。(说白了就和小程序一样,打开的时候使用,用完了就关闭拍屁股走人,一次性滴)注意:绑定服务不会调用onstart()或者onstartcommand()方法

在这里插入图片描述

Service的创建以及在AndroidManifest.xml文件中的声明

我们通过android studio创建service的时候,编译器自动的帮助我们在清单文件中声明了相关属性

在这里插入图片描述

        <service
            android:name=".StartService"
            android:enabled="true"
            android:exported="true"></service>
  • android:name:对应Service类名
  • android:exported:代表是否能被其他应用隐式调用,其默认值是由service中有无intent-filter决定的,如果有intent-filter,默认值为true,否则为false。为false的情况下,即使有intent-filter匹配,也无法打开,即无法被其他应用隐式调用。
  • android:enabled:是否可以被系统实例化,默认为 true因为父标签 也有 enable 属性,所以必须两个都为默认值true的情况下服务才会被激活,否则不会激活。

startService

startService生命周期

  1. startService(Intent)通过这种方式开启的服务,执行的生命周期方法:第一次调用startService的时候:onCreate→onStartCommand再次调用startService的时候:只执行onStartCommand
  2. 想停止用startService开启的服务要使用stopService(Intent),stopService执行之后,Service会走onDestroy()方法,执行之后Service销毁,再次调用stopService没有反应
  3. 如果在Activity中通过startService方法开启一个服务,当Activity退出的时候Service不会销毁,依然在后台运行,只有手动调用stopService或者在应用管理器中关闭Service,服务才会销毁

startService案例

设计一个界面,上面有两个按钮,分别是启动按钮与停止按钮,用来启动、停止服务
在这里插入图片描述
创建一个service

public class StartService extends Service {
	
	// 声明一个线程
    private Thread myThread;
	
	// 控制线程的运行
    private boolean flag=true;

	// 判断当前service内的线程是否在运行
    private boolean trigger=false;

    public StartService() {
    }

    /**
     * 绑定服务时才会调用
     * 必须要实现的方法
     * @param intent
     * @return
     */
    @Override
    public IBinder onBind(Intent intent) {
        Log.w("StartService", "onBind()");
       return null;
    }

    /**
     * 首次创建服务时,系统将调用此方法来执行一次性设置程序(在调用 onStartCommand() 或 onBind() 之前)。
     * 如果服务已在运行,则不会调用此方法。该方法只被调用一次
     */
    @Override
    public void onCreate() {
        super.onCreate();
		// 在服务创建时,实例化一个线程
        myThread=new Thread(new Runnable() {
            @Override
            public void run() {
                while(flag){
                    try {

                        SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                        Log.w(format.format(new Date(System.currentTimeMillis())), "服务正在运行。。。。");
                        Thread.sleep(1000);

                    }catch(Exception e){
                        e.printStackTrace();
                    }
                }
            }
        });
        Log.w("StartService", "服务被创建了");
    }

    /**
     * 每次通过startService()方法启动Service时都会被回调。
     * @param intent
     * @param flags
     * @param startId
     * @return
     */
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.w("StartService", "服务onStartCommand()被调用了");
		
		// 在onStartCommand触发时启动线程,如果线程已经启动就无须再次启动
        if(!trigger){
            myThread.start();
            trigger=true;
        }
        return super.onStartCommand(intent, flags, startId);
    }

    /**
     * 调用stopService()停止服务销毁时的回调
     */
    @Override
    public void onDestroy() {
	// 在service销毁时结束进程
	// 将进程的运行标志设为false
        flag=false;
        trigger=false;
        Log.w("StartService", "服务被销毁了");
        super.onDestroy();
    }
}

MainActivity

public class MainActivity extends AppCompatActivity {

    private Button startBtn;
    private Button stopBtn;

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

        startBtn = this.findViewById(R.id.startBtn);
        stopBtn = this.findViewById(R.id.stopBtn);

        // 创建服务实例
        final Intent service = new Intent(this, StartService.class);


        startBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 启动服务
                MainActivity.this.startService(service);
            }
        });


        stopBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 停止服务
                MainActivity.this.stopService(service);
            }
        });
    }
}

点击启动服务时,启动服务的activity进入了后台,服务并不会结束

在这里插入图片描述

结束服务只有kill当前程序或者调用stopService方法来结束service

在这里插入图片描述

bindService

  1. bindService启动服务特点:(和小程序一样,一次性滴,进入页面的时候绑定service,退出的时候关闭service所以一般我们都在Activity的onStart方法中绑定服务,在onStop中解绑服务
  2. bindService启动的服务和调用者之间是典型的client-server模式。调用者是client,service则是server端。service只有一个,但绑定到service上面的client可以有一个或很多个。这里所提到的client指的是组件,比如某个Activity。
  3. client可以通过IBinder接口获取Service实例,从而实现在client端直接调用Service中的方法以实现灵活交互,这在通过startService方法启动中是无法实现的。
  4. bindService启动服务的生命周期与其绑定的client息息相关。当client销毁时,client会自动与Service解除绑定。当然,client也可以明确调用Context的unbindService()方法与Service解除绑定。

bindService实例

结果实例

在这里插入图片描述

activity 界面

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/fun01_btn"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="服务方法1"
        app:layout_constraintBottom_toTopOf="@+id/fun02_btn"
        app:layout_constraintEnd_toEndOf="@+id/fun02_btn"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="@+id/fun02_btn"
        app:layout_constraintTop_toBottomOf="@+id/bind_btn" />

    <Button
        android:id="@+id/fun02_btn"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="服务方法2"
        app:layout_constraintBottom_toTopOf="@+id/fun03_btn"
        app:layout_constraintEnd_toEndOf="@+id/fun03_btn"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="@+id/fun03_btn"
        app:layout_constraintTop_toBottomOf="@+id/fun01_btn" />

    <Button
        android:id="@+id/fun03_btn"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="服务方法3"
        app:layout_constraintBottom_toTopOf="@+id/unbind_btn"
        app:layout_constraintEnd_toEndOf="@+id/unbind_btn"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="@+id/unbind_btn"
        app:layout_constraintTop_toBottomOf="@+id/fun02_btn" />

    <Button
        android:id="@+id/bind_btn"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="绑定服务"
        app:layout_constraintBottom_toTopOf="@+id/fun01_btn"
        app:layout_constraintEnd_toEndOf="@+id/fun01_btn"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="@+id/fun01_btn"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/unbind_btn"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginEnd="172dp"
        android:text="解绑服务"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/fun03_btn" />

</androidx.constraintlayout.widget.ConstraintLayout>

activity

public class MainActivity extends AppCompatActivity {

    Button btn_bind;
    Button btn_unbind;
    Button btn_fun01;
    Button btn_fun02;
    Button btn_fun03;

    private MyService myService;
    private ServiceConnection connection;

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

        // 绑定服务
        btn_bind = findViewById(R.id.bind_btn);
        btn_bind.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (connection == null) {
                    Intent intent = new Intent(MainActivity.this, MyService.class);
                    connection = new ServiceConnection() {
                        @Override
                        public void onServiceConnected(ComponentName name, IBinder service) {
                            myService = ((MyService.MyBinder) service).getService();
                        }

                        @Override
                        public void onServiceDisconnected(ComponentName name) {

                        }
                    };
                    MainActivity.this.bindService(intent, connection, Context.BIND_AUTO_CREATE);
                }
            }
        });

        // 解绑服务
        btn_unbind = findViewById(R.id.unbind_btn);
        btn_unbind.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (connection != null) {
                    unbindService(connection);
                    connection = null;
                }
            }
        });


        btn_fun01 = findViewById(R.id.fun01_btn);
        btn_fun01.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (connection != null) {
                    myService.fun01();
                }
            }
        });

        btn_fun02 = findViewById(R.id.fun02_btn);
        btn_fun02.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (connection != null) {
                    myService.fun02();
                }
            }
        });

        btn_fun03 = findViewById(R.id.fun03_btn);
        btn_fun03.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (connection != null) {
                    myService.fun03();
                }
            }
        });
    }
}

service(核心代码)

public class MyService extends Service {


    public MyService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.i("MyService", "onBind");
        return new MyBinder();
    }

    public void fun01() {
        Log.i("MyService", "fun01");
    }

    public void fun02() {
        Log.i("MyService", "fun02");
    }

    public void fun03() {
        Log.i("MyService", "fun03");
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.i("MyService", "onUnBind");

        return super.onUnbind(intent);
    }

    public class MyBinder extends Binder {

        public MyService getService() {
            return MyService.this;
        }
    }
}

  • 4
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 13
    评论
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值