首页 > 其他分享 >Android 四大组件 service

Android 四大组件 service

时间:2024-05-29 18:31:34浏览次数:15  
标签:Service service isBound void Override 组件 new Android public

前言

在Android系统中,Service 是一个用来执行长时间运行的操作而不提供用户界面的应用组件。它可以在后台执行任务,即使用户切换到其他应用也不会被中断。

Service 在Android中主要用于在后台执行长时间运行的任务,例如播放音乐、执行文件下载、处理网络请求等。尽管Service运行在后台,但它仍然属于应用程序的一部分,因此不会影响用户对前台应用的交互。

Service的类型

在Android中,Service 可以分为三种类型:

前台Service

前台Service 是用户可见的服务,它会在系统的通知区域显示一个通知,表示正在运行的服务。这种类型的Service被视为用户当前活跃的一部分,因此系统不太可能在内存不足时终止它。前台Service 常用于音乐播放或GPS导航等需要用户明确知道并持续运行的功能。

后台Service

后台Service 在用户不可见的情况下执行操作,通常用于执行不需要与用户交互的任务。但从Android Oreo(API 级别 26)开始,后台服务的使用受到了严格限制,以减少对系统性能的影响和提升电池寿命。

绑定Service

绑定Service 是一种允许应用组件(如Activity)绑定到Service并与之交互的服务。组件可以发送请求、接收响应,甚至进行进程间通信(IPC)。绑定的Service 只在其他应用组件与其绑定时运行,不会无限期运行。

Service的实现

实现Service 主要涉及以下几个步骤:

  • 定义Service: 在Java或Kotlin文件中扩展Service基类,并重写其生命周期方法如onCreate(), onStartCommand(), onBind(), 和onDestroy()

  • 配置Manifest: 在AndroidManifest.xml中声明Service,并设置适当的权限和属性。

  • 启动和绑定Service: 通过startService(Intent)方法启动服务,或者使用bindService(Intent, ServiceConnection, int)绑定服务。前者适用于执行单一操作或执行不返回结果的操作,后者适用于与服务进行交互。

如下是一个例子:创建一个服务,允许用户在后台播放音乐,即使他们离开了应用,音乐仍然可以继续播放:

public class MusicService extends Service {
    private MediaPlayer mediaPlayer;

    @Override
    public void onCreate() {
        super.onCreate();
        // 初始化 MediaPlayer 对象
        mediaPlayer = MediaPlayer.create(this, R.raw.sample_music);
        mediaPlayer.setLooping(true); // 设置音乐循环播放
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        mediaPlayer.start(); // 开始播放音乐
        return START_STICKY; // 系统如果终止服务后,会尝试重新创建服务并调用 onStartCommand()
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mediaPlayer != null) {
            mediaPlayer.stop();
            mediaPlayer.release();
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null; // 不提供绑定功能
    }
}
<service android:name=".MusicService" />
public class MainActivity extends AppCompatActivity {

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

        Button startButton = findViewById(R.id.startButton);
        Button stopButton = findViewById(R.id.stopButton);

        startButton.setOnClickListener(v -> startService(new Intent(this, MusicService.class)));
        stopButton.setOnClickListener(v -> stopService(new Intent(this, MusicService.class)));
    }
}

管理Service的生命周期

主要包括:

  • onCreate(): 当服务第一次创建时调用。
  • onStartCommand(): 每次通过 startService() 方法启动服务时调用。
  • onBind(): 当其他组件想要与服务绑定时调用。
  • onUnbind(): 当所有组件都与服务解绑时调用。
  • onDestroy(): 当服务不再使用且将被销毁时调用。

与服务通信

Binder

对于在同一应用内运行的服务,可以通过定义一个 Binder 类并在服务中返回这个 Binder 的实例,从而实现与服务的通信。客户端(如 Activity)可以绑定到服务并获得这个 Binder 对象,通过这个对象调用服务中的方法。

public class LocalService extends Service {
    // Binder 类的实例,用于返回给客户端
    private final IBinder binder = new LocalBinder();

    public class LocalBinder extends Binder {
        LocalService getService() {
            // 返回当前的 LocalService 实例以供客户端调用公开的方法
            return LocalService.this;
        }
    }

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

    // 服务中的一个方法,客户端可以调用
    public int getRandomNumber() {
        return new Random().nextInt(100);
    }
}
public class MainActivity extends AppCompatActivity {
    private LocalService localService;
    private boolean isBound = false;

    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName className, IBinder service) {
            LocalBinder binder = (LocalBinder) service;
            localService = binder.getService();
            isBound = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            isBound = false;
        }
    };

    @Override
    protected void onStart() {
        super.onStart();
        bindService(new Intent(this, LocalService.class), connection, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (isBound) {
            unbindService(connection);
            isBound = false;
        }
    }

    public void onButtonClick(View v) {
        if (isBound) {
            // 调用服务的方法
            int num = localService.getRandomNumber();
            Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show();
        }
    }
}
Messager

如果服务需要与多个应用组件或其他应用进行跨进程通信,可以使用 Messenger。在这种方式a中,服务使用 Handler 接收消息,并通过 Messenger 对象响应。

public class MessengerService extends Service {
    static final int MSG_SAY_HELLO = 1;

    class IncomingHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_SAY_HELLO:
                    Toast.makeText(getApplicationContext(), "Hello!", Toast.LENGTH_SHORT).show();
                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    }

    final Messenger messenger = new Messenger(new IncomingHandler());

    @Override
    public IBinder onBind(Intent intent) {
        return messenger.getBinder();
    }
}
public class ActivityMessenger extends AppCompatActivity {
    Messenger messenger = null;
    boolean isBound;

