Android绑定式服务

news2024/12/28 19:05:30

Github:https://github.com/MADMAX110/Odometer
启动式服务对于后台操作很合适,不过需要一个更有交互性的服务。
接下来构建这样一个应用:
1、创建一个绑定式服务的基本版本,名为OdometerService
我们要为它增加一个方法getDistance(),这个方法会返回一个随机数
2、让活动MainActivity绑定到OdometerService,并调用它的getDistance方法。
将每秒调用一次这个方法,在MainActivity中用得到的结果更新一个文本视图。
3、更新OdometerService,改为使用Android的位置服务。
这个服务将得到用户当前位置的更新,并使用这些更新计算所走过的距离。

创建一个名为Odometer的Android新工程

在这里插入图片描述

创建一个新服务

要创建一个绑定式服务,需要扩展Service类。
如图所示,在com.hfad.odometer中创建一个服务。
不要选中Exported,因为只有当希望这个应用之外的服务能够访问这个服务时才需要将它设置为true。
确保选中Enabled,不选中的话活动将无法运行应用。
在这里插入图片描述

package com.hafd.odometer;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;

public class OdometerService extends Service {

    @Override
    public IBinder onBind(Intent intent) {
        
    }
}

上面的代码实现了一个方法onBind,当一个组件希望绑定到这个服务时,会调用这个方法。这个方法有一个参数Intent,并返回一个IBinder对象。
IBinder是一个接口,用来将你的服务绑定到活动,需要在服务代码中提供它的一个实现。

实现一个绑定器

定义绑定器:

    public class OdometerBinder extends Binder {
        OdometerService getOdometer() {
            return OdometerService.this;
        }
    }

更新OdometerService.java代码并增加一个getDistance方法

package com.hafd.odometer;

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

public class OdometerService extends Service {

    private final IBinder binder = new OdometerBinder();
    private final Random random = new Random();

    //创建一个绑定式服务时,需要提供一个Binder实现
    public class OdometerBinder extends Binder {
        //活动将使用这个方法得到OdometerService的一个引用
        OdometerService getOdometer() {
            return OdometerService.this;
        }
    }

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

    public double getDistance() {
        return random.nextDouble();
    }
}

更新MainActivity的布局

<?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"
    tools:context=".MainActivity"
    android:orientation="vertical"
    android:padding="16dp">

    <TextView
        android:id="@+id/distance"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="48sp"
        android:layout_gravity="center_horizontal"
        android:textAppearance="?android:attr/textAppearanceLarge" />

</LinearLayout>

MainActivity需要做什么

1、创建一个ServiceConnection

ServiceConnection是一个接口,允许将活动绑定到一个服务。
它有两个方法需要你定义:
onServiceConnected():建立与服务的连接时会调用
onServiceDisconnected():断开服务连接时会调用
更新MainActivity.java

    package com.hafd.odometer;

import androidx.appcompat.app.AppCompatActivity;

import android.content.ComponentName;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;

public class MainActivity extends AppCompatActivity {

    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {

        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {

        }
    }

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

在活动和服务之间建立连接时会调用这个方法。
有两个参数:一个ComponentName对象和一个IBinder对象,ComponentName对象描述所要连接的服务,IBinder对象由服务定义。
我们使用onServiceConnected方法做两件事:
1、使用它的IBinder参数得到所连接服务的一个引用,在这里就是OdometerService的引用。为此可以将IBinder强制转换为一个OdometerService.OdometerBinder,并调用它的getOdometer方法。
2、记录活动绑定到这个服务。

    private OdometerService odometer;
    private boolean bound = false;
    
    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            OdometerService.OdometerBinder odometerBinder = (OdometerService.OdometerBinder) iBinder;
            odometer = odometerBinder.getOdometer(); //使用IBinder得到服务的一个引用
            bound = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            bound = false;
        }
    };

onServiceDisconnected方法

记录活动不再绑定到服务。

public void onServiceDisconnected(ComponentName componentName) {
            bound = false;
        }

2、将活动绑定到服务

使用bindService绑定服务

