Android Studio App开发之服务Service的讲解及实战(包括启动和停止,绑定与解绑,推送服务到前台实现音乐播放器,附源码)

简介: Android Studio App开发之服务Service的讲解及实战(包括启动和停止,绑定与解绑,推送服务到前台实现音乐播放器,附源码)

运行有问题或需要源码请点赞关注收藏后评论区留言~~~

一、服务的启动和停止

服务Service是Android的四大组件之一,它常用于页面的高级场合,这些系统服务平时几乎感觉不到它们的存在,却是系统不可或缺的重要组成部分。

既然Android自带了系统服务,App也可以拥有自己的服务,服务Service与活动Activity相比,不同之处在于没有对应的页面,相同之处在于都有生命周期 常用方法如下

1:onCreate 创建服务

2:onStart  开始服务

3:onStartCommand  开始服务

4:onDestroy 销毁服务

5:onBind 绑定服务

6:onUnbind 解除绑定

7:onRebind 重新绑定

点击启动服务和停止服务会调用相对应得方法  效果如下

代码如下

Java类

package com.example.chapter11;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import com.example.chapter11.service.NormalService;
import com.example.chapter11.util.DateUtil;
@SuppressLint("StaticFieldLeak")
public class ServiceNormalActivity extends AppCompatActivity implements View.OnClickListener {
    private static TextView tv_normal;
    private Intent mIntent; // 声明一个意图对象
    private static String mDesc;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_service_normal);
        tv_normal = findViewById(R.id.tv_normal);
        findViewById(R.id.btn_start).setOnClickListener(this);
        findViewById(R.id.btn_stop).setOnClickListener(this);
        mDesc = "";
        // 创建一个通往普通服务的意图
        mIntent = new Intent(this, NormalService.class);
    }
    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.btn_start) { // 点击了启动服务按钮
            startService(mIntent); // 启动指定意图的服务
        } else if (v.getId() == R.id.btn_stop) { // 点击了停止服务按钮
            stopService(mIntent); // 停止指定意图的服务
        }
    }
    public static void showText(String desc) {
        if (tv_normal != null) {
            mDesc = String.format("%s%s %s\n", mDesc, DateUtil.getNowDateTime("HH:mm:ss"), desc);
            tv_normal.setText(mDesc);
        }
    }
}

XML文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >
        <Button
            android:id="@+id/btn_start"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center"
            android:text="启动服务"
            android:textColor="@color/black"
            android:textSize="17sp" />
        <Button
            android:id="@+id/btn_stop"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center"
            android:text="停止服务"
            android:textColor="@color/black"
            android:textSize="17sp" />
    </LinearLayout>
    <TextView
        android:id="@+id/tv_normal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingLeft="5dp"
        android:textColor="@color/black"
        android:textSize="17sp" />
</LinearLayout>

二、服务的绑定与解绑

服务启停除了上一小节介绍的普通方式,也就是绑定服务和解绑服务。对于服务来说,便要求提供粘合剂Binder指定服务的绑定关系,同时黏合剂指定服务的绑定关系,同时黏合剂还负责在两个组件或者在两个进程之间交流通信。效果如下

延迟绑定与立即绑定的生命周期区别在于

1:延迟绑定的首次绑定操作只触发onBind方法,再次绑定操作只触发onRebind方法

2:延迟绑定的解绑操作只触发onUnbind方法

代码如下

Java类

