Android 四大组件之 Service

重温Android 四大组件之 Service

目录

一、Service是什么?

1.Service是一个应用组件,它用来在后台完成一个时间跨度比较大的工作且没有关联任何界面

2.一个Service可以完成下面这些工作:

3.服务的特点:

4. 源码

二 、Service的分类

1.Local Service(本地服务)

2.Remote Service(远程服务)

三、 定义Service

1.定义一个类继承于Service类

2.在AndroidManifest.xml中配置Service

四、启动与停止Service

1.方式一:一般启动

context.startService(Intent intent)contstopService(lntent intent)

2.方式二:绑定启动

bindService(Intent intent,ServiceConnection connection)unbindService(ServiceConnection connection)

五、代码示例

1. 本地服务

(1) activity_main.xml 中定义两组按钮

(2) 自定义Service 类, 并实现onBind 方法, 以及重写其它生命周期相关方法(onCreate / onStartCommand/ onUnbind/ onDestroy)

(3) AndroidManifest 中声明service

(4) Activity 中处理Button 点击事件 

(5) 启动或停止服务的 日志输出:

(6) 绑定或解绑服务的 日志输出:



一、Service是什么?


1.Service是一个应用组件,它用来在后台完成一个时间跨度比较大的工作且没有关联任何界面

2.一个Service可以完成下面这些工作:

       访问网络
       播放音乐
       文件1O操作
       大数据量的数据库操作

3.服务的特点:

Service在后台运行,不用与用户进行交互即使应用退出,服务也不会停止.
在默认情况下,Service运行在应用程序进程的主线程(UI线程)中,如果需要在Service中处理一些网络连接等耗时的操作,那么应该将
这些任务放在分线程中处理,避兔阻塞用户界面

4. 源码

Service 类是一个抽象类, 继承了ContextWrapper,  即Context 类里定义的方法也可以用到 (Activity 也是ContextWrapper 的子类)