通常会在两个地方将活动绑定到服务:
活动变得可见时,在活动的onStart方法中,如果只需要在活动可见时与活动交互,在这个方法中绑定服务就很合适。
活动创建时,在活动的onCreate方法中,如果需要从服务接受更新,即使活动已经停止也要继续接受更新,就要在这个方法中绑定服务。
在这里我们只需要在MainActivity可见时显示从OdometerService得到的更新,所以要在活动的onStart方法中绑定服务。
要绑定这个服务首先要创建一个显式意图,指定想要绑定的服务。然后使用活动的bindService方法绑定服务,传入这个意图,服务定义的ServiceConnection对象以及描述希望如何绑定的一个标志。

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

3、与服务交互

调用OdometerService的getDistance方法
一旦活动绑定到服务,我们要每秒调用一次OdometerService的getDistance方法,并将其值更新MainActivity的文本视图。
为MainActivity增加一个displayDistance方法:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        displayDistance();
    }
    
   private void displayDistance() {
        final TextView distanceView = (TextView) findViewById(R.id.distance);
        final Handler handler = new Handler();
        handler.post(new Runnable() {
            @Override
            public void run() {
                double distance = 0.0;
                //如果得到OdometerService的一个引用,而且绑定到这个服务,则调用getDistance。
                if (bound && odometer != null)distance = odometer.getDistance();
                String distanceStr = String.format(Locale.getDefault(), "%1$,.2f miles", distance);
                distanceView.setText(distanceStr);
                //每秒运行一次
                handler.postDelayed(this, 1000);
            }
        });
    }

4、完成时与服务接触绑定

使用unbindService与服务解除绑定

将活动与服务解除绑定时,通常会把相应的代码增加到活动的onStop或onDestroy方法中。使用哪一个方法取决于你的bindService代码放在哪里:
如果在活动的onStart方法中绑定服务,则在onStop方法中解除绑定。
如果在onCreate方法中绑定服务,则在onDestroy方法中解除绑定。
所以这里在onStop方法与服务解除绑定。这个方法有一个参数,即ServiceConnection对象。需要向MainActivity增加以下代码:

    protected void onStop() {
        super.onStop();
        if (bound) {
            unbindService(connection);
            bound = false;
        }
    }

试一试应用

运行这个应用时会在MainActivity显示一个随机数,这个数每秒改变一次。
在这里插入图片描述

安卓绑定式服务的生命周期

1、服务创建
2、onCreate(): 当服务第一次被创建时执行。这个方法可以在服务创建时进行一些初始化操作。
3、onBind(): 当其他组件通过调用bindService()方法与服务绑定时执行。在这个方法中,服务会返回一个IBinder接口实例,客户端可以通过这个接口与服务进行通信。
4、服务绑定
5、onUnbind(): 当其他组件通过调用unbindService()方法与服务解绑时执行。在这个方法中,服务可以执行一些清理操作,例如停止在后台运行的任务等。
6、onDestroy(): 当服务不再被使用或被销毁时执行。注意,如果服务同时被启动和绑定,那么即使所有的客户端都解绑了服务,服务也不会被销毁,除非服务用stopSelf()方法或其他组件调用stopService()方法来终止自己。
7、服务撤销

总的来说,绑定式服务的生命周期与启动式服务的生命周期略有不同,主要区别在于绑定式服务需要与其他组件进行绑定和解绑操作,并且服务的生命周期会受到这些操作的影响。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1083072.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PDF编辑软件哪个好用?PDF文档怎么编辑修改内容

在生活中&#xff0c;为了方便文件传输&#xff0c;会将文件扫描或转换成PDF格式&#xff0c;但是如果需要编辑修改会比较麻烦&#xff0c;这时一款好用的PDF编辑器显得十分重要。今天就带大家了解下PDF编辑软件哪个好用&#xff0c;PDF文档怎么编辑修改内容。 一、PDF编辑软件…

【Android 从入门到出门】第一章:Android开发技能入门指南