package com.example.chapter11;
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.TextView;
import androidx.appcompat.app.AppCompatActivity;
import com.example.chapter11.service.BindDelayService;
import com.example.chapter11.util.DateUtil;
public class BindDelayActivity extends AppCompatActivity implements View.OnClickListener {
    private static final String TAG = "BindDelayActivity";
    private static TextView tv_delay;
    private Intent mIntent; // 声明一个意图对象
    private static String mDesc;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_bind_delay);
        tv_delay = findViewById(R.id.tv_delay);
        findViewById(R.id.btn_start).setOnClickListener(this);
        findViewById(R.id.btn_bind).setOnClickListener(this);
        findViewById(R.id.btn_unbind).setOnClickListener(this);
        findViewById(R.id.btn_stop).setOnClickListener(this);
        mDesc = "";
        // 创建一个通往延迟绑定服务的意图
        mIntent = new Intent(this, BindDelayService.class);
    }
    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.btn_start) { // 点击了开始服务按钮
            startService(mIntent); // 启动服务
        } else if (v.getId() == R.id.btn_bind) { // 点击了绑定服务按钮
            boolean bindFlag = bindService(mIntent, mFirstConn, Context.BIND_AUTO_CREATE); // 绑定服务
            Log.d(TAG, "bindFlag=" + bindFlag);
        } else if (v.getId() == R.id.btn_unbind) { // 点击了解绑服务按钮
            if (mBindService != null) {
                unbindService(mFirstConn); // 解绑服务
                mBindService = null;
            }
        } else if (v.getId() == R.id.btn_stop) { // 点击了停止服务按钮
            stopService(mIntent); // 停止服务
        }
    }
    public static void showText(String desc) {
        if (tv_delay != null) {
            mDesc = String.format("%s%s %s\n", mDesc, DateUtil.getNowDateTime("HH:mm:ss"), desc);
            tv_delay.setText(mDesc);
        }
    }
    private BindDelayService mBindService; // 声明一个服务对象
    private ServiceConnection mFirstConn = new ServiceConnection() {
        // 获取服务对象时的操作
        public void onServiceConnected(ComponentName name, IBinder service) {
            // 如果服务运行于另外一个进程,则不能直接强制转换类型,否则会报错
            mBindService = ((BindDelayService.LocalBinder) service).getService();
            Log.d(TAG, "onServiceConnected");
        }
        // 无法获取到服务对象时的操作
        public void onServiceDisconnected(ComponentName name) {
            mBindService = null;
            Log.d(TAG, "onServiceDisconnected");
        }
    };
}

XML文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >
        <Button
            android:id="@+id/btn_start"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center"
            android:text="启动服务"
            android:textColor="@color/black"
            android:textSize="15sp" />
        <Button
            android:id="@+id/btn_bind"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center"
            android:text="绑定服务"
            android:textColor="@color/black"
            android:textSize="15sp" />
        <Button
            android:id="@+id/btn_unbind"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center"
            android:text="解绑服务"
            android:textColor="@color/black"
            android:textSize="15sp" />
        <Button
            android:id="@+id/btn_stop"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center"
            android:text="停止服务"
            android:textColor="@color/black"
            android:textSize="15sp" />
    </LinearLayout>
    <TextView
        android:id="@+id/tv_delay"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingLeft="5dp"
        android:textColor="@color/black"
        android:textSize="17sp" />
</LinearLayout>

三、推送服务到前台

服务没有自己的布局文件,意味着无法直接在页面上展示服务信息,要想了解服务的运行情况,要么通过打印日志观察,要么通过某个页面的静态控件显示运行结果,然而活动页面有自身的生命周期,为此Android设计了一个让服务在前台运行的机制,也就是在手机的通知栏展示服务的画像,同时允许自己是否需要在通知栏显示 包括下面两个方法

1:startForeground 把当前服务切换到前台运行 即展示到通知栏

2:stopForeground 停止前台运行 即取消通知栏上的展示

效果如下 连接了真机后会在 后台显示

代码如下

Java类