    private ServiceConnection connection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder service) {
            messenger = new Messenger(service);
            isBound = true;
        }

        public void onServiceDisconnected(ComponentName className) {
            messenger = null;
            isBound = false;
        }
    };

    public void sayHello(View v) {
        if (!isBound) return;
        Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0);
        try {
            messenger.send(msg);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
}
AIDL

AIDL(Android Interface Definition Language)是一种接口定义语言,用于让客户端和服务之间能够在不同的进程中进行通信。使用 AIDL 是处理复杂数据传输或跨应用通信的标准方式。

定义一个 AIDL 文件,这个文件描述了服务将要公开的接口

interface IRandomNumberService {
    int getRandomNumber();
}

当构建项目时,Android 构建工具会根据 AIDL 文件生成一个 Java 接口。然后可以创建一个实现这个接口的服务:

IRandomNumberService.Stub 是由 AIDL 文件自动生成的,需要实现这个 Stub 类中的方

public class RandomNumberService extends Service {
    private final IRandomNumberService.Stub binder = new IRandomNumberService.Stub() {
        public int getRandomNumber() throws RemoteException {
            return new java.util.Random().nextInt(100);
        }
    };

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

现在,任何其他应用都可以绑定到这个服务并调用 getRandomNumber 方法

public class ClientActivity extends AppCompatActivity {
    private IRandomNumberService randomNumberService;
    private boolean isBound = false;

    private ServiceConnection connection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder service) {
            randomNumberService = IRandomNumberService.Stub.asInterface(service);
            isBound = true;
        }

        public void onServiceDisconnected(ComponentName className) {
            randomNumberService = null;
            isBound = false;
        }
    };

    @Override
    protected void onStart() {
        super.onStart();
        bindService(new Intent("com.example.myapp.RandomNumberService"),
                    connection, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (isBound) {
            unbindService(connection);
            isBound = false;
        }
    }

    public void onButtonClick() {
        if (isBound) {
            try {
                int randomNumber = randomNumberService.getRandomNumber();
                // Use the random number...
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }
}

标签:Service,service,isBound,void,Override,组件,new,Android,public
From: https://blog.csdn.net/m0_63629756/article/details/137870372

相关文章

  • Android 图片加载glide库 一次通关
    前言Glide是一个由Bumptech开发的开源图片加载库,专门用于Android平台。它被广泛应用于Android应用中,以简化图片加载过程,并提高性能和效率。Glide能够快速加载图片,同时减少页面加载时间和内存消耗。Glide具有强大的缓存机制,支持内存缓存和磁盘缓存,有效地减少重复的图片加载请......
  • 升鲜宝供应链管理系统重构版发布(技术点:Java8、mysql8.0 uniapp、vue、android、web 框
    升鲜宝供应链管理系统重构版发布(技术点:Java8、mysql8.0uniapp、vue、android、web框架:Vue3+SpringBoot3),界面功能(三) 主要功能要点:     权限管理(组织机构、用户管理、角色管理、岗位管理)     系统设置(菜单管理、参数管理、数据字典、定时任务、文件管......
  • HarmonyOS实战开发:@ohos.pluginComponent (插件组件管理器)
    用于给插件组件的使用者请求组件与数据,使用者发送组件模板和数据。如需实现插件模板的显示,请参考PluginComponent。说明:本模块首批接口从APIVersion8开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。导入模块importpluginComponentManagerfrom......
  • QT C++实现表头添加组件
    QTableWidget在表头添加组件QTableWidget的表头有一个类QHeaderView是专门处理表头的类,要在表头添加一个类似QCheckBox的组件需要重写一个类并继承QHeaderView。QTableWidget中添加复选框并实现全选居中:自定义类MyHeaderView并继承QHeaderView自定义类MyTableWidget并继承QTa......
  • 鸿蒙HarmonyOS实战-Web组件(前端函数和应用侧函数相互调用)
    ......
  • 封装通用 ECharts 图表组件(三):环形图实现
    在数据可视化领域,ECharts是一个非常流行且功能强大的图表库。它提供了丰富的图表类型,能够满足各种复杂的数据展示需求。在本系列的第三篇文章中,我们将探讨如何封装一个通用的ECharts环形图组件。什么是环形图?环形图是一种特殊的饼图,它由一个内圆和一个外圆组成,中间的部分是......
  • 封装通用 ECharts 图表组件(四):分格柱状图实现
    在数据可视化的世界中,ECharts以其强大的功能和灵活性,成为了开发者们的首选图表库之一。继我们之前探讨的环形图封装之后,本文将带领大家进入另一个实用且美观的图表类型——分格柱状图的封装实现。分格柱状图简介分格柱状图是一种特殊的柱状图,它通过将每个柱子分割成多个小格......
  • vue3 组件的动态渲染 <component :is=“componentTag“ />
    1、动态渲染组件        <component:is=""></component>        通过isShow来切换显示A、B组件首先创建父组件.vue文件和两个子组件A、B文件,并引入。template:<div><h3>我是父组件dynamicComp.vue</h3><button@click="isShow=!isShow">切换......
  • docker安装jenkins+Android sdk
    1、宿主机安装Java环境参考这个链接:https://www.cnblogs.com/likecoke/p/13638419.html2、宿主机安装 AndroidSDK2.1下载zip包wgethttps://dl.google.com/android/repository/commandlinetools-linux-6858069_latest.zip2.2解压到 /home/android-sdk路径下unzip-d/hom......
  • Android14音频进阶之dump各阶段音频数据<Tee Sink方案>(七十五)
    简介:CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长!优质专栏:Audio工程师进阶系列【原创干货持续更新中……】......