&#x1f935;‍♂️ 个人主页&#xff1a;艾迦洼的个人主页 ✍&#x1f3fb;作者简介&#xff1a;后端程序猿 &#x1f604; 希望大家多多支持&#xff0c;如果文章对你有帮助的话&#xff0c;欢迎 &#x1f4ac;&#x1f44d;&#x1f3fb;&#x1f4c2; 目录 &#x1f44b;第…

C#(Csharp)我的基础教程(三)(我的菜鸟教程笔记)-控件对象与窗体容器集合(Control)的探究与学习

目录 1、窗体类&#xff08;主代码文件窗体设计器后台代码文件&#xff09;2、控件对象与窗体容器集合&#xff08;Control&#xff09; 1、窗体类&#xff08;主代码文件窗体设计器后台代码文件&#xff09; 主窗体对象的创建&#xff1a;在Program类里面&#xff1a; Appli…

Windows操作系统登录双因素认证解决方案 安当加密

实现Windows操作系统登录双因素认证&#xff0c;可以通过安当ASP身份认证平台进行设置。安当ASP身份认证平台提供了多种双因素认证方式&#xff0c;包括USB Key ID、OTP&#xff08;动态口令&#xff09;等&#xff0c;可以灵活选择和配置。 以下是使用安当ASP身份认证平台的US…

2023 家电行业品牌社媒营销洞察报告

过去三年的疫情&#xff0c;给人们的生活和消费方式都带来了极大的改变。直播电商、社交电商的兴起&#xff0c;也带动了传统线下家电零售商向线上渠道发展&#xff0c;传统大家电“重获新生”&#xff0c;新兴小家电“冉冉升起”&#xff0c;成为了业绩增长的新引擎。 2023年&…

c++视觉处理---拉普拉斯金字塔和高斯金字塔

拉普拉斯金字塔和高斯金字塔 拉普拉斯金字塔&#xff08;Laplacian Pyramid&#xff09;和高斯金字塔&#xff08;Gaussian Pyramid&#xff09;是两种不同类型的图像金字塔&#xff0c;用于多尺度图像处理和特征提取。它们之间的主要区别在于它们所包含的信息和用途&#xff…

ROS仿真软件Turtlebot-Gazebo的安装使用以及错误处理[机器人避障]

很多时候由于机器人价格比较贵&#xff0c;而且会因为环境因素、操作失误或者摔坏等&#xff0c;所以我们可以先在仿真软件上做测试&#xff0c;也可以避免这些问题&#xff0c;虽然没有那么真实感&#xff0c;可毕竟是免费的嘛。我们可以在这些仿真的机器人身上去学习如何控制…

格式化硬盘时提示“此驱动器正在使用”解决占用问题

Windows 11 或 Windows 10 的大多数问题都有一个很好的解决方案——格式化系统驱动器并重新安装 Windows。或者有时&#xff0c;我们可能只想擦除数据驱动器上的所有文件和文件夹&#xff0c;例如。D 盘、E 盘等。为此&#xff0c;我们只需右键单击 Windows 文件资源管理器的 P…

深度学习batch、batch_size、epoch、iteration以及小样本中episode、support set、query set关系

batch、batch_size、epoch、iteration关系&#xff1a; epoch&#xff1a;整个数据集 batch&#xff1a; 整个数据集分成多少小块进行训练 batch_size&#xff1a; 一次训练&#xff08;1 batch&#xff09;需要 batch_size个样本 iteration&#xff1a; 整个数据集需要用b…

深度学习简述

⭐️⭐️⭐️⭐️⭐️欢迎来到我的博客⭐️⭐️⭐️⭐️⭐️ &#x1f434;作者&#xff1a;秋无之地 &#x1f434;简介&#xff1a;CSDN爬虫、后端、大数据领域创作者。目前从事python爬虫、后端和大数据等相关工作&#xff0c;主要擅长领域有&#xff1a;爬虫、后端、大数据…

MT8390(Genio 700)安卓核心板参数_联发科MTK智能模组