package com.example.chapter11;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.example.chapter11.service.MusicService;
import com.example.chapter11.util.ViewUtil;
public class ForegroundServiceActivity extends AppCompatActivity implements View.OnClickListener {
    private EditText et_song;
    private Button btn_send_service;
    private boolean isPlaying = true; // 是否正在播放
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_foreground_service);
        et_song = findViewById(R.id.et_song);
        btn_send_service = findViewById(R.id.btn_send_service);
        btn_send_service.setOnClickListener(this);
    }
    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.btn_send_service) {
            if (TextUtils.isEmpty(et_song.getText())) {
                Toast.makeText(this, "请填写歌曲名称", Toast.LENGTH_SHORT).show();
                return;
            }
            // 创建一个通往音乐服务的意图
            Intent intent = new Intent(this, MusicService.class);
            intent.putExtra("is_play", isPlaying); // 是否正在播放音乐
            intent.putExtra("song", et_song.getText().toString());
            btn_send_service.setText(isPlaying?"暂停播放音乐":"开始播放音乐");
            startService(intent); // 启动音乐播放服务
            isPlaying = !isPlaying;
        }
    }
}

XML文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="5dp" >
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:orientation="horizontal">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:gravity="center"
            android:text="歌曲名称:"
            android:textColor="@color/black"
            android:textSize="17sp" />
        <EditText
            android:id="@+id/et_song"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:layout_margin="5dp"
            android:background="@drawable/editext_selector"
            android:hint="请填写歌曲名称"
            android:textColor="@color/black"
            android:textSize="17sp" />
    </LinearLayout>
    <Button
        android:id="@+id/btn_send_service"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="开始播放音乐"
        android:textColor="#000000"
        android:textSize="17sp" />
</LinearLayout>

创作不易 觉得有帮助请点赞关注收藏~~~