public abstract class Service extends ContextWrapper implements ComponentCallbacks2,
        ContentCaptureManager.ContentCaptureClient {

二 、Service的分类

1.Local Service(本地服务)

Service对象与Serive的启动者在同个进程中运行,两者的通信是进程内通信


2.Remote Service(远程服务)

Service对象与Service的启动者不在同一个进程中运行,这时存在一个进程间通信的问题,Android专门为此设计了AlDL来实现进程间通信

3. 前台service 、后台service

参考:

Android入门教程 | 四大组件之Service(前台服务,后台服务) - 哔哩哔哩点击进入查看全文>https://www.bilibili.com/read/cv13538561前台需使用 startForegroundService 启动,并在状态栏上显示图标(Notification);

一般用得多的是后台service

三、 定义Service

1.定义一个类继承于Service类

public class MyLocalService extends Service {

2.在AndroidManifest.xml中配置Service

<application 
           ...>
    <service android:name=".MyLocalService"/>
</application>

四、启动与停止Service


1.方式一:一般启动

context.startService(Intent intent)
context.stopService(lntent intent)


2.方式二:绑定启动

bindService(Intent intent,ServiceConnection connection)
unbindService(ServiceConnection connection)


区别:看Service启动后是否与启动者有关联?
Service对象经历的生命周期是否相同?

五、代码示例

1. 本地服务

实例如图:

(1) activity_main.xml 中定义两组按钮

分别为 启动服务 、停止服务  和 绑定服务、解绑服务, 界面很简单

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:textSize="30sp"
        android:text="1. 测试启动本地服务" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:orientation="horizontal">
        <Button
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="match_parent"
            android:text="启动服务"
            android:onClick="startService"
            android:textSize="20sp"/>

        <Button
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="match_parent"
            android:text="停止服务"
            android:onClick="stopService"
            android:textSize="20sp"/>
    </LinearLayout>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:textSize="30sp"
        android:text="2. 测试绑定本地服务" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:orientation="horizontal">
        <Button
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="match_parent"
            android:text="绑定服务"
            android:onClick="bindService"
            android:textSize="20sp"/>

        <Button
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="match_parent"
            android:text="解绑服务"
            android:onClick="unbindService"
            android:textSize="20sp"/>
    </LinearLayout>

</LinearLayout>

(2) 自定义Service 类, 并实现onBind 方法, 以及重写其它生命周期相关方法(onCreate / onStartCommand/ onUnbind/ onDestroy)

package com.example.servicetest1;

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

import androidx.annotation.Nullable;

public class MyLocalService extends Service {
    private final static String TAG = "MyLocalService";

    @Override
    public void onCreate() {
        super.onCreate();
        log("onCreate");
    }

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

    @Override
    public void onDestroy() {
        super.onDestroy();
        log("onDestroy");
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        log("onBind");
        return new Binder();
    }

    @Override
    public boolean onUnbind(Intent intent) {
        log("onUnbind");
        return super.onUnbind(intent);
    }

    private void log(String msg){
        Log.d(TAG, msg);
    }
}

(3) AndroidManifest 中声明service

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        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=".MyLocalService"/>
    </application>

(4) Activity 中处理Button 点击事件 

import androidx.appcompat.app.AppCompatActivity;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    private final static String TAG = "MainActivity";

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

    public void startService(View view) {
        log("startService ");
        Intent intent = new Intent(this, MyLocalService.class);
        startService(intent);
    }

    public void stopService(View view) {
        log("stopService ");
        Intent intent = new Intent(this, MyLocalService.class);
        stopService(intent);
    }

    private void log(String msg) {
        Log.d(TAG, msg);
    }

    private ServiceConnection mConnection = null;

    public void bindService(View view) {
        log("bindService ");
        Intent intent = new Intent(this, MyLocalService.class);
        if (mConnection == null) {
            mConnection = new ServiceConnection() {
                @Override
                public void onServiceConnected(ComponentName name, IBinder service) {
                    log("onServiceConnected ");
                }

                @Override
                public void onServiceDisconnected(ComponentName name) {
                    log("onServiceDisconnected ");
                }
            };
        }

        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }

    public void unbindService(View view) {
        log("unbindService ");
        if (mConnection != null) {
            unbindService(mConnection);
            mConnection = null;
            Toast.makeText(this, "unbind service", Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    protected void onDestroy() { // 似乎是多余的
        super.onDestroy();
        log("onDestroy ");
        if (mConnection != null) {
            log("onDestroy - need unbind service");
            unbindService(mConnection);
            mConnection = null;
        }
    }
}

(5) 启动或停止服务的 日志输出:

//第一次点击启动
2020-11-26 12:42:27.305  D/MainActivity: startService 
2020-11-26 12:42:27.312  D/MyLocalService: onCreate
2020-11-26 12:42:27.312  D/MyLocalService: onStartCommand
//第二次点击启动
2020-11-26 12:42:31.241  D/MainActivity: startService 
2020-11-26 12:42:31.244  D/MyLocalService: onStartCommand

//点击停止
2020-11-26 12:42:34.118  D/MainActivity: stopService 
2020-11-26 12:42:34.122  D/MyLocalService: onDestroy

可以看到, 在启动时, Service 会调用 onCreate / onStartCommand,   而已经启动情况下,再调启动,仅会执行onStartCommand;

停止时, Service 会调用 onDestroy

(6) 绑定或解绑服务的 日志输出:

//点击绑定
2020-11-26 12:47:46.372  D/MainActivity: bindService 
2020-11-26 12:47:46.379  D/MyLocalService: onCreate
2020-11-26 12:47:46.380  D/MyLocalService: onBind
2020-11-26 12:47:46.383  D/MainActivity: onServiceConnected

//点击解绑
2020-11-26 12:51:48.959  D/MainActivity: unbindService 
2020-11-26 12:51:48.984  D/MyLocalService: onUnbind
2020-11-26 12:51:48.985  D/MyLocalService: onDestroy

//绑定的时候,退出Activity
2020-11-26 12:53:12.285  I/ViewRootImpl@665f8ac[MainActivity]: dispatchDetachedFromWindow
2020-11-26 12:53:12.304  D/MyLocalService: onUnbind
2020-11-26 12:53:12.304  D/MyLocalService: onDestroy

在绑定的时候, 会调用 onCreate /onBind,   客户端会回调 onServiceConnected

解绑的试试,会先调用 onUnBind,  再调用 onDestroy.

此外,在绑定的时候,退出Activity, 似乎会自动解绑服务?? (不需要在Activity onDestroy 时, 手动调用解绑服务??, 不会报 leak service connection ??)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值