MT8390安卓核心板是一款功能强大且高度集成的平台&#xff0c;专为广泛的人工智能(AI)和物联网(IoT)应用案例而设计。它具备高性能边缘处理、先进的多媒体和连接能力、多个高分辨率摄像头、连接的触摸屏显示以及多任务高级操作系统的使用。 MT8390安卓核心板采用了高性能的八核…

保护互联网数据安全:关键方法与最佳实践

在当今数字化时代&#xff0c;互联网数据安全已经成为个人、企业和组织的首要任务之一。随着信息技术的迅猛发展&#xff0c;网络威胁也不断演进&#xff0c;因此保护互联网数据安全变得尤为关键。本文将介绍一些关键方法和最佳实践&#xff0c;帮助您确保互联网数据的安全性。…

从零学算法(LCR 187. 破冰游戏)

社团共有 num 为成员参与破冰游戏&#xff0c;编号为 0 ~ num-1。成员们按照编号顺序围绕圆桌而坐。社长抽取一个数字 target&#xff0c;从 0 号成员起开始计数&#xff0c;排在第 target 位的成员离开圆桌&#xff0c;且成员离开后从下一个成员开始计数。请返回游戏结束时最后…

第五节 C++ 循环结构(算法)

文章目录 前言介绍1. for 语句1.1 语法结构1.2 语法流程的执行过程1.2.1 案例 1:循环的正序输入和倒序输入1.2.2 案例2 : 求1~n的平方数1.2.3 案例 3: 求输入a和b,求a~b区间数. 1.3 for 循环案例练习1.3.1 求最大值与最小值1.3.2 计算奇数和和偶数和1.3.3 计算平均气温与最高气…

day03_if_循环

今日内容 1.if.elseif 2.循环 3.控制关键词 复习 一 运算符算术,赋值,关系,逻辑,三目!,非,取反的作用boolean r !true; //falseboolean r2 !(1 > 0);// false 二 键盘录入1) 导包 import java.util.Scanner;2) 创建扫描器 Scanner scanner new Scanner(System.in);3) 调…

3.5 高速以太网

思维导图&#xff1a; 3.5.1 100BASE-T以太网 **3.5 高速以太网** 随着技术进步&#xff0c;以太网的传输速度不断增加。从早期的10 Mbit/s的速度&#xff0c;增长到了1 Gbit/s甚至更快。以下是一些关于高速以太网技术的简介。 **3.5.1 100BASE-T以太网** - **定义**&#…

信息系统项目管理师第四版学习笔记——项目沟通管理

管理基础 沟通模型的关键要素包括&#xff1a;编码、信息和反馈信息、媒介、噪声、解码。 在编制书面或口头信息的时候&#xff0c;应使用书面沟通的5C原则&#xff0c;以减轻理解错误&#xff1a;正确的语法和拼写(Correctness)、简洁的表述(Concise)、清晰的目的和表述(Cla…

传统工厂如何搭建蒸汽流量远程无线抄表系统?

一、应用背景 2021年国务院政府工作报告中指出&#xff0c;扎实做好碳达峰、碳中和各项工作&#xff0c;制定2030年前碳排放达峰行动方案&#xff0c;优化产业结构和能源结构&#xff0c;特别是近期煤炭价格上涨导致蒸汽价格大幅上涨&#xff0c;节能减排显得更加重要&#xf…

深度学习之微调

在现代深度学习领域&#xff0c;精细调整&#xff08;Fine-tune&#xff09;已经成为一种非常重要的技术手段。 预训练模型 在介绍finetune之前&#xff0c;先了解一下什么是预训练模型。在搭建一个网络模型来完成一个特定的图像分类的任务时&#xff0c;首先&#xff0c;需要…

ad5665r STM32 GD32 IIC驱动设计

本文涉及文档工程代码&#xff0c;下载地址如下 ad5665rSTM32GD32IIC驱动设计,驱动程序在AD公司提供例程上修改得到,IO模拟的方式进行IIC通信资源-CSDN文库 硬件设计 MCU采用STM32或者GD32,GD32基本上和STM32一样,针对ad566r的IIC时序操作是完全相同的. 原理图设计如下 与MC…