相关文章
|
18天前
|
移动开发 开发框架 小程序
轻松搭建婚恋交友系统源码,H5/小程序/APP自动适配,智能匹配恋爱交友平台快速落地
婚恋交友系统涵盖在线交友、线下活动、专业服务、社交娱乐等,满足用户多样化需求。系统设计简洁易用,提供实名认证、多注册方式及安全保护,确保用户隐私和数据安全。功能丰富,支持图文展示、筛选匹配、聊天互动、虚拟礼物等,提升互动趣味性。平台可分类管理用户、审核信息、智能推荐,优化用户体验。基于TP6+Uni-app框架,实现跨平台同步,支持二次开发,适应不同市场需求。 [了解更多](https://gitee.com/multi-customer-software/jy)
|
17天前
|
小程序 IDE PHP
圈子源码如何打包生成App小程序/开发一个圈子系统软件所需要的费用体现在哪里?
将PHP源码打包成App的过程涉及多个步骤和技术选择。以圈子源码为例,首先明确需求,确定App功能和目标用户群体,并根据需求开发小程序页面,如用户注册、圈子列表等。源码准备阶段确保源码适用于小程序开发,环境配置需安装IDE(如微信开发者工具)及依赖库。最后在IDE中打包小程序并上传至管理平台,通过审核后发布。费用方面,模板开发成本较低,定制开发则更高,具体取决于需求复杂度和第三方服务费用。
50 0
|
2月前
|
开发框架 小程序 前端开发
圈子社交app前端+后端源码,uniapp社交兴趣圈子开发,框架php圈子小程序安装搭建
本文介绍了圈子社交APP的源码获取、分析与定制,PHP实现的圈子框架设计及代码编写,以及圈子小程序的安装搭建。涵盖环境配置、数据库设计、前后端开发与接口对接等内容,确保平台的安全性、性能和功能完整性。通过详细指导,帮助开发者快速搭建稳定可靠的圈子社交平台。
|
2月前
|
PHP
全新uniapp小说漫画APP小说源码/会员阅读/月票功能
价值980的uniapp小说漫画APP小说源码/会员阅读/月票功能
113 20
|
2月前
|
JSON 缓存 前端开发
HarmonyOS NEXT 5.0鸿蒙开发一套影院APP(附带源码)
本项目基于HarmonyOS NEXT 5.0开发了一款影院应用程序,主要实现了电影和影院信息的展示功能。应用包括首页、电影列表、影院列表等模块。首页包含轮播图与正在热映及即将上映的电影切换显示;电影列表模块通过API获取电影数据并以网格形式展示,用户可以查看电影详情;影院列表则允许用户选择城市后查看对应影院信息,并支持城市选择弹窗。此外,项目中还集成了Axios用于网络请求,并进行了二次封装以简化接口调用流程,同时添加了请求和响应拦截器来处理通用逻辑。整体代码结构清晰,使用了组件化开发方式,便于维护和扩展。 该简介概括了提供的内容,但请注意实际开发中还需考虑UI优化、性能提升等方面的工作。
102 11
|
15天前
|
移动开发 小程序
thinkphp+uniapp开发的多端商城系统源码/H5/小程序/APP支持DIY模板直播分销
thinkphp+uniapp开发的多端商城系统源码/H5/小程序/APP支持DIY模板直播分销
14 0
|
2月前
|
机器学习/深度学习 前端开发 算法
婚恋交友系统平台 相亲交友平台系统 婚恋交友系统APP 婚恋系统源码 婚恋交友平台开发流程 婚恋交友系统架构设计 婚恋交友系统前端/后端开发 婚恋交友系统匹配推荐算法优化
婚恋交友系统平台通过线上互动帮助单身男女找到合适伴侣,提供用户注册、个人资料填写、匹配推荐、实时聊天、社区互动等功能。开发流程包括需求分析、技术选型、系统架构设计、功能实现、测试优化和上线运维。匹配推荐算法优化是核心,通过用户行为数据分析和机器学习提高匹配准确性。
136 3
|
2月前
|
前端开发 搜索推荐 PHP
大开眼界!uniapp秀操作,陪玩系统新功能,陪玩app源码,可实时互动随心优化!
多客游戏陪玩系统采用前端uniapp与PHP语言,实现全开源、易改造,RTC传输协议确保低延迟语音连麦,分布式部署应对高并发。功能创新包括游戏约单、多人语音聊天室、动态广场、私信聊天等,提供高端社交和个性化服务,满足各类需求,让玩家畅享游戏乐趣。
|
2月前
|
小程序 安全 网络安全
清晰易懂!陪玩系统源码搭建的核心功能,陪玩小程序、陪玩app的搭建步骤!
陪玩系统源码包含多种约单方式、实时语音互动、直播间与聊天室、大神申请与抢单、动态互动与社交及在线支付与评价等核心功能。搭建步骤包括环境准备、源码上传与解压、数据库配置、域名与SSL证书绑定、伪静态配置及后台管理。注意事项涵盖源码安全性、二次开发、合规性和技术支持。确保平台安全、合规并提供良好用户体验是关键。
|
3月前
|
移动开发 小程序
仿青藤之恋社交交友软件系统源码 即时通讯 聊天 微信小程序 App H5三端通用
仿青藤之恋社交交友软件系统源码 即时通讯 聊天 微信小程序 App H5三端通用
114 3

热门文章

最新文章

  • 1
    DeepSeek Artifacts:在线实时预览的前端 AI 编程工具,基于DeepSeek V3快速生成React App
  • 2
    圈子社交app前端+后端源码,uniapp社交兴趣圈子开发,框架php圈子小程序安装搭建
  • 3
    【05】2025年1月首发完整版-篇幅较长-苹果app如何上架到app store完整流程·不借助第三方上架工具的情况下无需花钱但需仔细学习-优雅草央千澈详解关于APP签名以及分发-们最关心的一篇来了-IOS上架app
  • 4
    【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
  • 5
    电竞陪玩系统架构优化设计,陪玩app如何提升系统稳定性,陪玩小程序平台的测试与监控
  • 6
    京东商品详情数据接口(H5、APP 端)
  • 7
    年轻人如何运用圈子系统进行扩列,社交圈子论坛app扩列的好处,兴趣行业圈子提升社交技能
  • 8
    【Azure App Service】对App Service中CPU指标数据中系统占用部分(System CPU)的解释
  • 9
    【Azure Logic App】使用MySQL 新增行触发器遇见错误 :“Unknown column 'created_at' in 'order clause'”
  • 10
    【01】vs-code如何配置flutter环境-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈-供大大的学习提升